From 220a6001c6658efc6d387d333f1defdaa86d4993 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Sun, 19 May 2019 13:55:18 +0200 Subject: [PATCH 001/117] events: add captureRejection option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/27867 Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell Reviewed-By: Jeremiah Senkpiel Reviewed-By: Anna Henningsen Reviewed-By: Michaël Zasso --- doc/api/events.md | 125 ++++++++ lib/events.js | 112 ++++++- .../parallel/test-event-capture-rejections.js | 297 ++++++++++++++++++ 3 files changed, 528 insertions(+), 6 deletions(-) create mode 100644 test/parallel/test-event-capture-rejections.js diff --git a/doc/api/events.md b/doc/api/events.md index ec6f608609073f..3a558ec233f06b 100644 --- a/doc/api/events.md +++ b/doc/api/events.md @@ -155,9 +155,66 @@ myEmitter.emit('error', new Error('whoops!')); // Prints: whoops! there was an error ``` +## Capture Rejections of Promises + +> Stability: 1 - captureRejections is experimental. + +Using `async` functions with event handlers is problematic, because it +can lead to an unhandled rejection in case of a thrown exception: + +```js +const ee = new EventEmitter(); +ee.on('something', async (value) => { + throw new Error('kaboom'); +}); +``` + +The `captureRejections` option in the `EventEmitter` constructor or the global +setting change this behavior, installing a `.then(undefined, handler)` +handler on the `Promise`. This handler routes the exception +asynchronously to the [`Symbol.for('nodejs.rejection')`][rejection] method +if there is one, or to [`'error'`][error] event handler if there is none. + +```js +const ee1 = new EventEmitter({ captureRejections: true }); +ee1.on('something', async (value) => { + throw new Error('kaboom'); +}); + +ee1.on('error', console.log); + +const ee2 = new EventEmitter({ captureRejections: true }); +ee2.on('something', async (value) => { + throw new Error('kaboom'); +}); + +ee2[Symbol.for('nodejs.rejection')] = console.log; +``` + +Setting `EventEmitter.captureRejections = true` will change the default for all +new instances of `EventEmitter`. + +```js +EventEmitter.captureRejections = true; +const ee1 = new EventEmitter(); +ee1.on('something', async (value) => { + throw new Error('kaboom'); +}); + +ee1.on('error', console.log); +``` + +The `'error'` events that are generated by the `captureRejections` behavior +do not have a catch handler to avoid infinite error loops: the +recommendation is to **not use `async` functions as `'error'` event handlers**. + ## Class: EventEmitter The `EventEmitter` class is defined and exposed by the `events` module: @@ -169,6 +226,12 @@ const EventEmitter = require('events'); All `EventEmitter`s emit the event `'newListener'` when new listeners are added and `'removeListener'` when existing listeners are removed. +It supports the following option: + +* `captureRejections` {boolean} It enables + [automatic capturing of promise rejection][capturerejections]. + Default: `false`. + ### Event: 'newListener' + +> Stability: 1 - captureRejections is experimental. + +* `err` Error +* `eventName` {string|symbol} +* `...args` {any} + +The `Symbol.for('nodejs.rejection')` method is called in case a +promise rejection happens when emitting an event and +[`captureRejections`][capturerejections] is enabled on the emitter. +It is possible to use [`events.captureRejectionSymbol`][rejectionsymbol] in +place of `Symbol.for('nodejs.rejection')`. + +```js +const { EventEmitter, captureRejectionSymbol } = require('events'); + +class MyClass extends EventEmitter { + constructor() { + super({ captureRejections: true }); + } + + [captureRejectionSymbol](err, event, ...args) { + console.log('rejection happened for', event, 'with', err, ...args); + this.destroy(err); + } + + destroy(err) { + // Tear the resource down here. + } +} +``` + ## events.once(emitter, name) + +> Stability: 1 - captureRejections is experimental. + +Value: {boolean} + +Change the default `captureRejections` option on all new `EventEmitter` objects. + +## events.captureRejectionSymbol + + +> Stability: 1 - captureRejections is experimental. + +Value: `Symbol.for('nodejs.rejection')` + +See how to write a custom [rejection handler][rejection]. + [WHATWG-EventTarget]: https://dom.spec.whatwg.org/#interface-eventtarget [`--trace-warnings`]: cli.html#cli_trace_warnings [`EventEmitter.defaultMaxListeners`]: #events_eventemitter_defaultmaxlisteners @@ -751,3 +872,7 @@ run(); [`net.Server`]: net.html#net_class_net_server [`process.on('warning')`]: process.html#process_event_warning [stream]: stream.html +[capturerejections]: #events_capture_rejections_of_promises +[rejection]: #events_emitter_symbol_for_nodejs_rejection_err_eventname_args +[rejectionsymbol]: #events_events_capturerejectionsymbol +[error]: #events_error_events diff --git a/lib/events.js b/lib/events.js index a09333af443534..ce93cd9f9bfd3e 100644 --- a/lib/events.js +++ b/lib/events.js @@ -23,6 +23,7 @@ const { Array, + Boolean, MathMin, NumberIsNaN, ObjectCreate, @@ -32,6 +33,7 @@ const { ReflectApply, ReflectOwnKeys, } = primordials; +const kRejection = Symbol.for('nodejs.rejection'); let spliceOne; @@ -49,8 +51,10 @@ const { inspect } = require('internal/util/inspect'); -function EventEmitter() { - EventEmitter.init.call(this); +const kCapture = Symbol('kCapture'); + +function EventEmitter(opts) { + EventEmitter.init.call(this, opts); } module.exports = EventEmitter; module.exports.once = once; @@ -60,6 +64,29 @@ EventEmitter.EventEmitter = EventEmitter; EventEmitter.usingDomains = false; +EventEmitter.captureRejectionSymbol = kRejection; +ObjectDefineProperty(EventEmitter, 'captureRejections', { + get() { + return EventEmitter.prototype[kCapture]; + }, + set(value) { + if (typeof value !== 'boolean') { + throw new ERR_INVALID_ARG_TYPE('EventEmitter.captureRejections', + 'boolean', value); + } + + EventEmitter.prototype[kCapture] = value; + }, + enumerable: true +}); + +// The default for captureRejections is false +ObjectDefineProperty(EventEmitter.prototype, kCapture, { + value: false, + writable: true, + enumerable: false +}); + EventEmitter.prototype._events = undefined; EventEmitter.prototype._eventsCount = 0; EventEmitter.prototype._maxListeners = undefined; @@ -89,7 +116,7 @@ ObjectDefineProperty(EventEmitter, 'defaultMaxListeners', { } }); -EventEmitter.init = function() { +EventEmitter.init = function(opts) { if (this._events === undefined || this._events === ObjectGetPrototypeOf(this)._events) { @@ -98,8 +125,64 @@ EventEmitter.init = function() { } this._maxListeners = this._maxListeners || undefined; + + + if (opts && opts.captureRejections) { + if (typeof opts.captureRejections !== 'boolean') { + throw new ERR_INVALID_ARG_TYPE('options.captureRejections', + 'boolean', opts.captureRejections); + } + this[kCapture] = Boolean(opts.captureRejections); + } else { + // Assigning it directly a prototype lookup, as it slighly expensive + // and it sits in a very sensitive hot path. + this[kCapture] = EventEmitter.prototype[kCapture]; + } }; +function addCatch(that, promise, type, args) { + if (!that[kCapture]) { + return; + } + + // Handle Promises/A+ spec, then could be a getter + // that throws on second use. + try { + const then = promise.then; + + if (typeof then === 'function') { + then.call(promise, undefined, function(err) { + // The callback is called with nextTick to avoid a follow-up + // rejection from this promise. + process.nextTick(emitUnhandledRejectionOrErr, that, err, type, args); + }); + } + } catch (err) { + that.emit('error', err); + } +} + +function emitUnhandledRejectionOrErr(ee, err, type, args) { + if (typeof ee[kRejection] === 'function') { + ee[kRejection](err, type, ...args); + } else { + // We have to disable the capture rejections mechanism, otherwise + // we might end up in an infinite loop. + const prev = ee[kCapture]; + + // If the error handler throws, it is not catcheable and it + // will end up in 'uncaughtException'. We restore the previous + // value of kCapture in case the uncaughtException is present + // and the exception is handled. + try { + ee[kCapture] = false; + ee.emit('error', err); + } finally { + ee[kCapture] = prev; + } + } +} + // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { @@ -216,12 +299,29 @@ EventEmitter.prototype.emit = function emit(type, ...args) { return false; if (typeof handler === 'function') { - ReflectApply(handler, this, args); + const result = ReflectApply(handler, this, args); + + // We check if result is undefined first because that + // is the most common case so we do not pay any perf + // penalty + if (result !== undefined && result !== null) { + addCatch(this, result, type, args); + } } else { const len = handler.length; const listeners = arrayClone(handler, len); - for (let i = 0; i < len; ++i) - ReflectApply(listeners[i], this, args); + for (var i = 0; i < len; ++i) { + const result = ReflectApply(listeners[i], this, args); + + // We check if result is undefined first because that + // is the most common case so we do not pay any perf + // penalty. + // This code is duplicated because extracting it away + // would make it non-inlineable. + if (result !== undefined && result !== null) { + addCatch(this, result, type, args); + } + } } return true; diff --git a/test/parallel/test-event-capture-rejections.js b/test/parallel/test-event-capture-rejections.js new file mode 100644 index 00000000000000..83da3184a67116 --- /dev/null +++ b/test/parallel/test-event-capture-rejections.js @@ -0,0 +1,297 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const { EventEmitter, captureRejectionSymbol } = require('events'); +const { inherits } = require('util'); + +// Inherits from EE without a call to the +// parent constructor. +function NoConstructor() { +} + +inherits(NoConstructor, EventEmitter); + +function captureRejections() { + const ee = new EventEmitter({ captureRejections: true }); + const _err = new Error('kaboom'); + ee.on('something', common.mustCall(async (value) => { + throw _err; + })); + + ee.on('error', common.mustCall((err) => { + assert.strictEqual(err, _err); + process.nextTick(captureRejectionsTwoHandlers); + })); + + ee.emit('something'); +} + +function captureRejectionsTwoHandlers() { + const ee = new EventEmitter({ captureRejections: true }); + const _err = new Error('kaboom'); + + ee.on('something', common.mustCall(async (value) => { + throw _err; + })); + + // throw twice + ee.on('something', common.mustCall(async (value) => { + throw _err; + })); + + let count = 0; + + ee.on('error', common.mustCall((err) => { + assert.strictEqual(err, _err); + if (++count === 2) { + process.nextTick(defaultValue); + } + }, 2)); + + ee.emit('something'); +} + +function defaultValue() { + const ee = new EventEmitter(); + const _err = new Error('kaboom'); + ee.on('something', common.mustCall(async (value) => { + throw _err; + })); + + process.removeAllListeners('unhandledRejection'); + + process.once('unhandledRejection', common.mustCall((err) => { + // restore default + process.on('unhandledRejection', (err) => { throw err; }); + + assert.strictEqual(err, _err); + process.nextTick(globalSetting); + })); + + ee.emit('something'); +} + +function globalSetting() { + assert.strictEqual(EventEmitter.captureRejections, false); + EventEmitter.captureRejections = true; + const ee = new EventEmitter(); + const _err = new Error('kaboom'); + ee.on('something', common.mustCall(async (value) => { + throw _err; + })); + + ee.on('error', common.mustCall((err) => { + assert.strictEqual(err, _err); + + // restore default + EventEmitter.captureRejections = false; + process.nextTick(configurable); + })); + + ee.emit('something'); +} + +// We need to be able to configure this for streams, as we would +// like to call destro(err) there. +function configurable() { + const ee = new EventEmitter({ captureRejections: true }); + const _err = new Error('kaboom'); + ee.on('something', common.mustCall(async (...args) => { + assert.deepStrictEqual(args, [42, 'foobar']); + throw _err; + })); + + assert.strictEqual(captureRejectionSymbol, Symbol.for('nodejs.rejection')); + + ee[captureRejectionSymbol] = common.mustCall((err, type, ...args) => { + assert.strictEqual(err, _err); + assert.strictEqual(type, 'something'); + assert.deepStrictEqual(args, [42, 'foobar']); + process.nextTick(globalSettingNoConstructor); + }); + + ee.emit('something', 42, 'foobar'); +} + +function globalSettingNoConstructor() { + assert.strictEqual(EventEmitter.captureRejections, false); + EventEmitter.captureRejections = true; + const ee = new NoConstructor(); + const _err = new Error('kaboom'); + ee.on('something', common.mustCall(async (value) => { + throw _err; + })); + + ee.on('error', common.mustCall((err) => { + assert.strictEqual(err, _err); + + // restore default + EventEmitter.captureRejections = false; + process.nextTick(thenable); + })); + + ee.emit('something'); +} + +function thenable() { + const ee = new EventEmitter({ captureRejections: true }); + const _err = new Error('kaboom'); + ee.on('something', common.mustCall((value) => { + const obj = {}; + + Object.defineProperty(obj, 'then', { + get: common.mustCall(() => { + return common.mustCall((resolved, rejected) => { + assert.strictEqual(resolved, undefined); + rejected(_err); + }); + }, 1) // Only 1 call for Promises/A+ compat. + }); + + return obj; + })); + + ee.on('error', common.mustCall((err) => { + assert.strictEqual(err, _err); + process.nextTick(avoidLoopOnRejection); + })); + + ee.emit('something'); +} + +function avoidLoopOnRejection() { + const ee = new EventEmitter({ captureRejections: true }); + const _err1 = new Error('kaboom'); + const _err2 = new Error('kaboom2'); + ee.on('something', common.mustCall(async (value) => { + throw _err1; + })); + + ee[captureRejectionSymbol] = common.mustCall(async (err) => { + assert.strictEqual(err, _err1); + throw _err2; + }); + + process.removeAllListeners('unhandledRejection'); + + process.once('unhandledRejection', common.mustCall((err) => { + // restore default + process.on('unhandledRejection', (err) => { throw err; }); + + assert.strictEqual(err, _err2); + process.nextTick(avoidLoopOnError); + })); + + ee.emit('something'); +} + +function avoidLoopOnError() { + const ee = new EventEmitter({ captureRejections: true }); + const _err1 = new Error('kaboom'); + const _err2 = new Error('kaboom2'); + ee.on('something', common.mustCall(async (value) => { + throw _err1; + })); + + ee.on('error', common.mustCall(async (err) => { + assert.strictEqual(err, _err1); + throw _err2; + })); + + process.removeAllListeners('unhandledRejection'); + + process.once('unhandledRejection', common.mustCall((err) => { + // restore default + process.on('unhandledRejection', (err) => { throw err; }); + + assert.strictEqual(err, _err2); + process.nextTick(thenableThatThrows); + })); + + ee.emit('something'); +} + +function thenableThatThrows() { + const ee = new EventEmitter({ captureRejections: true }); + const _err = new Error('kaboom'); + ee.on('something', common.mustCall((value) => { + const obj = {}; + + Object.defineProperty(obj, 'then', { + get: common.mustCall(() => { + throw _err; + }, 1) // Only 1 call for Promises/A+ compat. + }); + + return obj; + })); + + ee.on('error', common.mustCall((err) => { + assert.strictEqual(err, _err); + process.nextTick(resetCaptureOnThrowInError); + })); + + ee.emit('something'); +} + +function resetCaptureOnThrowInError() { + const ee = new EventEmitter({ captureRejections: true }); + ee.on('something', common.mustCall(async (value) => { + throw new Error('kaboom'); + })); + + ee.once('error', common.mustCall((err) => { + throw err; + })); + + process.removeAllListeners('uncaughtException'); + + process.once('uncaughtException', common.mustCall((err) => { + process.nextTick(next); + })); + + ee.emit('something'); + + function next() { + process.on('uncaughtException', common.mustNotCall()); + + const _err = new Error('kaboom2'); + ee.on('something2', common.mustCall(async (value) => { + throw _err; + })); + + ee.on('error', common.mustCall((err) => { + assert.strictEqual(err, _err); + + process.removeAllListeners('uncaughtException'); + + // restore default + process.on('uncaughtException', (err) => { throw err; }); + + process.nextTick(argValidation); + })); + + ee.emit('something2'); + } +} + +function argValidation() { + + function testType(obj) { + common.expectsError(() => new EventEmitter({ captureRejections: obj }), { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + }); + + common.expectsError(() => EventEmitter.captureRejections = obj, { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError + }); + } + + testType([]); + testType({ hello: 42 }); + testType(42); +} + +captureRejections(); From 89bc571490649f8facc67f22a7c384425e6c0fdd Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Mon, 19 Aug 2019 17:45:30 +0200 Subject: [PATCH 002/117] stream: add support for captureRejection option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/27867 Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell Reviewed-By: Jeremiah Senkpiel Reviewed-By: Anna Henningsen Reviewed-By: Michaël Zasso --- lib/_stream_readable.js | 10 +++- lib/_stream_writable.js | 7 ++- lib/internal/streams/legacy.js | 4 +- test/parallel/test-stream-catch-rejections.js | 52 +++++++++++++++++++ 4 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 test/parallel/test-stream-catch-rejections.js diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index 0d83ada205b835..8f5f66b391293c 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -190,7 +190,7 @@ function Readable(options) { this._destroy = options.destroy; } - Stream.call(this); + Stream.call(this, options); } ObjectDefineProperty(Readable.prototype, 'destroyed', { @@ -233,6 +233,14 @@ Readable.prototype._destroy = function(err, cb) { cb(err); }; +Readable.prototype[EE.captureRejectionSymbol] = function(err) { + // TODO(mcollina): remove the destroyed if once errorEmitted lands in + // Readable. + if (!this.destroyed) { + this.destroy(err); + } +}; + // Manually shove something into the read() buffer. // This returns true if the highWaterMark has not been hit yet, // similar to how Writable.write() returns true if you should diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js index 9bea209e257d2a..3452ac810beec9 100644 --- a/lib/_stream_writable.js +++ b/lib/_stream_writable.js @@ -35,6 +35,7 @@ module.exports = Writable; Writable.WritableState = WritableState; const internalUtil = require('internal/util'); +const EE = require('events'); const Stream = require('stream'); const { Buffer } = require('buffer'); const destroyImpl = require('internal/streams/destroy'); @@ -254,7 +255,7 @@ function Writable(options) { this._final = options.final; } - Stream.call(this); + Stream.call(this, options); } // Otherwise people can pipe Writable streams, which is just wrong. @@ -804,3 +805,7 @@ Writable.prototype._undestroy = destroyImpl.undestroy; Writable.prototype._destroy = function(err, cb) { cb(err); }; + +Writable.prototype[EE.captureRejectionSymbol] = function(err) { + this.destroy(err); +}; diff --git a/lib/internal/streams/legacy.js b/lib/internal/streams/legacy.js index 702e3c56ba6376..2bc7a86aa050b6 100644 --- a/lib/internal/streams/legacy.js +++ b/lib/internal/streams/legacy.js @@ -6,8 +6,8 @@ const { const EE = require('events'); -function Stream() { - EE.call(this); +function Stream(opts) { + EE.call(this, opts); } ObjectSetPrototypeOf(Stream.prototype, EE.prototype); ObjectSetPrototypeOf(Stream, EE); diff --git a/test/parallel/test-stream-catch-rejections.js b/test/parallel/test-stream-catch-rejections.js new file mode 100644 index 00000000000000..fb5f1fccc18bd2 --- /dev/null +++ b/test/parallel/test-stream-catch-rejections.js @@ -0,0 +1,52 @@ +'use strict'; + +const common = require('../common'); +const stream = require('stream'); +const assert = require('assert'); + +{ + const r = new stream.Readable({ + captureRejections: true, + read() { + this.push('hello'); + this.push('world'); + this.push(null); + } + }); + + const err = new Error('kaboom'); + + r.on('error', common.mustCall((_err) => { + assert.strictEqual(err, _err); + assert.strictEqual(r.destroyed, true); + })); + + r.on('data', async () => { + throw err; + }); +} + +{ + const w = new stream.Writable({ + captureRejections: true, + highWaterMark: 1, + write(chunk, enc, cb) { + cb(); + } + }); + + const err = new Error('kaboom'); + + w.write('hello', () => { + w.write('world'); + }); + + w.on('error', common.mustCall((_err) => { + assert.strictEqual(err, _err); + assert.strictEqual(w.destroyed, true); + })); + + w.on('drain', common.mustCall(async () => { + throw err; + }, 2)); +} From 33a6bf3a83eb8f016e791a18517ff104c2ff3ef9 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Tue, 3 Sep 2019 09:41:15 +0200 Subject: [PATCH 003/117] http: implement capture rejections for 'request' event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/27867 Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell Reviewed-By: Jeremiah Senkpiel Reviewed-By: Anna Henningsen Reviewed-By: Michaël Zasso --- lib/_http_server.js | 21 ++++ .../test-http-server-capture-rejections.js | 108 ++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 test/parallel/test-http-server-capture-rejections.js diff --git a/lib/_http_server.js b/lib/_http_server.js index 6c52f7adbc919d..3444c44a6ce881 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -27,6 +27,7 @@ const { } = primordials; const net = require('net'); +const EE = require('events'); const assert = require('internal/assert'); const { parsers, @@ -357,6 +358,26 @@ Server.prototype.setTimeout = function setTimeout(msecs, callback) { return this; }; +Server.prototype[EE.captureRejectionSymbol] = function( + err, event, req, res) { + + switch (event) { + case 'request': + if (!res.headersSent && !res.writableEnded) { + // Don't leak headers. + for (const name of res.getHeaderNames()) { + res.removeHeader(name); + } + res.statusCode = 500; + res.end(STATUS_CODES[500]); + } else { + res.destroy(); + } + break; + default: + this.emit('error', err); + } +}; function connectionListener(socket) { defaultTriggerAsyncIdScope( diff --git a/test/parallel/test-http-server-capture-rejections.js b/test/parallel/test-http-server-capture-rejections.js new file mode 100644 index 00000000000000..b437e27b589dfc --- /dev/null +++ b/test/parallel/test-http-server-capture-rejections.js @@ -0,0 +1,108 @@ +'use strict'; + +const common = require('../common'); +const events = require('events'); +const { createServer, request } = require('http'); +const assert = require('assert'); + +events.captureRejections = true; + +{ + const server = createServer(common.mustCall(async (req, res) => { + // We will test that this header is cleaned up before forwarding. + res.setHeader('content-type', 'application/json'); + throw new Error('kaboom'); + })); + + server.listen(0, common.mustCall(() => { + const req = request({ + method: 'GET', + host: server.address().host, + port: server.address().port + }); + + req.end(); + + req.on('response', common.mustCall((res) => { + assert.strictEqual(res.statusCode, 500); + assert.strictEqual(res.headers.hasOwnProperty('content-type'), false); + let data = ''; + res.setEncoding('utf8'); + res.on('data', common.mustCall((chunk) => { + data += chunk; + })); + res.on('end', common.mustCall(() => { + assert.strictEqual(data, 'Internal Server Error'); + server.close(); + })); + })); + })); +} + +{ + let resolve; + const latch = new Promise((_resolve) => { + resolve = _resolve; + }); + const server = createServer(common.mustCall(async (req, res) => { + server.close(); + + // We will test that this header is cleaned up before forwarding. + res.setHeader('content-type', 'application/json'); + res.write('{'); + req.resume(); + + // Wait so the data is on the wire + await latch; + + throw new Error('kaboom'); + })); + + server.listen(0, common.mustCall(() => { + const req = request({ + method: 'GET', + host: server.address().host, + port: server.address().port + }); + + req.end(); + + req.on('response', common.mustCall((res) => { + assert.strictEqual(res.statusCode, 200); + assert.strictEqual(res.headers['content-type'], 'application/json'); + resolve(); + + let data = ''; + res.setEncoding('utf8'); + res.on('data', common.mustCall((chunk) => { + data += chunk; + })); + + req.on('close', common.mustCall(() => { + assert.strictEqual(data, '{'); + })); + })); + })); +} + +{ + const server = createServer(common.mustCall(async (req, res) => { + // We will test that this header is cleaned up before forwarding. + res.writeHead(200); + throw new Error('kaboom'); + })); + + server.listen(0, common.mustCall(() => { + const req = request({ + method: 'GET', + host: server.address().host, + port: server.address().port + }); + + req.end(); + req.on('error', common.mustCall((err) => { + assert.strictEqual(err.code, 'ECONNRESET'); + server.close(); + })); + })); +} From 334d4f6256541f37b1328d66edf4c068b92c012a Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 20 Sep 2019 18:19:35 +0200 Subject: [PATCH 004/117] http: add captureRejection support to OutgoingMessage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/27867 Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell Reviewed-By: Jeremiah Senkpiel Reviewed-By: Anna Henningsen Reviewed-By: Michaël Zasso --- lib/_http_outgoing.js | 6 ++ ...http-outgoing-message-capture-rejection.js | 89 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 test/parallel/test-http-outgoing-message-capture-rejection.js diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index e331d073b57067..c3bfbd09bfca0c 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -32,6 +32,7 @@ const { const { getDefaultHighWaterMark } = require('internal/streams/state'); const assert = require('internal/assert'); +const EE = require('events'); const Stream = require('stream'); const internalUtil = require('internal/util'); const { kOutHeaders, utcDate, kNeedDrain } = require('internal/http'); @@ -884,6 +885,11 @@ OutgoingMessage.prototype.pipe = function pipe() { this.emit('error', new ERR_STREAM_CANNOT_PIPE()); }; +OutgoingMessage.prototype[EE.captureRejectionSymbol] = +function(err, event) { + this.destroy(err); +}; + module.exports = { OutgoingMessage }; diff --git a/test/parallel/test-http-outgoing-message-capture-rejection.js b/test/parallel/test-http-outgoing-message-capture-rejection.js new file mode 100644 index 00000000000000..5f667ea17ea156 --- /dev/null +++ b/test/parallel/test-http-outgoing-message-capture-rejection.js @@ -0,0 +1,89 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const events = require('events'); +const { createServer, request } = require('http'); + +events.captureRejections = true; + +{ + const server = createServer(common.mustCall((req, res) => { + const _err = new Error('kaboom'); + res.on('drain', common.mustCall(async () => { + throw _err; + })); + + res.socket.on('error', common.mustCall((err) => { + assert.strictEqual(err, _err); + })); + + // Write until there is space in the buffer + while (res.write('hello')) {} + })); + + server.listen(0, common.mustCall(() => { + const req = request({ + method: 'GET', + host: server.address().host, + port: server.address().port + }); + + req.end(); + + req.on('response', common.mustCall((res) => { + res.on('aborted', common.mustCall()); + res.resume(); + server.close(); + })); + })); +} + +{ + let _res; + let shouldEnd = false; + // Not using mustCall here, because it is OS-dependant. + const server = createServer((req, res) => { + // So that we cleanly stop + _res = res; + + if (shouldEnd) { + res.end(); + } + }); + + server.listen(0, common.mustCall(() => { + const _err = new Error('kaboom'); + + const req = request({ + method: 'POST', + host: server.address().host, + port: server.address().port + }); + + req.on('response', common.mustNotCall((res) => { + // So that we cleanly stop + res.resume(); + server.close(); + })); + + req.on('error', common.mustCall((err) => { + server.close(); + // On some variants of Windows, this can happen before + // the server has received the request. + if (_res) { + _res.end(); + } else { + shouldEnd = true; + } + assert.strictEqual(err, _err); + })); + + req.on('drain', common.mustCall(async () => { + throw _err; + })); + + // Write until there is space in the buffer + while (req.write('hello')) {} + })); +} From 4eecee089d285d0fb42506175753746901ee4f94 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Tue, 1 Oct 2019 17:30:39 +0200 Subject: [PATCH 005/117] net: implement capture rejections for 'connection' event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/27867 Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell Reviewed-By: Jeremiah Senkpiel Reviewed-By: Anna Henningsen Reviewed-By: Michaël Zasso --- lib/_http_server.js | 6 +++-- lib/net.js | 13 +++++++++ .../test-net-server-capture-rejection.js | 27 +++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 test/parallel/test-net-server-capture-rejection.js diff --git a/lib/_http_server.js b/lib/_http_server.js index 3444c44a6ce881..b967cac3ae402d 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -359,10 +359,11 @@ Server.prototype.setTimeout = function setTimeout(msecs, callback) { }; Server.prototype[EE.captureRejectionSymbol] = function( - err, event, req, res) { + err, event, ...args) { switch (event) { case 'request': + const [ , res] = args; if (!res.headersSent && !res.writableEnded) { // Don't leak headers. for (const name of res.getHeaderNames()) { @@ -375,7 +376,8 @@ Server.prototype[EE.captureRejectionSymbol] = function( } break; default: - this.emit('error', err); + net.Server.prototype[Symbol.for('nodejs.rejection')] + .call(this, err, event, ...args); } }; diff --git a/lib/net.js b/lib/net.js index 02fd18748036a3..7e5d0ea621dedc 100644 --- a/lib/net.js +++ b/lib/net.js @@ -1653,6 +1653,19 @@ function emitCloseNT(self) { } +Server.prototype[EventEmitter.captureRejectionSymbol] = function( + err, event, sock) { + + switch (event) { + case 'connection': + sock.destroy(err); + break; + default: + this.emit('error', err); + } +}; + + // Legacy alias on the C++ wrapper object. This is not public API, so we may // want to runtime-deprecate it at some point. There's no hurry, though. ObjectDefineProperty(TCP.prototype, 'owner', { diff --git a/test/parallel/test-net-server-capture-rejection.js b/test/parallel/test-net-server-capture-rejection.js new file mode 100644 index 00000000000000..b1564ec26874af --- /dev/null +++ b/test/parallel/test-net-server-capture-rejection.js @@ -0,0 +1,27 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const events = require('events'); +const { createServer, connect } = require('net'); + +events.captureRejections = true; + +const server = createServer(common.mustCall(async (sock) => { + server.close(); + + const _err = new Error('kaboom'); + sock.on('error', common.mustCall((err) => { + assert.strictEqual(err, _err); + })); + throw _err; +})); + +server.listen(0, common.mustCall(() => { + const sock = connect( + server.address().port, + server.address().host + ); + + sock.on('close', common.mustCall()); +})); From 5ad3efbfb35e6a5f393cbe695e6386b9fa134ac1 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Tue, 1 Oct 2019 18:06:22 +0200 Subject: [PATCH 006/117] tls: implement capture rejections for 'secureConnection' event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/27867 Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell Reviewed-By: Jeremiah Senkpiel Reviewed-By: Anna Henningsen Reviewed-By: Michaël Zasso --- lib/_tls_wrap.js | 14 ++++++++ .../test-tls-server-capture-rejection.js | 34 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 test/parallel/test-tls-server-capture-rejection.js diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index 530a41a1e855fd..4379287cc4775c 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -37,6 +37,7 @@ assertCrypto(); const { setImmediate } = require('timers'); const assert = require('internal/assert'); const crypto = require('crypto'); +const EE = require('events'); const net = require('net'); const tls = require('tls'); const common = require('_tls_common'); @@ -1284,6 +1285,19 @@ Server.prototype.addContext = function(servername, context) { this._contexts.push([re, tls.createSecureContext(context).context]); }; +Server.prototype[EE.captureRejectionSymbol] = function( + err, event, sock) { + + switch (event) { + case 'secureConnection': + sock.destroy(err); + break; + default: + net.Server.prototype[Symbol.for('nodejs.rejection')] + .call(this, err, event, sock); + } +}; + function SNICallback(servername, callback) { const contexts = this.server._contexts; diff --git a/test/parallel/test-tls-server-capture-rejection.js b/test/parallel/test-tls-server-capture-rejection.js new file mode 100644 index 00000000000000..f9bd3320e101f0 --- /dev/null +++ b/test/parallel/test-tls-server-capture-rejection.js @@ -0,0 +1,34 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const events = require('events'); +const fixtures = require('../common/fixtures'); +const { createServer, connect } = require('tls'); +const cert = fixtures.readKey('rsa_cert.crt'); +const key = fixtures.readKey('rsa_private.pem'); + +events.captureRejections = true; + +const server = createServer({ cert, key }, common.mustCall(async (sock) => { + server.close(); + + const _err = new Error('kaboom'); + sock.on('error', common.mustCall((err) => { + assert.strictEqual(err, _err); + })); + throw _err; +})); + +server.listen(0, common.mustCall(() => { + const sock = connect({ + port: server.address().port, + host: server.address().host, + rejectUnauthorized: false + }); + + sock.on('close', common.mustCall()); +})); From c3ac4c85a5fc9b1cddd2587ef61ed1dd0803b92d Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Wed, 2 Oct 2019 13:02:37 +0200 Subject: [PATCH 007/117] http2: implement capture rection for 'request' and 'stream' events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/27867 Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell Reviewed-By: Jeremiah Senkpiel Reviewed-By: Anna Henningsen Reviewed-By: Michaël Zasso --- lib/internal/http2/core.js | 45 ++++++ test/parallel/test-http2-capture-rejection.js | 152 ++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 test/parallel/test-http2-capture-rejection.js diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index c4d12f9205151c..167044f8408fee 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -1388,6 +1388,17 @@ class Http2Session extends EventEmitter { this[kMaybeDestroy](); } + [EventEmitter.captureRejectionSymbol](err, event, ...args) { + switch (event) { + case 'stream': + const [stream] = args; + stream.destroy(err); + break; + default: + this.destroy(err); + } + } + // Destroy the session if: // * error is not undefined/null // * session is closed and there are no more pending or open streams @@ -2875,6 +2886,40 @@ class Http2Server extends NETServer { } } +Http2Server.prototype[EventEmitter.captureRejectionSymbol] = function( + err, event, ...args) { + + switch (event) { + case 'stream': + // TODO(mcollina): we might want to match this with what we do on + // the compat side. + const [stream] = args; + if (stream.sentHeaders) { + stream.destroy(err); + } else { + stream.respond({ [HTTP2_HEADER_STATUS]: 500 }); + stream.end(); + } + break; + case 'request': + const [, res] = args; + if (!res.headersSent && !res.finished) { + // Don't leak headers. + for (const name of res.getHeaderNames()) { + res.removeHeader(name); + } + res.statusCode = 500; + res.end(http.STATUS_CODES[500]); + } else { + res.destroy(); + } + break; + default: + net.Server.prototype[EventEmitter.captureRejectionSymbol] + .call(this, err, event, ...args); + } +}; + function setupCompat(ev) { if (ev === 'request') { this.removeListener('newListener', setupCompat); diff --git a/test/parallel/test-http2-capture-rejection.js b/test/parallel/test-http2-capture-rejection.js new file mode 100644 index 00000000000000..58f43581eb6bd3 --- /dev/null +++ b/test/parallel/test-http2-capture-rejection.js @@ -0,0 +1,152 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const events = require('events'); +const { createServer, connect } = require('http2'); + +events.captureRejections = true; + +{ + // Test error thrown in the server 'stream' event, + // after a respond() + + const server = createServer(); + server.on('stream', common.mustCall(async (stream) => { + server.close(); + + stream.respond({ ':status': 200 }); + + const _err = new Error('kaboom'); + stream.on('error', common.mustCall((err) => { + assert.strictEqual(err, _err); + })); + throw _err; + })); + + server.listen(0, common.mustCall(() => { + const { port } = server.address(); + const session = connect(`http://localhost:${port}`); + + const req = session.request(); + + req.on('error', common.mustCall((err) => { + assert.strictEqual(err.code, 'ERR_HTTP2_STREAM_ERROR'); + })); + + req.on('close', common.mustCall(() => { + session.close(); + })); + })); +} + +{ + // Test error thrown in the server 'stream' event, + // before a respond(). + + const server = createServer(); + server.on('stream', common.mustCall(async (stream) => { + server.close(); + + stream.on('error', common.mustNotCall()); + + throw new Error('kaboom'); + })); + + server.listen(0, common.mustCall(() => { + const { port } = server.address(); + const session = connect(`http://localhost:${port}`); + + const req = session.request(); + + req.on('response', common.mustCall((headers) => { + assert.strictEqual(headers[':status'], 500); + })); + + req.on('close', common.mustCall(() => { + session.close(); + })); + })); +} + + +{ + // Test error thrown in 'request' event + + const server = createServer(common.mustCall(async (req, res) => { + server.close(); + res.setHeader('content-type', 'application/json'); + const _err = new Error('kaboom'); + throw _err; + })); + + server.listen(0, common.mustCall(() => { + const { port } = server.address(); + const session = connect(`http://localhost:${port}`); + + const req = session.request(); + + req.on('response', common.mustCall((headers) => { + assert.strictEqual(headers[':status'], 500); + assert.strictEqual(Object.hasOwnProperty.call(headers, 'content-type'), + false); + })); + + req.on('close', common.mustCall(() => { + session.close(); + })); + + req.resume(); + })); +} + +{ + // Test error thrown in the client 'stream' event + + const server = createServer(); + server.on('stream', common.mustCall(async (stream) => { + const { port } = server.address(); + + server.close(); + + stream.pushStream({ + ':scheme': 'http', + ':path': '/foobar', + ':authority': `localhost:${port}`, + }, common.mustCall((err, push) => { + push.respond({ + 'content-type': 'text/html', + ':status': 200 + }); + push.end('pushed by the server'); + + stream.end('test'); + })); + + stream.respond({ + ':status': 200 + }); + })); + + server.listen(0, common.mustCall(() => { + const { port } = server.address(); + const session = connect(`http://localhost:${port}`); + + const req = session.request(); + + session.on('stream', common.mustCall(async (stream) => { + session.close(); + + const _err = new Error('kaboom'); + stream.on('error', common.mustCall((err) => { + assert.strictEqual(err, _err); + })); + throw _err; + })); + + req.end(); + })); +} From 50ab1fa013c643189bc6a8d6899e6d3cb9e6824b Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sun, 1 Dec 2019 02:59:36 -0800 Subject: [PATCH 008/117] test: change common.PORT to arbitrary port Change common.PORT to arbitrary port in test-child-process-fork-getconnections to prepare for moving that test from sequential to parallel. PR-URL: https://github.com/nodejs/node/pull/30749 Reviewed-By: Denys Otrishko Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- test/sequential/test-child-process-fork-getconnections.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/sequential/test-child-process-fork-getconnections.js b/test/sequential/test-child-process-fork-getconnections.js index 9a8f97c2bb2842..1b1ba9c0d96048 100644 --- a/test/sequential/test-child-process-fork-getconnections.js +++ b/test/sequential/test-child-process-fork-getconnections.js @@ -20,7 +20,7 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const fork = require('child_process').fork; const net = require('net'); @@ -79,7 +79,7 @@ if (process.argv[2] === 'child') { server.on('listening', function() { let j = count; while (j--) { - const client = net.connect(common.PORT, '127.0.0.1'); + const client = net.connect(server.address().port, '127.0.0.1'); client.on('close', function() { disconnected += 1; }); @@ -110,7 +110,7 @@ if (process.argv[2] === 'child') { closeEmitted = true; }); - server.listen(common.PORT, '127.0.0.1'); + server.listen(0, '127.0.0.1'); process.on('exit', function() { assert.strictEqual(sent, count); From 9bd5c72104fd3016cf29753741135e9c3c56436b Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sun, 1 Dec 2019 03:06:51 -0800 Subject: [PATCH 009/117] test: move test-child-process-fork-getconnections to parallel Now that the test uses an open port assigned by the operating system rather than a hardcoded common.PORT, it can be moved to parallel. PR-URL: https://github.com/nodejs/node/pull/30749 Reviewed-By: Denys Otrishko Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- .../test-child-process-fork-getconnections.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{sequential => parallel}/test-child-process-fork-getconnections.js (100%) diff --git a/test/sequential/test-child-process-fork-getconnections.js b/test/parallel/test-child-process-fork-getconnections.js similarity index 100% rename from test/sequential/test-child-process-fork-getconnections.js rename to test/parallel/test-child-process-fork-getconnections.js From 145f881ff9eb1eea07a2ef4b5c9f76580606e648 Mon Sep 17 00:00:00 2001 From: Michael Dawson Date: Fri, 29 Nov 2019 16:52:50 -0500 Subject: [PATCH 010/117] doc: update status of Python 3 support Refs: https://github.com/nodejs/TSC/pull/781#issuecomment-559666380 Based on the completion of the Python 3 strategic initiative, update statements around Python 3 support. PR-URL: https://github.com/nodejs/node/pull/30722 Reviewed-By: Sam Roberts Reviewed-By: Anna Henningsen Reviewed-By: Jiawen Geng Reviewed-By: James M Snell Reviewed-By: Joyee Cheung --- BUILDING.md | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index 14206976e48a12..1939d2513e9237 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -227,18 +227,10 @@ Consult previous versions of this document for older versions of Node.js: ### Note about Python 2 and Python 3 -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/ -for more information. - -The Node.js project is in the process of transitioning its Python code to -Python 3 compatibility. Installing both versions of Python while building -and testing Node.js allows developers and end users to test, benchmark, -and debug Node.js running on both versions to ensure a smooth and complete -transition before the year-end deadline. +The Node.js project supports both Python 3 and Python 2 for building. +If both are installed Python 3 will be used. If only Python 2 is available +it will be used instead. When possible we recommend that you build and +test with Python 3. ### Unix and macOS @@ -248,7 +240,7 @@ transition before the year-end deadline. * GNU Make 3.81 or newer * Python (see note above) * Python 2.7 - * Python 3.5, 3.6, 3.7, and 3.8 are experimental. + * Python 3.5, 3.6, 3.7, and 3.8. Installation via Linux package manager can be achieved with: @@ -264,7 +256,7 @@ FreeBSD and OpenBSD users may also need to install `libexecinfo`. * Xcode Command Line Tools >= 10 for macOS * Python (see note above) * Python 2.7 - * Python 3.5, 3.6, 3.7, and 3.8 are experimental. + * Python 3.5, 3.6, 3.7, and 3.8. macOS users can install the `Xcode Command Line Tools` by running `xcode-select --install`. Alternatively, if you already have the full Xcode From a0fa327365c2e713676a5c2f3c9a20f26bd981c1 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sun, 1 Dec 2019 12:13:33 -0800 Subject: [PATCH 011/117] test: use block-scoping in test-net-server-address Use block-scoping in test-net-server-address. This also allows us to easily rename some identifiers that were not camelCase. PR-URL: https://github.com/nodejs/node/pull/30754 Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- test/sequential/test-net-server-address.js | 122 +++++++++++---------- 1 file changed, 67 insertions(+), 55 deletions(-) diff --git a/test/sequential/test-net-server-address.js b/test/sequential/test-net-server-address.js index 52a8c1ac820e24..4312ffd5a1fe78 100644 --- a/test/sequential/test-net-server-address.js +++ b/test/sequential/test-net-server-address.js @@ -25,77 +25,89 @@ const assert = require('assert'); const net = require('net'); // Test on IPv4 Server -const family_ipv4 = 'IPv4'; -const server_ipv4 = net.createServer(); - -server_ipv4.on('error', common.mustNotCall()); - -server_ipv4 - .listen(common.PORT + 1, common.localhostIPv4, common.mustCall(() => { - const address_ipv4 = server_ipv4.address(); - assert.strictEqual(address_ipv4.address, common.localhostIPv4); - assert.strictEqual(address_ipv4.port, common.PORT + 1); - assert.strictEqual(address_ipv4.family, family_ipv4); - server_ipv4.close(); - })); +{ + const family = 'IPv4'; + const server = net.createServer(); + + server.on('error', common.mustNotCall()); + + server + .listen(common.PORT + 1, common.localhostIPv4, common.mustCall(() => { + const address4 = server.address(); + assert.strictEqual(address4.address, common.localhostIPv4); + assert.strictEqual(address4.port, common.PORT + 1); + assert.strictEqual(address4.family, family); + server.close(); + })); +} if (!common.hasIPv6) { common.printSkipMessage('ipv6 part of test, no IPv6 support'); return; } +const family6 = 'IPv6'; +const anycast6 = '::'; + // Test on IPv6 Server -const localhost_ipv6 = '::1'; -const family_ipv6 = 'IPv6'; -const server_ipv6 = net.createServer(); +{ + const localhost = '::1'; -server_ipv6.on('error', common.mustNotCall()); + const server = net.createServer(); -server_ipv6.listen(common.PORT + 2, localhost_ipv6, common.mustCall(() => { - const address_ipv6 = server_ipv6.address(); - assert.strictEqual(address_ipv6.address, localhost_ipv6); - assert.strictEqual(address_ipv6.port, common.PORT + 2); - assert.strictEqual(address_ipv6.family, family_ipv6); - server_ipv6.close(); -})); + server.on('error', common.mustNotCall()); -// Test without hostname or ip -const anycast_ipv6 = '::'; -const server1 = net.createServer(); - -server1.on('error', common.mustNotCall()); + server.listen(common.PORT + 2, localhost, common.mustCall(() => { + const address = server.address(); + assert.strictEqual(address.address, localhost); + assert.strictEqual(address.port, common.PORT + 2); + assert.strictEqual(address.family, family6); + server.close(); + })); +} -// Specify the port number -server1.listen(common.PORT + 3, common.mustCall(() => { - const address = server1.address(); - assert.strictEqual(address.address, anycast_ipv6); - assert.strictEqual(address.port, common.PORT + 3); - assert.strictEqual(address.family, family_ipv6); - server1.close(); -})); +// Test without hostname or ip +{ + const server = net.createServer(); + + server.on('error', common.mustNotCall()); + + // Specify the port number + server.listen(common.PORT + 3, common.mustCall(() => { + const address = server.address(); + assert.strictEqual(address.address, anycast6); + assert.strictEqual(address.port, common.PORT + 3); + assert.strictEqual(address.family, family6); + server.close(); + })); +} // Test without hostname or port -const server2 = net.createServer(); +{ + const server = net.createServer(); -server2.on('error', common.mustNotCall()); + server.on('error', common.mustNotCall()); -// Don't specify the port number -server2.listen(common.mustCall(() => { - const address = server2.address(); - assert.strictEqual(address.address, anycast_ipv6); - assert.strictEqual(address.family, family_ipv6); - server2.close(); -})); + // Don't specify the port number + server.listen(common.mustCall(() => { + const address = server.address(); + assert.strictEqual(address.address, anycast6); + assert.strictEqual(address.family, family6); + server.close(); + })); +} // Test without hostname, but with a false-y port -const server3 = net.createServer(); +{ + const server = net.createServer(); -server3.on('error', common.mustNotCall()); + server.on('error', common.mustNotCall()); -// Specify a false-y port number -server3.listen(0, common.mustCall(() => { - const address = server3.address(); - assert.strictEqual(address.address, anycast_ipv6); - assert.strictEqual(address.family, family_ipv6); - server3.close(); -})); + // Specify a false-y port number + server.listen(0, common.mustCall(() => { + const address = server.address(); + assert.strictEqual(address.address, anycast6); + assert.strictEqual(address.family, family6); + server.close(); + })); +} From b51b26ffef23e2f00f462819518759c1d12e4121 Mon Sep 17 00:00:00 2001 From: Priyanka Kore Date: Sun, 1 Dec 2019 13:41:39 +0100 Subject: [PATCH 012/117] src: fix node_dir.cc memory allocation PR-URL: https://github.com/nodejs/node/pull/30750 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: David Carlier --- src/node_dir.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node_dir.cc b/src/node_dir.cc index 37285928fbd731..36366502aafe3b 100644 --- a/src/node_dir.cc +++ b/src/node_dir.cc @@ -172,7 +172,7 @@ static MaybeLocal DirentListToArray( int num, enum encoding encoding, Local* err_out) { - MaybeStackBuffer, 96> entries(num * 3); + MaybeStackBuffer, 64> entries(num * 2); // Return an array of all read filenames. int j = 0; From cb69ff47f665a8fe90d07f3ece123a0161f088f4 Mon Sep 17 00:00:00 2001 From: Priyanka Kore Date: Sun, 1 Dec 2019 14:35:18 +0100 Subject: [PATCH 013/117] src: improve node_crypto.cc memory allocation This avoids heap allocations in common cases PR-URL: https://github.com/nodejs/node/pull/30751 Reviewed-By: Anna Henningsen Reviewed-By: David Carlier Reviewed-By: Denys Otrishko Reviewed-By: James M Snell Reviewed-By: Colin Ihrig --- src/node_crypto.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/node_crypto.cc b/src/node_crypto.cc index d1bd5471f3fba2..2d965bcbff5ea0 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -2697,11 +2697,11 @@ void SSLWrap::GetSharedSigalgs(const FunctionCallbackInfo& args) { Base* w; ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); Environment* env = w->ssl_env(); - std::vector> ret_arr; SSL* ssl = w->ssl_.get(); int nsig = SSL_get_shared_sigalgs(ssl, 0, nullptr, nullptr, nullptr, nullptr, nullptr); + MaybeStackBuffer, 16> ret_arr(nsig); for (int i = 0; i < nsig; i++) { int hash_nid; @@ -2765,12 +2765,11 @@ void SSLWrap::GetSharedSigalgs(const FunctionCallbackInfo& args) { } else { sig_with_md += "UNDEF"; } - - ret_arr.push_back(OneByteString(env->isolate(), sig_with_md.c_str())); + ret_arr[i] = OneByteString(env->isolate(), sig_with_md.c_str()); } args.GetReturnValue().Set( - Array::New(env->isolate(), ret_arr.data(), ret_arr.size())); + Array::New(env->isolate(), ret_arr.out(), ret_arr.length())); } From 66db8746c72d57fc81abd93370e5b446738c7791 Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Sun, 1 Dec 2019 15:30:36 +0800 Subject: [PATCH 014/117] src: remove redundant cast in node_dir.cc PR-URL: https://github.com/nodejs/node/pull/30747 Reviewed-By: David Carlier Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Colin Ihrig --- src/node_dir.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node_dir.cc b/src/node_dir.cc index 36366502aafe3b..ec53d8216bcba0 100644 --- a/src/node_dir.cc +++ b/src/node_dir.cc @@ -320,7 +320,7 @@ static void OpenDir(const FunctionCallbackInfo& args) { const enum encoding encoding = ParseEncoding(isolate, args[1], UTF8); - FSReqBase* req_wrap_async = static_cast(GetReqWrap(env, args[2])); + FSReqBase* req_wrap_async = GetReqWrap(env, args[2]); if (req_wrap_async != nullptr) { // openDir(path, encoding, req) AsyncCall(env, req_wrap_async, args, "opendir", encoding, AfterOpenDir, uv_fs_opendir, *path); From 838ae10a9baa7f664a6bf71b3fe008362a6d65b8 Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Sun, 1 Dec 2019 15:31:03 +0800 Subject: [PATCH 015/117] src: delete redundant method in node_dir.h PR-URL: https://github.com/nodejs/node/pull/30747 Reviewed-By: David Carlier Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Colin Ihrig --- src/node_dir.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/node_dir.h b/src/node_dir.h index caef7a5d309180..b55245d5b89a2e 100644 --- a/src/node_dir.h +++ b/src/node_dir.h @@ -18,7 +18,6 @@ class DirHandle : public AsyncWrap { ~DirHandle() override; static void New(const v8::FunctionCallbackInfo& args); - static void Open(const v8::FunctionCallbackInfo& args); static void Read(const v8::FunctionCallbackInfo& args); static void Close(const v8::FunctionCallbackInfo& args); From 83695627574b899b73205bc87be5c48320e770fb Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sat, 30 Nov 2019 19:18:01 -0800 Subject: [PATCH 016/117] doc: clarify text about using 'session' event for compatibility PR-URL: https://github.com/nodejs/node/pull/30746 Reviewed-By: Sam Roberts Reviewed-By: Anna Henningsen --- doc/api/tls.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/api/tls.md b/doc/api/tls.md index 3fd8e8cb494de7..8fa601096bc779 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -726,14 +726,14 @@ On the client, the `session` can be provided to the `session` option of See [Session Resumption][] for more information. -Note: For TLSv1.2 and below, [`tls.TLSSocket.getSession()`][] can be called once -the handshake is complete. For TLSv1.3, only ticket based resumption is allowed +For TLSv1.2 and below, [`tls.TLSSocket.getSession()`][] can be called once +the handshake is complete. For TLSv1.3, only ticket-based resumption is allowed by the protocol, multiple tickets are sent, and the tickets aren't sent until -later, after the handshake completes, so it is necessary to wait for the -`'session'` event to get a resumable session. Applications are -recommended to use the `'session'` event instead of `getSession()` to ensure -they will work for all TLS protocol versions. Applications that only expect to -get or use 1 session should listen for this event only once: +after the handshake completes. So it is necessary to wait for the +`'session'` event to get a resumable session. Applications +should use the `'session'` event instead of `getSession()` to ensure +they will work for all TLS versions. Applications that only expect to +get or use one session should listen for this event only once: ```js tlsSocket.once('session', (session) => { From 9428304d4a829ae9f7bb49c21faaed1ea3289c14 Mon Sep 17 00:00:00 2001 From: Jan-Philip Gehrcke Date: Thu, 28 Nov 2019 19:30:52 +0100 Subject: [PATCH 017/117] doc: Buffer.toString(): add note about invalid data PR-URL: https://github.com/nodejs/node/pull/30706 Reviewed-By: Anna Henningsen Reviewed-By: Denys Otrishko Reviewed-By: Trivikram Kamat Reviewed-By: Colin Ihrig Reviewed-By: David Carlier --- doc/api/buffer.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/api/buffer.md b/doc/api/buffer.md index a97ab6c2a6314b..c5b7bf15047177 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -2162,6 +2162,8 @@ added: v0.1.90 Decodes `buf` to a string according to the specified character encoding in `encoding`. `start` and `end` may be passed to decode only a subset of `buf`. +If a byte sequence in the input is not valid in the given `encoding` then +it is replaced with the replacement character `U+FFFD`. The maximum length of a string instance (in UTF-16 code units) is available as [`buffer.constants.MAX_STRING_LENGTH`][]. From 255cd7e57218bee655eba90085de425a20d892b6 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Mon, 3 Jun 2019 11:48:25 -0700 Subject: [PATCH 018/117] tls: expose IETF name for current cipher suite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenSSL has its own legacy names, but knowing the IETF name is useful when trouble-shooting, or looking for more information on the cipher. PR-URL: https://github.com/nodejs/node/pull/30637 Reviewed-By: Colin Ihrig Reviewed-By: Tobias Nießen Reviewed-By: David Carlier Reviewed-By: Yorkie Liu Reviewed-By: Ben Noordhuis Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- doc/api/tls.md | 15 +++++++++++++-- src/env.h | 1 + src/node_crypto.cc | 3 +++ test/parallel/test-tls-getcipher.js | 4 ++++ test/parallel/test-tls-multi-key.js | 2 ++ test/parallel/test-tls-multi-pfx.js | 2 ++ 6 files changed, 25 insertions(+), 2 deletions(-) diff --git a/doc/api/tls.md b/doc/api/tls.md index 8fa601096bc779..7473c11a68b91f 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -827,16 +827,27 @@ changes: pr-url: https://github.com/nodejs/node/pull/26625 description: Return the minimum cipher version, instead of a fixed string (`'TLSv1/SSLv3'`). + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/30637 + description: Return the IETF cipher name as `standardName`. --> * Returns: {Object} - * `name` {string} The name of the cipher suite. + * `name` {string} OpenSSL name for the cipher suite. + * `standardName` {string} IETF name for the cipher suite. * `version` {string} The minimum TLS protocol version supported by this cipher suite. Returns an object containing information on the negotiated cipher suite. -For example: `{ name: 'AES256-SHA', version: 'TLSv1.2' }`. +For example: +```json +{ + "name": "AES128-SHA256", + "standardName": "TLS_RSA_WITH_AES_128_CBC_SHA256", + "version": "TLSv1.2" +} +``` See [SSL_CIPHER_get_name](https://www.openssl.org/docs/man1.1.1/man3/SSL_CIPHER_get_name.html) diff --git a/src/env.h b/src/env.h index c25a03ea1e520a..b3f1243f77584b 100644 --- a/src/env.h +++ b/src/env.h @@ -351,6 +351,7 @@ constexpr size_t kFsStatsBufferLength = V(sni_context_string, "sni_context") \ V(source_string, "source") \ V(stack_string, "stack") \ + V(standard_name_string, "standardName") \ V(start_time_string, "startTime") \ V(status_string, "status") \ V(stdio_string, "stdio") \ diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 2d965bcbff5ea0..3f771793e2c874 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -2685,6 +2685,9 @@ void SSLWrap::GetCipher(const FunctionCallbackInfo& args) { const char* cipher_name = SSL_CIPHER_get_name(c); info->Set(context, env->name_string(), OneByteString(args.GetIsolate(), cipher_name)).Check(); + const char* cipher_standard_name = SSL_CIPHER_standard_name(c); + info->Set(context, env->standard_name_string(), + OneByteString(args.GetIsolate(), cipher_standard_name)).Check(); const char* cipher_version = SSL_CIPHER_get_version(c); info->Set(context, env->version_string(), OneByteString(args.GetIsolate(), cipher_version)).Check(); diff --git a/test/parallel/test-tls-getcipher.js b/test/parallel/test-tls-getcipher.js index 624f8efd24ba6e..744276aa59bf37 100644 --- a/test/parallel/test-tls-getcipher.js +++ b/test/parallel/test-tls-getcipher.js @@ -52,6 +52,7 @@ server.listen(0, '127.0.0.1', common.mustCall(function() { }, common.mustCall(function() { const cipher = this.getCipher(); assert.strictEqual(cipher.name, 'AES128-SHA256'); + assert.strictEqual(cipher.standardName, 'TLS_RSA_WITH_AES_128_CBC_SHA256'); assert.strictEqual(cipher.version, 'TLSv1.2'); this.end(); })); @@ -65,6 +66,8 @@ server.listen(0, '127.0.0.1', common.mustCall(function() { }, common.mustCall(function() { const cipher = this.getCipher(); assert.strictEqual(cipher.name, 'ECDHE-RSA-AES128-GCM-SHA256'); + assert.strictEqual(cipher.standardName, + 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256'); assert.strictEqual(cipher.version, 'TLSv1.2'); this.end(); })); @@ -86,6 +89,7 @@ tls.createServer({ }, common.mustCall(() => { const cipher = client.getCipher(); assert.strictEqual(cipher.name, 'TLS_AES_128_CCM_8_SHA256'); + assert.strictEqual(cipher.standardName, cipher.name); assert.strictEqual(cipher.version, 'TLSv1.3'); client.end(); })); diff --git a/test/parallel/test-tls-multi-key.js b/test/parallel/test-tls-multi-key.js index c5e66f3980b999..b9eaa05d59feb6 100644 --- a/test/parallel/test-tls-multi-key.js +++ b/test/parallel/test-tls-multi-key.js @@ -157,6 +157,7 @@ function test(options) { }, common.mustCall(function() { assert.deepStrictEqual(ecdsa.getCipher(), { name: 'ECDHE-ECDSA-AES256-GCM-SHA384', + standardName: 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', version: 'TLSv1.2' }); assert.strictEqual(ecdsa.getPeerCertificate().subject.CN, eccCN); @@ -175,6 +176,7 @@ function test(options) { }, common.mustCall(function() { assert.deepStrictEqual(rsa.getCipher(), { name: 'ECDHE-RSA-AES256-GCM-SHA384', + standardName: 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', version: 'TLSv1.2' }); assert.strictEqual(rsa.getPeerCertificate().subject.CN, rsaCN); diff --git a/test/parallel/test-tls-multi-pfx.js b/test/parallel/test-tls-multi-pfx.js index 3b0c0591822adc..c20376a82ad8a8 100644 --- a/test/parallel/test-tls-multi-pfx.js +++ b/test/parallel/test-tls-multi-pfx.js @@ -42,9 +42,11 @@ const server = tls.createServer(options, function(conn) { process.on('exit', function() { assert.deepStrictEqual(ciphers, [{ name: 'ECDHE-ECDSA-AES256-GCM-SHA384', + standardName: 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', version: 'TLSv1.2' }, { name: 'ECDHE-RSA-AES256-GCM-SHA384', + standardName: 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', version: 'TLSv1.2' }]); }); From 71d43a5569175a76992eadf5819f4497e86ed4bc Mon Sep 17 00:00:00 2001 From: legendecas Date: Thu, 21 Nov 2019 00:55:36 +0800 Subject: [PATCH 019/117] worker: add argv constructor option A convenience option to populate `process.argv` in worker threads. PR-URL: https://github.com/nodejs/node/pull/30559 Fixes: https://github.com/nodejs/node/issues/30531 Reviewed-By: Anna Henningsen Reviewed-By: Gireesh Punathil Reviewed-By: Denys Otrishko --- doc/api/worker_threads.md | 7 ++++ lib/internal/main/worker_thread.js | 18 ++++++++- lib/internal/worker.js | 10 ++++- test/parallel/test-worker-process-argv.js | 49 +++++++++++++++++++++++ 4 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 test/parallel/test-worker-process-argv.js diff --git a/doc/api/worker_threads.md b/doc/api/worker_threads.md index b334a1091b47fd..a93bd5422e4ca8 100644 --- a/doc/api/worker_threads.md +++ b/doc/api/worker_threads.md @@ -510,6 +510,9 @@ changes: - version: v13.2.0 pr-url: https://github.com/nodejs/node/pull/26628 description: The `resourceLimits` option was introduced. + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/30559 + description: The `argv` option was introduced. --> * `filename` {string} The path to the Worker’s main script. Must be @@ -518,6 +521,10 @@ changes: If `options.eval` is `true`, this is a string containing JavaScript code rather than a path. * `options` {Object} + * `argv` {any[]} List of arguments which would be stringified and appended to + `process.argv` in the worker. This is mostly similar to the `workerData` + but the values will be available on the global `process.argv` as if they + were passed as CLI options to the script. * `env` {Object} If set, specifies the initial value of `process.env` inside the Worker thread. As a special value, [`worker.SHARE_ENV`][] may be used to specify that the parent thread and the child thread should share their diff --git a/lib/internal/main/worker_thread.js b/lib/internal/main/worker_thread.js index 95fa3026fda90b..97b55ac769fb36 100644 --- a/lib/internal/main/worker_thread.js +++ b/lib/internal/main/worker_thread.js @@ -92,6 +92,7 @@ if (process.env.NODE_CHANNEL_FD) { port.on('message', (message) => { if (message.type === LOAD_SCRIPT) { const { + argv, cwdCounter, filename, doEval, @@ -115,6 +116,9 @@ port.on('message', (message) => { assert(!CJSLoader.hasLoadedAnyUserCJSModule); loadPreloadModules(); initializeFrozenIntrinsics(); + if (argv !== undefined) { + process.argv = process.argv.concat(argv); + } publicWorker.parentPort = publicPort; publicWorker.workerData = workerData; @@ -143,12 +147,22 @@ port.on('message', (message) => { port.postMessage({ type: UP_AND_RUNNING }); if (doEval) { const { evalScript } = require('internal/process/execution'); - evalScript('[worker eval]', filename); + const name = '[worker eval]'; + // This is necessary for CJS module compilation. + // TODO: pass this with something really internal. + ObjectDefineProperty(process, '_eval', { + configurable: true, + enumerable: true, + value: filename, + }); + process.argv.splice(1, 0, name); + evalScript(name, filename); } else { // script filename // runMain here might be monkey-patched by users in --require. // XXX: the monkey-patchability here should probably be deprecated. - CJSLoader.Module.runMain(process.argv[1] = filename); + process.argv.splice(1, 0, filename); + CJSLoader.Module.runMain(filename); } } else if (message.type === STDIO_PAYLOAD) { const { stream, chunk, encoding } = message; diff --git a/lib/internal/worker.js b/lib/internal/worker.js index 621dfa77693168..fb033b24729479 100644 --- a/lib/internal/worker.js +++ b/lib/internal/worker.js @@ -82,9 +82,16 @@ class Worker extends EventEmitter { validateString(filename, 'filename'); if (options.execArgv && !ArrayIsArray(options.execArgv)) { throw new ERR_INVALID_ARG_TYPE('options.execArgv', - 'array', + 'Array', options.execArgv); } + let argv; + if (options.argv) { + if (!ArrayIsArray(options.argv)) { + throw new ERR_INVALID_ARG_TYPE('options.argv', 'Array', options.argv); + } + argv = options.argv.map(String); + } if (!options.eval) { if (!path.isAbsolute(filename) && !/^\.\.?[\\/]/.test(filename)) { throw new ERR_WORKER_PATH(filename); @@ -154,6 +161,7 @@ class Worker extends EventEmitter { this[kPublicPort].on('message', (message) => this.emit('message', message)); setupPortReferencing(this[kPublicPort], this, 'message'); this[kPort].postMessage({ + argv, type: messageTypes.LOAD_SCRIPT, filename, doEval: !!options.eval, diff --git a/test/parallel/test-worker-process-argv.js b/test/parallel/test-worker-process-argv.js new file mode 100644 index 00000000000000..ebdebe02ab855c --- /dev/null +++ b/test/parallel/test-worker-process-argv.js @@ -0,0 +1,49 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const { Worker, isMainThread, workerData } = require('worker_threads'); + +if (isMainThread) { + assert.throws(() => { + new Worker(__filename, { argv: 'foo' }); + }, { + code: 'ERR_INVALID_ARG_TYPE' + }); + + [ + new Worker(__filename, { + argv: [null, 'foo', 123, Symbol('bar')], + // Asserts only if the worker is started by the test. + workerData: 'assert-argv' + }), + new Worker(` + const assert = require('assert'); + assert.deepStrictEqual( + process.argv, + [process.execPath, '[worker eval]'] + ); + `, { + eval: true + }), + new Worker(` + const assert = require('assert'); + assert.deepStrictEqual( + process.argv, + [process.execPath, '[worker eval]', 'null', 'foo', '123', + String(Symbol('bar'))] + ); + `, { + argv: [null, 'foo', 123, Symbol('bar')], + eval: true + }) + ].forEach((worker) => { + worker.on('exit', common.mustCall((code) => { + assert.strictEqual(code, 0); + })); + }); +} else if (workerData === 'assert-argv') { + assert.deepStrictEqual( + process.argv, + [process.execPath, __filename, 'null', 'foo', '123', String(Symbol('bar'))] + ); +} From 60b1e1ad6197d3f4db94b33a8adb4d6569bc7114 Mon Sep 17 00:00:00 2001 From: Rongjian Zhang Date: Fri, 22 Nov 2019 14:01:21 +0800 Subject: [PATCH 020/117] fs: fix existsSync for invalid symlink at win32 Fixes: https://github.com/nodejs/node/issues/30538 PR-URL: https://github.com/nodejs/node/pull/30556 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell --- lib/fs.js | 11 +++++++++- test/parallel/test-fs-symlink-dir-junction.js | 17 ++++++++++++++ test/parallel/test-fs-symlink-dir.js | 22 +++++++++++++++++++ test/parallel/test-fs-symlink.js | 12 ++++++++++ 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/lib/fs.js b/lib/fs.js index 6a5ebb8203af15..de37a0c2a0a704 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -234,7 +234,16 @@ function existsSync(path) { return false; } const ctx = { path }; - binding.access(pathModule.toNamespacedPath(path), F_OK, undefined, ctx); + const nPath = pathModule.toNamespacedPath(path); + binding.access(nPath, F_OK, undefined, ctx); + + // In case of an invalid symlink, `binding.access()` on win32 + // will **not** return an error and is therefore not enough. + // Double check with `binding.stat()`. + if (isWindows && ctx.errno === undefined) { + binding.stat(nPath, false, undefined, ctx); + } + return ctx.errno === undefined; } diff --git a/test/parallel/test-fs-symlink-dir-junction.js b/test/parallel/test-fs-symlink-dir-junction.js index fc89ad368401e4..42d6bc1214132b 100644 --- a/test/parallel/test-fs-symlink-dir-junction.js +++ b/test/parallel/test-fs-symlink-dir-junction.js @@ -53,3 +53,20 @@ fs.symlink(linkData, linkPath, 'junction', common.mustCall(function(err) { })); })); })); + +// Test invalid symlink +{ + const linkData = fixtures.path('/not/exists/dir'); + const linkPath = path.join(tmpdir.path, 'invalid_junction_link'); + + fs.symlink(linkData, linkPath, 'junction', common.mustCall(function(err) { + assert.ifError(err); + + assert(!fs.existsSync(linkPath)); + + fs.unlink(linkPath, common.mustCall(function(err) { + assert.ifError(err); + assert(!fs.existsSync(linkPath)); + })); + })); +} diff --git a/test/parallel/test-fs-symlink-dir.js b/test/parallel/test-fs-symlink-dir.js index 1ab1361a43fb9b..707bc5b486d723 100644 --- a/test/parallel/test-fs-symlink-dir.js +++ b/test/parallel/test-fs-symlink-dir.js @@ -44,3 +44,25 @@ for (const linkTarget of linkTargets) { testAsync(linkTarget, `${linkPath}-${path.basename(linkTarget)}-async`); } } + +// Test invalid symlink +{ + function testSync(target, path) { + fs.symlinkSync(target, path); + assert(!fs.existsSync(path)); + } + + function testAsync(target, path) { + fs.symlink(target, path, common.mustCall((err) => { + assert.ifError(err); + assert(!fs.existsSync(path)); + })); + } + + for (const linkTarget of linkTargets.map((p) => p + '-broken')) { + for (const linkPath of linkPaths) { + testSync(linkTarget, `${linkPath}-${path.basename(linkTarget)}-sync`); + testAsync(linkTarget, `${linkPath}-${path.basename(linkTarget)}-async`); + } + } +} diff --git a/test/parallel/test-fs-symlink.js b/test/parallel/test-fs-symlink.js index a6001103190aad..c52ffbc105ffae 100644 --- a/test/parallel/test-fs-symlink.js +++ b/test/parallel/test-fs-symlink.js @@ -58,6 +58,18 @@ fs.symlink(linkData, linkPath, common.mustCall(function(err) { })); })); +// Test invalid symlink +{ + const linkData = fixtures.path('/not/exists/file'); + const linkPath = path.join(tmpdir.path, 'symlink2.js'); + + fs.symlink(linkData, linkPath, common.mustCall(function(err) { + assert.ifError(err); + + assert(!fs.existsSync(linkPath)); + })); +} + [false, 1, {}, [], null, undefined].forEach((input) => { const errObj = { code: 'ERR_INVALID_ARG_TYPE', From 2c0f1edfd535c489107b644b28f1ade59c6a8d84 Mon Sep 17 00:00:00 2001 From: Shobhit Chittora Date: Thu, 14 Nov 2019 17:37:11 +0530 Subject: [PATCH 021/117] doc: adds assert doc for strict mode with pointer to strict equality Refs: https://github.com/nodejs/node/issues/30485 PR-URL: https://github.com/nodejs/node/pull/30486 Reviewed-By: Ruben Bridgewater Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat Reviewed-By: Gireesh Punathil --- doc/api/assert.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/api/assert.md b/doc/api/assert.md index b0c8c378e64b9b..9d1a7fb7e169ea 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -80,9 +80,9 @@ changes: description: Added strict mode to the assert module. --> -In `strict` mode, `assert` functions use the comparison in the corresponding -strict functions. For example, [`assert.deepEqual()`][] will behave like -[`assert.deepStrictEqual()`][]. +In `strict` mode (not to be confused with `"use strict"`), `assert` functions +use the comparison in the corresponding strict functions. For example, +[`assert.deepEqual()`][] will behave like [`assert.deepStrictEqual()`][]. In `strict` mode, error messages for objects display a diff. In legacy mode, error messages for objects display the objects, often truncated. From 543bf9d8ea00b9d97530dd9f7858b4254ef45cfb Mon Sep 17 00:00:00 2001 From: NickNaso Date: Tue, 26 Nov 2019 11:59:41 +0100 Subject: [PATCH 022/117] doc: fix up N-API doc PR-URL: https://github.com/nodejs/node/pull/30656 Reviewed-By: Michael Dawson Reviewed-By: Chengzhong Wu --- doc/api/n-api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 3b6fb9a97bfba0..d89ac03ccdc102 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -4380,7 +4380,7 @@ allows them to avoid blocking overall execution of the Node.js application. N-API provides an ABI-stable interface for these supporting functions which covers the most common asynchronous use cases. -N-API defines the `napi_work` structure which is used to manage +N-API defines the `napi_async_work` structure which is used to manage asynchronous workers. Instances are created/deleted with [`napi_create_async_work`][] and [`napi_delete_async_work`][]. @@ -4947,7 +4947,7 @@ napiVersion: 2 ```C NAPI_EXTERN napi_status napi_get_uv_event_loop(napi_env env, - uv_loop_t** loop); + struct uv_loop_s** loop); ``` * `[in] env`: The environment that the API is invoked under. From 510eb3a6ebf10f3e289d20e09c59aa01d8d9dbcd Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sun, 1 Dec 2019 21:06:17 -0800 Subject: [PATCH 023/117] doc: revise addons introduction for brevity and clarity PR-URL: https://github.com/nodejs/node/pull/30756 Reviewed-By: Daniel Bevenius Reviewed-By: Beth Griggs Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca --- doc/api/addons.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/api/addons.md b/doc/api/addons.md index 6e5e9bf18c8418..8b17d6b417b8e8 100644 --- a/doc/api/addons.md +++ b/doc/api/addons.md @@ -3,10 +3,9 @@ -Node.js Addons are dynamically-linked shared objects, written in C++, that -can be loaded into Node.js using the [`require()`][require] function, and used -just as if they were an ordinary Node.js module. They are used primarily to -provide an interface between JavaScript running in Node.js and C/C++ libraries. +Addons are dynamically-linked shared objects written in C++. The +[`require()`][require] function can load Addons as ordinary Node.js modules. +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 From 7cb84fdbe503e38d9b118a1d10323ed41feaa193 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sun, 1 Dec 2019 22:12:44 -0800 Subject: [PATCH 024/117] doc: remove usage of "Node" in favor of "Node.js" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In accordance with the Style Guide, remove "Node" in favor of "Node.js". A lint rule for this is forthcoming. PR-URL: https://github.com/nodejs/node/pull/30758 Reviewed-By: Jiawen Geng Reviewed-By: Michaël Zasso Reviewed-By: David Carlier Reviewed-By: Beth Griggs Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Richard Lau Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca --- SECURITY.md | 4 ++-- doc/STYLE_GUIDE.md | 2 +- doc/api/fs.md | 8 ++++---- doc/guides/contributing/pull-requests.md | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 7e984b7ba36872..3196055ccb78e5 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -23,8 +23,8 @@ the HackerOne platform. See for further details. ## Reporting a Bug in a third party module Security bugs in third party modules should be reported to their respective -maintainers and should also be coordinated through the Node Ecosystem Security -Team via [HackerOne](https://hackerone.com/nodejs-ecosystem). +maintainers and should also be coordinated through the Node.js Ecosystem +Security Team via [HackerOne](https://hackerone.com/nodejs-ecosystem). Details regarding this process can be found in the [Security Working Group repository](https://github.com/nodejs/security-wg/blob/master/processes/third_party_vuln_process.md). diff --git a/doc/STYLE_GUIDE.md b/doc/STYLE_GUIDE.md index 6f98ad1fc8fb4e..9784787428dbf1 100644 --- a/doc/STYLE_GUIDE.md +++ b/doc/STYLE_GUIDE.md @@ -55,9 +55,9 @@ * OK: JavaScript, Google's V8 * NOT OK: Javascript, Google's v8 - * Use _Node.js_ and not _Node_, _NodeJS_, or similar variants. + * When referring to the executable, _`node`_ is acceptable. See also API documentation structure overview in [doctools README][]. diff --git a/doc/api/fs.md b/doc/api/fs.md index 9a91f9f22082e0..643efaae03395d 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -3473,10 +3473,10 @@ completion callback. The `type` argument is only available on Windows and ignored on other platforms. It can be set to `'dir'`, `'file'`, or `'junction'`. If the `type` argument is -not set, Node will autodetect `target` type and use `'file'` or `'dir'`. If the -`target` does not exist, `'file'` will be used. Windows junction points require -the destination path to be absolute. When using `'junction'`, the `target` -argument will automatically be normalized to absolute path. +not set, Node.js will autodetect `target` type and use `'file'` or `'dir'`. If +the `target` does not exist, `'file'` will be used. Windows junction points +require the destination path to be absolute. When using `'junction'`, the +`target` argument will automatically be normalized to absolute path. Relative targets are relative to the link’s parent directory. diff --git a/doc/guides/contributing/pull-requests.md b/doc/guides/contributing/pull-requests.md index 31e3ba64757c12..cabc548be02556 100644 --- a/doc/guides/contributing/pull-requests.md +++ b/doc/guides/contributing/pull-requests.md @@ -49,7 +49,7 @@ In case of doubt, open an issue in the Node.js has two IRC channels: [#Node.js](https://webchat.freenode.net/?channels=node.js) for general help and questions, and -[#Node-dev](https://webchat.freenode.net/?channels=node-dev) for development of +[#node-dev](https://webchat.freenode.net/?channels=node-dev) for development of Node.js core specifically. ## Setting up your local environment From d3f0dd21484715ef961d126e7dbdb88a5cf01120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Sat, 30 Nov 2019 14:20:48 +0100 Subject: [PATCH 025/117] inspector: do not access queueMicrotask from global Grab it from the internal module where it's defined instead. PR-URL: https://github.com/nodejs/node/pull/30732 Reviewed-By: Colin Ihrig Reviewed-By: Anto Aravinth Reviewed-By: Trivikram Kamat Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell --- lib/inspector.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/inspector.js b/lib/inspector.js index 107500938377ce..b2bad040ceae79 100644 --- a/lib/inspector.js +++ b/lib/inspector.js @@ -22,6 +22,7 @@ if (!hasInspector) throw new ERR_INSPECTOR_NOT_AVAILABLE(); const EventEmitter = require('events'); +const { queueMicrotask } = require('internal/process/task_queues'); const { validateString } = require('internal/validators'); const { isMainThread } = require('worker_threads'); From 54a266c8781a4f5a96be910ac800aa2fb2b850e1 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Mon, 2 Dec 2019 05:21:37 -0800 Subject: [PATCH 026/117] test: increase debugging information in subprocess test Refs: https://github.com/nodejs/node/issues/25988#issuecomment-560394046 PR-URL: https://github.com/nodejs/node/pull/30761 Reviewed-By: Gireesh Punathil Reviewed-By: Colin Ihrig Reviewed-By: Anna Henningsen Reviewed-By: Luigi Pinca --- test/parallel/test-child-process-pipe-dataflow.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/parallel/test-child-process-pipe-dataflow.js b/test/parallel/test-child-process-pipe-dataflow.js index abaec73f3ea507..bc5e4e02fdf4e9 100644 --- a/test/parallel/test-child-process-pipe-dataflow.js +++ b/test/parallel/test-child-process-pipe-dataflow.js @@ -37,6 +37,14 @@ const MB = KB * KB; cat.stdout._handle.readStart = common.mustNotCall(); grep.stdout._handle.readStart = common.mustNotCall(); + // Keep an array of error codes and assert on them during process exit. This + // is because stdio can still be open when a child process exits, and we don't + // want to lose information about what caused the error. + const errors = []; + process.on('exit', () => { + assert.deepStrictEqual(errors, []); + }); + [cat, grep, wc].forEach((child, index) => { const errorHandler = (thing, type) => { // Don't want to assert here, as we might miss error code info. @@ -46,7 +54,9 @@ const MB = KB * KB; child.stderr.on('data', (d) => { errorHandler(d, 'data'); }); child.on('error', (err) => { errorHandler(err, 'error'); }); child.on('exit', common.mustCall((code) => { - assert.strictEqual(code, 0, `child ${index} exited with code ${code}`); + if (code !== 0) { + errors.push(`child ${index} exited with code ${code}`); + } })); }); From 7b9400ce63dc046a4d8166e0b8bf491606b59186 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Mon, 2 Dec 2019 05:26:39 -0800 Subject: [PATCH 027/117] tools: update ESLint to 6.7.2 PR-URL: https://github.com/nodejs/node/pull/30762 Reviewed-By: Colin Ihrig Reviewed-By: Trivikram Kamat --- tools/node_modules/eslint/README.md | 2 +- .../eslint/lib/cli-engine/file-enumerator.js | 18 +++- .../lib/rules/no-unexpected-multiline.js | 8 ++ .../eslint/lib/source-code/source-code.js | 82 +++++++++++++------ tools/node_modules/eslint/package.json | 2 +- 5 files changed, 81 insertions(+), 31 deletions(-) diff --git a/tools/node_modules/eslint/README.md b/tools/node_modules/eslint/README.md index b7cc385f0e35c7..0e574e5b2d2e18 100644 --- a/tools/node_modules/eslint/README.md +++ b/tools/node_modules/eslint/README.md @@ -265,7 +265,7 @@ The following companies, organizations, and individuals support ESLint's ongoing

Gold Sponsors

Shopify Salesforce Badoo Airbnb Facebook Open Source

Silver Sponsors

AMP Project

Bronze Sponsors

-

Bugsnag Stability Monitoring Crosswordsolver Codacy Mixpanel VPS Server Free Icons by Icons8 UI UX Design Agencies clay Discord ThemeIsle TekHattan Marfeel Fire Stick Tricks JSHeroes

+

UI UX Design Agencies EduBirdie Crosswordsolver Codacy Mixpanel VPS Server Free Icons by Icons8 Bugsnag Stability Monitoring clay Discord ThemeIsle TekHattan Marfeel Fire Stick Tricks JSHeroes

## Technology Sponsors diff --git a/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js b/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js index 700f8009cf88f2..b5a082b71a6bc8 100644 --- a/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js +++ b/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js @@ -375,9 +375,6 @@ class FileEnumerator { * @private */ *_iterateFilesRecursive(directoryPath, options) { - if (this._isIgnoredFile(directoryPath + path.sep, options)) { - return; - } debug(`Enter the directory: ${directoryPath}`); const { configArrayFactory, extensionRegExp } = internalSlotsMap.get(this); @@ -426,7 +423,20 @@ class FileEnumerator { // Dive into the sub directory. } else if (options.recursive && stat && stat.isDirectory()) { - yield* this._iterateFilesRecursive(filePath, options); + if (!config) { + config = configArrayFactory.getConfigArrayForFile( + filePath, + { ignoreNotFoundError: true } + ); + } + const ignored = this._isIgnoredFile( + filePath + path.sep, + { ...options, config } + ); + + if (!ignored) { + yield* this._iterateFilesRecursive(filePath, options); + } } } 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 8026e1722236ff..eb72008a2947e7 100644 --- a/tools/node_modules/eslint/lib/rules/no-unexpected-multiline.js +++ b/tools/node_modules/eslint/lib/rules/no-unexpected-multiline.js @@ -74,6 +74,14 @@ module.exports = { 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; + } + context.report({ node, loc: node.loc.start, messageId: "taggedTemplate" }); }, diff --git a/tools/node_modules/eslint/lib/source-code/source-code.js b/tools/node_modules/eslint/lib/source-code/source-code.js index 20b442f2367203..30b4e9ab5c26e3 100644 --- a/tools/node_modules/eslint/lib/source-code/source-code.js +++ b/tools/node_modules/eslint/lib/source-code/source-code.js @@ -90,6 +90,56 @@ function nodesOrTokensOverlap(first, second) { (second.range[0] <= first.range[0] && second.range[1] >= first.range[0]); } +/** + * Determines if two nodes or tokens have at least one whitespace character + * between them. Order does not matter. Returns false if the given nodes or + * tokens overlap. + * @param {SourceCode} sourceCode The source code object. + * @param {ASTNode|Token} first The first node or token to check between. + * @param {ASTNode|Token} second The second node or token to check between. + * @param {boolean} checkInsideOfJSXText If `true` is present, check inside of JSXText tokens for backward compatibility. + * @returns {boolean} True if there is a whitespace character between + * any of the tokens found between the two given nodes or tokens. + * @public + */ +function isSpaceBetween(sourceCode, first, second, checkInsideOfJSXText) { + if (nodesOrTokensOverlap(first, second)) { + return false; + } + + const [startingNodeOrToken, endingNodeOrToken] = first.range[1] <= second.range[0] + ? [first, second] + : [second, first]; + const firstToken = sourceCode.getLastToken(startingNodeOrToken) || startingNodeOrToken; + const finalToken = sourceCode.getFirstToken(endingNodeOrToken) || endingNodeOrToken; + let currentToken = firstToken; + + while (currentToken !== finalToken) { + const nextToken = sourceCode.getTokenAfter(currentToken, { includeComments: true }); + + if ( + currentToken.range[1] !== nextToken.range[0] || + + /* + * For backward compatibility, check speces in JSXText. + * https://github.com/eslint/eslint/issues/12614 + */ + ( + checkInsideOfJSXText && + nextToken !== finalToken && + nextToken.type === "JSXText" && + /\s/u.test(nextToken.value) + ) + ) { + return true; + } + + currentToken = nextToken; + } + + return false; +} + //------------------------------------------------------------------------------ // Public Interface //------------------------------------------------------------------------------ @@ -433,42 +483,24 @@ class SourceCode extends TokenStore { * @public */ isSpaceBetween(first, second) { - if (nodesOrTokensOverlap(first, second)) { - return false; - } - - const [startingNodeOrToken, endingNodeOrToken] = first.range[1] <= second.range[0] - ? [first, second] - : [second, first]; - const firstToken = this.getLastToken(startingNodeOrToken) || startingNodeOrToken; - const finalToken = this.getFirstToken(endingNodeOrToken) || endingNodeOrToken; - let currentToken = firstToken; - - while (currentToken !== finalToken) { - const nextToken = this.getTokenAfter(currentToken, { includeComments: true }); - - if (currentToken.range[1] !== nextToken.range[0]) { - return true; - } - - currentToken = nextToken; - } - - return false; + return isSpaceBetween(this, first, second, false); } /** * Determines if two nodes or tokens have at least one whitespace character * between them. Order does not matter. Returns false if the given nodes or * tokens overlap. - * @param {...ASTNode|Token} args The nodes or tokens to check between. + * For backward compatibility, this method returns true if there are + * `JSXText` tokens that contain whitespaces between the two. + * @param {ASTNode|Token} first The first node or token to check between. + * @param {ASTNode|Token} second The second node or token to check between. * @returns {boolean} True if there is a whitespace character between * any of the tokens found between the two given nodes or tokens. * @deprecated in favor of isSpaceBetween(). * @public */ - isSpaceBetweenTokens(...args) { - return this.isSpaceBetween(...args); + isSpaceBetweenTokens(first, second) { + return isSpaceBetween(this, first, second, true); } /** diff --git a/tools/node_modules/eslint/package.json b/tools/node_modules/eslint/package.json index 5fbc11817b879d..0abd303e051b44 100644 --- a/tools/node_modules/eslint/package.json +++ b/tools/node_modules/eslint/package.json @@ -153,5 +153,5 @@ "test:cli": "mocha", "webpack": "node Makefile.js webpack" }, - "version": "6.7.1" + "version": "6.7.2" } \ No newline at end of file From eb4f443a5afaacf1b81ecb6d87dd2697a1f944d0 Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Wed, 27 Nov 2019 01:54:23 -0500 Subject: [PATCH 028/117] esm: make specifier flag clearly experimental `--es-module-specifier-resolution` is the only flagged portion of the ESM implementation that does not have the word experimental in the flag name. This commit changes the flag to: `--experimental-specifier-resolution` `--es-module-specifier-resolution` remains as an alias for backwards compatibility but it is no longer documented. PR-URL: https://github.com/nodejs/node/pull/30678 Reviewed-By: Jan Krems Reviewed-By: Guy Bedford --- doc/api/cli.md | 30 +++++++++---------- doc/api/esm.md | 4 +-- doc/node.1 | 6 ++-- lib/internal/modules/esm/default_resolve.js | 12 +++++--- src/module_wrap.cc | 4 +-- src/node_options.cc | 26 +++++++++++++--- src/node_options.h | 1 + .../test-esm-specifiers-both-flags.mjs | 16 ++++++++++ .../test-esm-specifiers-legacy-flag.mjs | 18 +++++++++++ test/es-module/test-esm-specifiers.mjs | 2 +- ...rocess-env-allowed-flags-are-documented.js | 1 + 11 files changed, 89 insertions(+), 31 deletions(-) create mode 100644 test/es-module/test-esm-specifiers-both-flags.mjs create mode 100644 test/es-module/test-esm-specifiers-legacy-flag.mjs diff --git a/doc/api/cli.md b/doc/api/cli.md index ad8f86f86121b4..d4b4da5249a16b 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -156,20 +156,6 @@ Enable experimental Source Map V3 support for stack traces. Currently, overriding `Error.prepareStackTrace` is ignored when the `--enable-source-maps` flag is set. -### `--es-module-specifier-resolution=mode` - - -Sets the resolution algorithm for resolving ES module specifiers. Valid options -are `explicit` and `node`. - -The default is `explicit`, which requires providing the full path to a -module. The `node` mode will enable support for optional file extensions and -the ability to import a directory that has an index file. - -Please see [customizing ESM specifier resolution][] for example usage. - ### `--experimental-conditional-exports` + +Sets the resolution algorithm for resolving ES module specifiers. Valid options +are `explicit` and `node`. + +The default is `explicit`, which requires providing the full path to a +module. The `node` mode will enable support for optional file extensions and +the ability to import a directory that has an index file. + +Please see [customizing ESM specifier resolution][] for example usage. + ### `--experimental-vm-modules` * `--enable-fips` * `--enable-source-maps` -* `--es-module-specifier-resolution` * `--experimental-conditional-exports` * `--experimental-json-modules` * `--experimental-loader` @@ -1054,6 +1053,7 @@ Node.js options that are allowed are: * `--experimental-repl-await` * `--experimental-report` * `--experimental-resolve-self` +* `--experimental-specifier-resolution` * `--experimental-vm-modules` * `--experimental-wasi-unstable-preview0` * `--experimental-wasm-modules` diff --git a/doc/api/esm.md b/doc/api/esm.md index 93b89adec12a98..f834f29fbbee85 100644 --- a/doc/api/esm.md +++ b/doc/api/esm.md @@ -1372,7 +1372,7 @@ the CommonJS loader. One of the behavior differences is automatic resolution of file extensions and the ability to import directories that have an index file. -The `--es-module-specifier-resolution=[mode]` flag can be used to customize +The `--experimental-specifier-resolution=[mode]` flag can be used to customize the extension resolution algorithm. The default mode is `explicit`, which requires the full path to a module be provided to the loader. To enable the automatic extension resolution and importing from directories that include an @@ -1383,7 +1383,7 @@ $ node index.mjs success! $ node index # Failure! Error: Cannot find module -$ node --es-module-specifier-resolution=node index +$ node --experimental-specifier-resolution=node index success! ``` diff --git a/doc/node.1 b/doc/node.1 index 714772336e07c1..5f98ba709121fd 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -110,9 +110,6 @@ Enable FIPS-compliant crypto at startup. Requires Node.js to be built with .Sy ./configure --openssl-fips . . -.It Fl -es-module-specifier-resolution -Select extension resolution algorithm for ES Modules; either 'explicit' (default) or 'node' -. .It Fl -experimental-conditional-exports Enable experimental support for "require" and "node" conditional export targets. . @@ -130,6 +127,9 @@ Enable experimental top-level .Sy await 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 diff --git a/lib/internal/modules/esm/default_resolve.js b/lib/internal/modules/esm/default_resolve.js index 169c6f35694f24..c9ef3883c40412 100644 --- a/lib/internal/modules/esm/default_resolve.js +++ b/lib/internal/modules/esm/default_resolve.js @@ -13,8 +13,8 @@ const { getOptionValue } = require('internal/options'); const preserveSymlinks = getOptionValue('--preserve-symlinks'); const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main'); const experimentalJsonModules = getOptionValue('--experimental-json-modules'); -const esModuleSpecifierResolution = - getOptionValue('--es-module-specifier-resolution'); +const experimentalSpeciferResolution = + getOptionValue('--experimental-specifier-resolution'); const typeFlag = getOptionValue('--input-type'); const experimentalWasmModules = getOptionValue('--experimental-wasm-modules'); const { resolve: moduleWrapResolve, @@ -110,10 +110,14 @@ function resolve(specifier, parentURL) { if (ext === '.js' || (!format && isMain)) format = getPackageType(url.href) === TYPE_MODULE ? 'module' : 'commonjs'; if (!format) { - if (esModuleSpecifierResolution === 'node') + if (experimentalSpeciferResolution === 'node') { + process.emitWarning( + 'The Node.js specifier resolution in ESM is experimental.', + 'ExperimentalWarning'); format = legacyExtensionFormatMap[ext]; - else + } else { throw new ERR_UNKNOWN_FILE_EXTENSION(fileURLToPath(url)); + } } return { url: `${url}`, format }; } diff --git a/src/module_wrap.cc b/src/module_wrap.cc index 5745cce9e099ab..3c3d568329221d 100644 --- a/src/module_wrap.cc +++ b/src/module_wrap.cc @@ -789,7 +789,7 @@ inline Maybe ResolveIndex(const URL& search) { Maybe FinalizeResolution(Environment* env, const URL& resolved, const URL& base) { - if (env->options()->es_module_specifier_resolution == "node") { + if (env->options()->experimental_specifier_resolution == "node") { Maybe file = ResolveExtensions(resolved); if (!file.IsNothing()) { return file; @@ -1053,7 +1053,7 @@ Maybe PackageMainResolve(Environment* env, return Just(resolved); } } - if (env->options()->es_module_specifier_resolution == "node") { + if (env->options()->experimental_specifier_resolution == "node") { if (pcfg.has_main == HasMain::Yes) { return FinalizeResolution(env, URL(pcfg.main, pjson_url), base); } else { diff --git a/src/node_options.cc b/src/node_options.cc index 498bedd1e5e892..abf26fb78198e8 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -128,9 +128,23 @@ void EnvironmentOptions::CheckOptions(std::vector* errors) { } if (!es_module_specifier_resolution.empty()) { - if (es_module_specifier_resolution != "node" && - es_module_specifier_resolution != "explicit") { - errors->push_back("invalid value for --es-module-specifier-resolution"); + if (!experimental_specifier_resolution.empty()) { + errors->push_back( + "bad option: cannot use --es-module-specifier-resolution" + " and --experimental-specifier-resolution at the same time"); + } else { + experimental_specifier_resolution = es_module_specifier_resolution; + if (experimental_specifier_resolution != "node" && + experimental_specifier_resolution != "explicit") { + errors->push_back( + "invalid value for --es-module-specifier-resolution"); + } + } + } else if (!experimental_specifier_resolution.empty()) { + if (experimental_specifier_resolution != "node" && + experimental_specifier_resolution != "explicit") { + errors->push_back( + "invalid value for --experimental-specifier-resolution"); } } @@ -365,9 +379,13 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { "set module type for string input", &EnvironmentOptions::module_type, kAllowedInEnvironment); - AddOption("--es-module-specifier-resolution", + AddOption("--experimental-specifier-resolution", "Select extension resolution algorithm for es modules; " "either 'explicit' (default) or 'node'", + &EnvironmentOptions::experimental_specifier_resolution, + kAllowedInEnvironment); + AddOption("--es-module-specifier-resolution", + "", &EnvironmentOptions::es_module_specifier_resolution, kAllowedInEnvironment); AddOption("--no-deprecation", diff --git a/src/node_options.h b/src/node_options.h index fea912da446568..c4cb5dc04f18cb 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -104,6 +104,7 @@ class EnvironmentOptions : public Options { bool experimental_conditional_exports = false; bool experimental_json_modules = false; bool experimental_resolve_self = false; + std::string experimental_specifier_resolution; std::string es_module_specifier_resolution; bool experimental_wasm_modules = false; std::string module_type; diff --git a/test/es-module/test-esm-specifiers-both-flags.mjs b/test/es-module/test-esm-specifiers-both-flags.mjs new file mode 100644 index 00000000000000..fc5c7fcd0e98a9 --- /dev/null +++ b/test/es-module/test-esm-specifiers-both-flags.mjs @@ -0,0 +1,16 @@ +import { mustCall } from '../common/index.mjs'; +import { exec } from 'child_process'; +import assert from 'assert'; + +const expectedError = + 'cannot use --es-module-specifier-resolution ' + + 'and --experimental-specifier-resolution at the same time'; + +const flags = '--es-module-specifier-resolution=node ' + + '--experimental-specifier-resolution=node'; + +exec(`${process.execPath} ${flags}`, { + timeout: 300 +}, mustCall((error) => { + assert(error.message.includes(expectedError)); +})); diff --git a/test/es-module/test-esm-specifiers-legacy-flag.mjs b/test/es-module/test-esm-specifiers-legacy-flag.mjs new file mode 100644 index 00000000000000..fcf0c915b649f0 --- /dev/null +++ b/test/es-module/test-esm-specifiers-legacy-flag.mjs @@ -0,0 +1,18 @@ +// Flags: --es-module-specifier-resolution=node +import '../common/index.mjs'; +import assert from 'assert'; + +// commonJS index.js +import commonjs from '../fixtures/es-module-specifiers/package-type-commonjs'; +// esm index.js +import module from '../fixtures/es-module-specifiers/package-type-module'; +// Notice the trailing slash +import success, { explicit, implicit, implicitModule } + from '../fixtures/es-module-specifiers/'; + +assert.strictEqual(commonjs, 'commonjs'); +assert.strictEqual(module, 'module'); +assert.strictEqual(success, 'success'); +assert.strictEqual(explicit, 'esm'); +assert.strictEqual(implicit, 'cjs'); +assert.strictEqual(implicitModule, 'cjs'); diff --git a/test/es-module/test-esm-specifiers.mjs b/test/es-module/test-esm-specifiers.mjs index fdf9e5b25ecea4..5e436f21b74cc6 100644 --- a/test/es-module/test-esm-specifiers.mjs +++ b/test/es-module/test-esm-specifiers.mjs @@ -1,4 +1,4 @@ -// Flags: --es-module-specifier-resolution=node +// Flags: --experimental-specifier-resolution=node import { mustNotCall } from '../common/index.mjs'; import assert from 'assert'; import path from 'path'; 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 2e0d67eefcb242..f356f88fe9c740 100644 --- a/test/parallel/test-process-env-allowed-flags-are-documented.js +++ b/test/parallel/test-process-env-allowed-flags-are-documented.js @@ -85,6 +85,7 @@ const undocumented = difference(process.allowedNodeEnvironmentFlags, documented); // Remove intentionally undocumented options. assert(undocumented.delete('--debug-arraybuffer-allocations')); +assert(undocumented.delete('--es-module-specifier-resolution')); assert(undocumented.delete('--experimental-worker')); assert(undocumented.delete('--no-node-snapshot')); assert(undocumented.delete('--loader')); From 55a270b5837b2c4a2a63fc6a7ef4dcd85856a3bd Mon Sep 17 00:00:00 2001 From: Richard Lau Date: Mon, 2 Dec 2019 13:23:31 -0500 Subject: [PATCH 029/117] test: remove duplicate entries from root.status PR-URL: https://github.com/nodejs/node/pull/30769 Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Rich Trott Reviewed-By: Luigi Pinca Reviewed-By: Jiawen Geng Reviewed-By: Beth Griggs --- test/root.status | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/root.status b/test/root.status index 25400990b68af8..91aad08caa3527 100644 --- a/test/root.status +++ b/test/root.status @@ -1,11 +1,7 @@ [$mode==debug] async-hooks/test-callback-error: SLOW -async-hooks/test-callback-error: SLOW -async-hooks/test-emit-init: SLOW async-hooks/test-emit-init: SLOW async-hooks/test-querywrap: SLOW -async-hooks/test-querywrap: SLOW -async-hooks/test-tlswrap: SLOW async-hooks/test-tlswrap: SLOW message/eval_messages: SLOW message/stdin_messages: SLOW From 851f3135aba0fdbf0fc89f1ef346adf438f4c399 Mon Sep 17 00:00:00 2001 From: Rongjian Zhang Date: Sun, 24 Nov 2019 12:40:40 +0800 Subject: [PATCH 030/117] module: add warnings for experimental flags PR-URL: https://github.com/nodejs/node/pull/30617 Fixes: https://github.com/nodejs/node/issues/30600 Reviewed-By: Guy Bedford --- lib/internal/modules/cjs/loader.js | 15 ++++++--- lib/internal/modules/esm/translators.js | 4 ++- src/module_wrap.cc | 3 ++ src/node_process.h | 2 ++ src/node_process_events.cc | 16 ++++++++++ test/common/fixtures.mjs | 16 ++++++++++ test/es-module/test-esm-exports.mjs | 32 +++++++++++++++++++ test/es-module/test-esm-json.mjs | 24 +++++++++++++- test/es-module/test-esm-wasm.mjs | 24 +++++++++++++- .../es-modules/conditional-exports.js | 1 + test/fixtures/es-modules/json-modules.mjs | 1 + test/fixtures/es-modules/wasm-modules.mjs | 2 ++ .../node_modules/pkgexports/resolve-self.js | 1 + 13 files changed, 133 insertions(+), 8 deletions(-) create mode 100644 test/common/fixtures.mjs create mode 100644 test/fixtures/es-modules/conditional-exports.js create mode 100644 test/fixtures/es-modules/json-modules.mjs create mode 100644 test/fixtures/es-modules/wasm-modules.mjs create mode 100644 test/fixtures/node_modules/pkgexports/resolve-self.js diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index d962bc2a4cec30..11e3d59f781dc3 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -43,7 +43,7 @@ const { rekeySourceMap } = require('internal/source_map/source_map_cache'); const { pathToFileURL, fileURLToPath, URL } = require('internal/url'); -const { deprecate } = require('internal/util'); +const { deprecate, emitExperimentalWarning } = require('internal/util'); const vm = require('vm'); const assert = require('internal/assert'); const fs = require('fs'); @@ -584,8 +584,10 @@ function resolveExportsTarget(pkgPath, target, subpath, basePath, mappingKey) { if (experimentalConditionalExports && ObjectPrototypeHasOwnProperty(target, 'require')) { try { - return resolveExportsTarget(pkgPath, target.require, subpath, - basePath, mappingKey); + const result = resolveExportsTarget(pkgPath, target.require, subpath, + basePath, mappingKey); + emitExperimentalWarning('Conditional exports'); + return result; } catch (e) { if (e.code !== 'MODULE_NOT_FOUND') throw e; } @@ -593,8 +595,10 @@ function resolveExportsTarget(pkgPath, target, subpath, basePath, mappingKey) { if (experimentalConditionalExports && ObjectPrototypeHasOwnProperty(target, 'node')) { try { - return resolveExportsTarget(pkgPath, target.node, subpath, - basePath, mappingKey); + const result = resolveExportsTarget(pkgPath, target.node, subpath, + basePath, mappingKey); + emitExperimentalWarning('Conditional exports'); + return result; } catch (e) { if (e.code !== 'MODULE_NOT_FOUND') throw e; } @@ -697,6 +701,7 @@ Module._findPath = function(request, paths, isMain) { const selfFilename = trySelf(paths, exts, isMain, trailingSlash, request); if (selfFilename) { + emitExperimentalWarning('Package name self resolution'); Module._pathCache[cacheKey] = selfFilename; return selfFilename; } diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js index dafc1b02f03112..99e4c014053202 100644 --- a/lib/internal/modules/esm/translators.js +++ b/lib/internal/modules/esm/translators.js @@ -22,7 +22,7 @@ const createDynamicModule = require( const fs = require('fs'); const { fileURLToPath, URL } = require('url'); const { debuglog } = require('internal/util/debuglog'); -const { promisify } = require('internal/util'); +const { promisify, emitExperimentalWarning } = require('internal/util'); const { ERR_INVALID_URL, ERR_INVALID_URL_SCHEME, @@ -133,6 +133,7 @@ translators.set('builtin', async function builtinStrategy(url) { // Strategy for loading a JSON file translators.set('json', async function jsonStrategy(url) { + emitExperimentalWarning('Importing JSON modules'); debug(`Translating JSONModule ${url}`); debug(`Loading JSONModule ${url}`); const pathname = url.startsWith('file:') ? fileURLToPath(url) : null; @@ -187,6 +188,7 @@ translators.set('json', async function jsonStrategy(url) { // Strategy for loading a wasm module translators.set('wasm', async function(url) { + emitExperimentalWarning('Importing Web Assembly modules'); const buffer = await getSource(url); debug(`Translating WASMModule ${url}`); let compiled; diff --git a/src/module_wrap.cc b/src/module_wrap.cc index 3c3d568329221d..2fa8ba498edcb7 100644 --- a/src/module_wrap.cc +++ b/src/module_wrap.cc @@ -7,6 +7,7 @@ #include "util-inl.h" #include "node_contextify.h" #include "node_watchdog.h" +#include "node_process.h" #include // S_IFDIR @@ -962,6 +963,7 @@ Maybe ResolveExportsTarget(Environment* env, Maybe resolved = ResolveExportsTarget(env, pjson_url, conditionalTarget, subpath, pkg_subpath, base, false); if (!resolved.IsNothing()) { + ProcessEmitExperimentalWarning(env, "Conditional exports"); return resolved; } } @@ -1267,6 +1269,7 @@ Maybe PackageResolve(Environment* env, Maybe self_url = ResolveSelf(env, specifier, base); if (self_url.IsJust()) { + ProcessEmitExperimentalWarning(env, "Package name self resolution"); return self_url; } diff --git a/src/node_process.h b/src/node_process.h index 5db7b004d6f939..ad86b449f95290 100644 --- a/src/node_process.h +++ b/src/node_process.h @@ -27,6 +27,8 @@ v8::Maybe ProcessEmitWarningGeneric(Environment* env, const char* code = nullptr); v8::Maybe ProcessEmitWarning(Environment* env, const char* fmt, ...); +v8::Maybe ProcessEmitExperimentalWarning(Environment* env, + const char* warning); v8::Maybe ProcessEmitDeprecationWarning(Environment* env, const char* warning, const char* deprecation_code); diff --git a/src/node_process_events.cc b/src/node_process_events.cc index 06096226625bb6..d192ef19b7abad 100644 --- a/src/node_process_events.cc +++ b/src/node_process_events.cc @@ -1,4 +1,5 @@ #include +#include #include "env-inl.h" #include "node_process.h" @@ -95,6 +96,21 @@ Maybe ProcessEmitWarning(Environment* env, const char* fmt, ...) { return ProcessEmitWarningGeneric(env, warning); } + +std::set experimental_warnings; + +Maybe ProcessEmitExperimentalWarning(Environment* env, + const char* warning) { + if (experimental_warnings.find(warning) != experimental_warnings.end()) + return Nothing(); + + experimental_warnings.insert(warning); + std::string message(warning); + message.append( + " is an experimental feature. This feature could change at any time"); + return ProcessEmitWarningGeneric(env, message.c_str(), "ExperimentalWarning"); +} + Maybe ProcessEmitDeprecationWarning(Environment* env, const char* warning, const char* deprecation_code) { diff --git a/test/common/fixtures.mjs b/test/common/fixtures.mjs new file mode 100644 index 00000000000000..3eeef6d6077c4a --- /dev/null +++ b/test/common/fixtures.mjs @@ -0,0 +1,16 @@ +/* eslint-disable node-core/require-common-first, node-core/required-modules */ +import fixtures from './fixtures.js'; + +const { + fixturesDir, + path, + readSync, + readKey, +} = fixtures; + +export { + fixturesDir, + path, + readSync, + readKey, +}; diff --git a/test/es-module/test-esm-exports.mjs b/test/es-module/test-esm-exports.mjs index a361bafaa83804..73a86793a23863 100644 --- a/test/es-module/test-esm-exports.mjs +++ b/test/es-module/test-esm-exports.mjs @@ -1,6 +1,8 @@ // Flags: --experimental-modules import { mustCall } from '../common/index.mjs'; +import { path } from '../common/fixtures.mjs'; import { ok, deepStrictEqual, strictEqual } from 'assert'; +import { spawn } from 'child_process'; import { requireFixture, importFixture } from '../fixtures/pkgexports.mjs'; import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js'; @@ -149,3 +151,33 @@ function assertIncludes(actual, expected) { ok(actual.toString().indexOf(expected) !== -1, `${JSON.stringify(actual)} includes ${JSON.stringify(expected)}`); } + +// Test warning message +[ + [ + '--experimental-conditional-exports', + '/es-modules/conditional-exports.js', + 'Conditional exports', + ], + [ + '--experimental-resolve-self', + '/node_modules/pkgexports/resolve-self.js', + 'Package name self resolution', + ], +].forEach(([flag, file, message]) => { + const child = spawn(process.execPath, [flag, path(file)]); + + let stderr = ''; + child.stderr.setEncoding('utf8'); + child.stderr.on('data', (data) => { + stderr += data; + }); + child.on('close', (code, signal) => { + strictEqual(code, 0); + strictEqual(signal, null); + ok(stderr.toString().includes( + `ExperimentalWarning: ${message} is an experimental feature. ` + + 'This feature could change at any time' + )); + }); +}); diff --git a/test/es-module/test-esm-json.mjs b/test/es-module/test-esm-json.mjs index 9dd33f26b557d1..ddcc7cb33e709f 100644 --- a/test/es-module/test-esm-json.mjs +++ b/test/es-module/test-esm-json.mjs @@ -1,7 +1,29 @@ // Flags: --experimental-json-modules import '../common/index.mjs'; -import { strictEqual } from 'assert'; +import { path } from '../common/fixtures.mjs'; +import { strictEqual, ok } from 'assert'; +import { spawn } from 'child_process'; import secret from '../fixtures/experimental.json'; strictEqual(secret.ofLife, 42); + +// Test warning message +const child = spawn(process.execPath, [ + '--experimental-json-modules', + path('/es-modules/json-modules.mjs') +]); + +let stderr = ''; +child.stderr.setEncoding('utf8'); +child.stderr.on('data', (data) => { + stderr += data; +}); +child.on('close', (code, signal) => { + strictEqual(code, 0); + strictEqual(signal, null); + ok(stderr.toString().includes( + 'ExperimentalWarning: Importing JSON modules is an experimental feature. ' + + 'This feature could change at any time' + )); +}); diff --git a/test/es-module/test-esm-wasm.mjs b/test/es-module/test-esm-wasm.mjs index 46df5994afa932..b2218ce2f09893 100644 --- a/test/es-module/test-esm-wasm.mjs +++ b/test/es-module/test-esm-wasm.mjs @@ -1,8 +1,10 @@ // Flags: --experimental-wasm-modules import '../common/index.mjs'; +import { path } from '../common/fixtures.mjs'; import { add, addImported } from '../fixtures/es-modules/simple.wasm'; import { state } from '../fixtures/es-modules/wasm-dep.mjs'; -import { strictEqual } from 'assert'; +import { strictEqual, ok } from 'assert'; +import { spawn } from 'child_process'; strictEqual(state, 'WASM Start Executed'); @@ -13,3 +15,23 @@ strictEqual(addImported(0), 42); strictEqual(state, 'WASM JS Function Executed'); strictEqual(addImported(1), 43); + +// Test warning message +const child = spawn(process.execPath, [ + '--experimental-wasm-modules', + path('/es-modules/wasm-modules.mjs') +]); + +let stderr = ''; +child.stderr.setEncoding('utf8'); +child.stderr.on('data', (data) => { + stderr += data; +}); +child.on('close', (code, signal) => { + strictEqual(code, 0); + strictEqual(signal, null); + ok(stderr.toString().includes( + 'ExperimentalWarning: Importing Web Assembly modules is ' + + 'an experimental feature. This feature could change at any time' + )); +}); diff --git a/test/fixtures/es-modules/conditional-exports.js b/test/fixtures/es-modules/conditional-exports.js new file mode 100644 index 00000000000000..b480078bfc47f1 --- /dev/null +++ b/test/fixtures/es-modules/conditional-exports.js @@ -0,0 +1 @@ +require('pkgexports/condition') diff --git a/test/fixtures/es-modules/json-modules.mjs b/test/fixtures/es-modules/json-modules.mjs new file mode 100644 index 00000000000000..fa3f936bac921e --- /dev/null +++ b/test/fixtures/es-modules/json-modules.mjs @@ -0,0 +1 @@ +import secret from '../experimental.json'; diff --git a/test/fixtures/es-modules/wasm-modules.mjs b/test/fixtures/es-modules/wasm-modules.mjs new file mode 100644 index 00000000000000..c56e6a926b2a04 --- /dev/null +++ b/test/fixtures/es-modules/wasm-modules.mjs @@ -0,0 +1,2 @@ +import { add, addImported } from './simple.wasm'; +import { state } from './wasm-dep.mjs'; diff --git a/test/fixtures/node_modules/pkgexports/resolve-self.js b/test/fixtures/node_modules/pkgexports/resolve-self.js new file mode 100644 index 00000000000000..7bd3526aaa4e70 --- /dev/null +++ b/test/fixtures/node_modules/pkgexports/resolve-self.js @@ -0,0 +1 @@ +require('@pkgexports/name/valid-cjs') From 67823e8fc4d2cde2278d7d501a59f090266aedf8 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Mon, 2 Dec 2019 06:13:57 -0800 Subject: [PATCH 031/117] doc: remove imprecise and redundant testing text Remove "All commits...are tested on these platforms." for the following reasons: * It's somewhat redundant. The surrounding text makes it clear that we test on these platforms. * It's imprecise. Commits, such as those that only affect documentation or linting do not get tested on all the platforms. (Well, perhaps they do in an after-the-fact kind of way when a subsequent commit gets tested, but I think that's a stretch.) PR-URL: https://github.com/nodejs/node/pull/30763 Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca Reviewed-By: Richard Lau --- BUILDING.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index 1939d2513e9237..1abcc4cbd1bf4f 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -69,13 +69,11 @@ There are three support tiers: * **Tier 1**: These platforms represent the majority of Node.js users. The Node.js Build Working Group maintains infrastructure for full test coverage. - All commits to the Node.js repository are tested on these platforms. Test - failures on tier 1 platforms will block releases. + Test failures on tier 1 platforms will block releases. * **Tier 2**: These platforms represent smaller segments of the Node.js user base. The Node.js Build Working Group maintains infrastructure for full test - coverage. All commits to the Node.js repository are tested on these platforms. - Test failures on tier 2 platforms will block releases. Delays in release of - binaries for these platforms are acceptable where necessary due to + coverage. Test failures on tier 2 platforms will block releases. Delays in + release of binaries for these platforms are acceptable where necessary due to infrastructure concerns. * **Experimental**: May not compile or test suite may not pass. The core team does not create releases for these platforms. Test failures on experimental From fb31ab52c08daac38df409b59b6e8c043fba2e44 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Mon, 2 Dec 2019 11:47:10 -0800 Subject: [PATCH 032/117] test: simplify tmpdir import in wasi tests PR-URL: https://github.com/nodejs/node/pull/30770 Reviewed-By: Richard Lau Reviewed-By: Colin Ihrig Reviewed-By: Yongsheng Zhang Reviewed-By: Jiawen Geng Reviewed-By: Ruben Bridgewater Reviewed-By: Anna Henningsen --- test/wasi/test-wasi-symlinks.js | 2 +- test/wasi/test-wasi.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/wasi/test-wasi-symlinks.js b/test/wasi/test-wasi-symlinks.js index 3829464198273b..7c6e6809738975 100644 --- a/test/wasi/test-wasi-symlinks.js +++ b/test/wasi/test-wasi-symlinks.js @@ -33,7 +33,7 @@ if (process.argv[2] === 'wasi-child') { const assert = require('assert'); const cp = require('child_process'); - const tmpdir = require('../../test/common/tmpdir'); + const tmpdir = require('../common/tmpdir'); // Setup the sandbox environment. tmpdir.refresh(); diff --git a/test/wasi/test-wasi.js b/test/wasi/test-wasi.js index fa2e0894c906ce..d1060f5b32d33d 100644 --- a/test/wasi/test-wasi.js +++ b/test/wasi/test-wasi.js @@ -3,7 +3,7 @@ const common = require('../common'); if (process.argv[2] === 'wasi-child') { const fixtures = require('../common/fixtures'); - const tmpdir = require('../../test/common/tmpdir'); + const tmpdir = require('../common/tmpdir'); const fs = require('fs'); const path = require('path'); From 30756e36e7cff01995068e7e66a6ab817b5f9b73 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Mon, 2 Dec 2019 12:25:39 -0800 Subject: [PATCH 033/117] test: improve wasi test coverage Add test coverage for options validation in WASI constructor. PR-URL: https://github.com/nodejs/node/pull/30770 Reviewed-By: Richard Lau Reviewed-By: Colin Ihrig Reviewed-By: Yongsheng Zhang Reviewed-By: Jiawen Geng Reviewed-By: Ruben Bridgewater Reviewed-By: Anna Henningsen --- test/wasi/test-wasi-options-validation.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 test/wasi/test-wasi-options-validation.js diff --git a/test/wasi/test-wasi-options-validation.js b/test/wasi/test-wasi-options-validation.js new file mode 100644 index 00000000000000..34ab7e078f1210 --- /dev/null +++ b/test/wasi/test-wasi-options-validation.js @@ -0,0 +1,22 @@ +'use strict'; + +// Flags: --experimental-wasi-unstable-preview0 + +require('../common'); +const assert = require('assert'); +const { WASI } = require('wasi'); + +// If args is undefined, it should default to [] and should not throw. +new WASI({}); + +// If args is not an Array and not undefined, it should throw. +assert.throws(() => { new WASI({ args: 'fhqwhgads' }); }, + { code: 'ERR_INVALID_ARG_TYPE' }); + +// If env is not an Object and not undefined, it should throw. +assert.throws(() => { new WASI({ env: 'fhqwhgads' }); }, + { code: 'ERR_INVALID_ARG_TYPE' }); + +// If preopens is not an Object and not undefined, it should throw. +assert.throws(() => { new WASI({ preopens: 'fhqwhgads' }); }, + { code: 'ERR_INVALID_ARG_TYPE' }); From 94f237e5acb2dafb87399534de26da765cd9d537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Jos=C3=A9=20Arboleda?= Date: Wed, 27 Nov 2019 20:26:36 -0500 Subject: [PATCH 034/117] lib,test: improves ERR_REQUIRE_ESM message PR-URL: https://github.com/nodejs/node/pull/30694 Fixes: https://github.com/nodejs/node/issues/30599 Reviewed-By: Guy Bedford --- lib/internal/errors.js | 21 +++++++++++++++- lib/internal/modules/cjs/loader.js | 27 +++------------------ test/es-module/test-cjs-esm-warn.js | 10 +++++--- test/es-module/test-esm-type-flag-errors.js | 5 +++- 4 files changed, 35 insertions(+), 28 deletions(-) diff --git a/lib/internal/errors.js b/lib/internal/errors.js index f85253ec444256..3db047cd3274c4 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -1123,7 +1123,26 @@ E('ERR_OUT_OF_RANGE', msg += ` It must be ${range}. Received ${received}`; return msg; }, RangeError); -E('ERR_REQUIRE_ESM', 'Must use import to load ES Module: %s', Error); +E('ERR_REQUIRE_ESM', + (filename, parentPath = null, packageJsonPath = null) => { + let msg = `Must use import to load ES Module: ${filename}`; + if (parentPath && packageJsonPath) { + const path = require('path'); + const basename = path.basename(filename) === path.basename(parentPath) ? + filename : path.basename(filename); + msg += + '\nrequire() of ES modules is not supported.\nrequire() of ' + + `${filename} ${parentPath ? `from ${parentPath} ` : ''}` + + 'is an ES module file as it is a .js file whose nearest parent ' + + 'package.json contains "type": "module" which defines all .js ' + + 'files in that package scope as ES modules.\nInstead rename ' + + `${basename} to end in .cjs, change the requiring code to use ` + + 'import(), or remove "type": "module" from ' + + `${packageJsonPath}.\n`; + return msg; + } + return msg; + }, Error); E('ERR_SCRIPT_EXECUTION_INTERRUPTED', 'Script execution was interrupted by `SIGINT`', Error); E('ERR_SERVER_ALREADY_LISTEN', diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 11e3d59f781dc3..319f89078025dd 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -1139,33 +1139,14 @@ Module.prototype._compile = function(content, filename) { }; // Native extension for .js -let warnRequireESM = true; Module._extensions['.js'] = function(module, filename) { if (filename.endsWith('.js')) { const pkg = readPackageScope(filename); + // Function require shouldn't be used in ES modules. if (pkg && pkg.data && pkg.data.type === 'module') { - if (warnRequireESM) { - const parentPath = module.parent && module.parent.filename; - const basename = parentPath && - path.basename(filename) === path.basename(parentPath) ? - filename : path.basename(filename); - process.emitWarning( - 'require() of ES modules is not supported.\nrequire() of ' + - `${filename} ${parentPath ? `from ${module.parent.filename} ` : ''}` + - 'is an ES module file as it is a .js file whose nearest parent ' + - 'package.json contains "type": "module" which defines all .js ' + - 'files in that package scope as ES modules.\nInstead rename ' + - `${basename} to end in .cjs, change the requiring code to use ` + - 'import(), or remove "type": "module" from ' + - `${path.resolve(pkg.path, 'package.json')}.`, - undefined, - undefined, - undefined, - true - ); - warnRequireESM = false; - } - throw new ERR_REQUIRE_ESM(filename); + const parentPath = module.parent && module.parent.filename; + const packageJsonPath = path.resolve(pkg.path, 'package.json'); + throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath); } } const content = fs.readFileSync(filename, 'utf8'); diff --git a/test/es-module/test-cjs-esm-warn.js b/test/es-module/test-cjs-esm-warn.js index b1b2e7f434256f..b800a47d0515d5 100644 --- a/test/es-module/test-cjs-esm-warn.js +++ b/test/es-module/test-cjs-esm-warn.js @@ -26,15 +26,19 @@ child.on('close', common.mustCall((code, signal) => { assert.strictEqual(code, 1); assert.strictEqual(signal, null); - assert.ok(stderr.startsWith(`(node:${child.pid}) Warning: ` + - 'require() of ES modules is not supported.\nrequire() of ' + + assert.ok(stderr.indexOf( + `Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: ${required}` + + '\nrequire() of ES modules is not supported.\nrequire() of ' + `${required} from ${requiring} ` + 'is an ES module file as it is a .js file whose nearest parent ' + 'package.json contains "type": "module" which defines all .js ' + 'files in that package scope as ES modules.\nInstead rename ' + `${basename} to end in .cjs, change the requiring code to use ` + 'import(), or remove "type": "module" from ' + - `${pjson}.\n`)); + `${pjson}.\n`) !== -1); assert.ok(stderr.indexOf( 'Error [ERR_REQUIRE_ESM]: Must use import to load ES Module') !== -1); + + assert.strictEqual( + stderr.match(/Must use import to load ES Module/g).length, 1); })); diff --git a/test/es-module/test-esm-type-flag-errors.js b/test/es-module/test-esm-type-flag-errors.js index 5d19cedd84a844..e0dedc16cabf8c 100644 --- a/test/es-module/test-esm-type-flag-errors.js +++ b/test/es-module/test-esm-type-flag-errors.js @@ -27,7 +27,10 @@ try { require('../fixtures/es-modules/package-type-module/index.js'); assert.fail('Expected CJS to fail loading from type: module package.'); } catch (e) { - assert(e.toString().match(/Error \[ERR_REQUIRE_ESM\]: Must use import to load ES Module:/)); + assert.strictEqual(e.name, 'Error'); + assert.strictEqual(e.code, 'ERR_REQUIRE_ESM'); + assert(e.toString().match(/Must use import to load ES Module/g)); + assert(e.message.match(/Must use import to load ES Module/g)); } function expect(opt = '', inputFile, want, wantsError = false) { From bd2f1270f76db3603f8198f36afc886fbebabef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Fri, 8 Nov 2019 18:38:26 +0100 Subject: [PATCH 035/117] module: ignore resolution failures for inspect-brk The resolution for the main entry point may fail when the resolution requires a preloaded module to be executed first (for example when adding new extensions to the resolution process). Silently skipping such failures allow us to defer the resolution as long as needed without having any adverse change (since the main entry point won't resolve anyway if it really can't be resolved at all). PR-URL: https://github.com/nodejs/node/pull/30336 Reviewed-By: Guy Bedford Reviewed-By: Joyee Cheung --- lib/internal/modules/cjs/loader.js | 10 +++++-- .../test-resolution-inspect-brk-main.ext | 0 .../test-resolution-inspect-brk-resolver.js | 5 ++++ .../sequential/test-resolution-inspect-brk.js | 29 +++++++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/test-resolution-inspect-brk-main.ext create mode 100644 test/fixtures/test-resolution-inspect-brk-resolver.js create mode 100644 test/sequential/test-resolution-inspect-brk.js diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 319f89078025dd..91b256661e4751 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -1107,14 +1107,20 @@ Module.prototype._compile = function(content, filename) { if (!resolvedArgv) { // We enter the repl if we're not given a filename argument. if (process.argv[1]) { - resolvedArgv = Module._resolveFilename(process.argv[1], null, false); + try { + resolvedArgv = Module._resolveFilename(process.argv[1], null, false); + } catch { + // We only expect this codepath to be reached in the case of a + // preloaded module (it will fail earlier with the main entry) + assert(Array.isArray(getOptionValue('--require'))); + } } else { resolvedArgv = 'repl'; } } // Set breakpoint on module start - if (!hasPausedEntry && filename === resolvedArgv) { + if (resolvedArgv && !hasPausedEntry && filename === resolvedArgv) { hasPausedEntry = true; inspectorWrapper = internalBinding('inspector').callAndPauseOnStart; } diff --git a/test/fixtures/test-resolution-inspect-brk-main.ext b/test/fixtures/test-resolution-inspect-brk-main.ext new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/test/fixtures/test-resolution-inspect-brk-resolver.js b/test/fixtures/test-resolution-inspect-brk-resolver.js new file mode 100644 index 00000000000000..fdfb5ca5b170c2 --- /dev/null +++ b/test/fixtures/test-resolution-inspect-brk-resolver.js @@ -0,0 +1,5 @@ +'use strict'; +// eslint-disable-next-line no-unused-vars +const common = require('../common'); + +require.extensions['.ext'] = require.extensions['.js']; diff --git a/test/sequential/test-resolution-inspect-brk.js b/test/sequential/test-resolution-inspect-brk.js new file mode 100644 index 00000000000000..2af32426c03f57 --- /dev/null +++ b/test/sequential/test-resolution-inspect-brk.js @@ -0,0 +1,29 @@ +'use strict'; +const common = require('../common'); +common.skipIfInspectorDisabled(); + +// A test to ensure that preload modules are given a chance to execute before +// resolving the main entry point with --inspect-brk active. + +const assert = require('assert'); +const cp = require('child_process'); +const path = require('path'); + +function test(execArgv) { + const child = cp.spawn(process.execPath, execArgv); + + child.stderr.once('data', common.mustCall(function() { + child.kill('SIGTERM'); + })); + + child.on('exit', common.mustCall(function(code, signal) { + assert.strictEqual(signal, 'SIGTERM'); + })); +} + +test([ + '--require', + path.join(__dirname, '../fixtures/test-resolution-inspect-brk-resolver.js'), + '--inspect-brk', + '../fixtures/test-resolution-inspect-resolver-main.ext', +]); From a7ec78f34e5807bd79e6b1e8257862cb14274254 Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Thu, 5 Dec 2019 00:11:04 -0500 Subject: [PATCH 036/117] module: fixup lint and test regressions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/30802 Reviewed-By: Rich Trott Reviewed-By: João Reis Reviewed-By: Matteo Collina --- lib/internal/modules/cjs/loader.js | 2 +- test/es-module/test-cjs-esm-warn.js | 11 ++++------- test/es-module/test-esm-specifiers-both-flags.mjs | 4 +--- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 91b256661e4751..10fbbb8d01e90e 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -1112,7 +1112,7 @@ Module.prototype._compile = function(content, filename) { } catch { // We only expect this codepath to be reached in the case of a // preloaded module (it will fail earlier with the main entry) - assert(Array.isArray(getOptionValue('--require'))); + assert(ArrayIsArray(getOptionValue('--require'))); } } else { resolvedArgv = 'repl'; diff --git a/test/es-module/test-cjs-esm-warn.js b/test/es-module/test-cjs-esm-warn.js index b800a47d0515d5..ddeda72fc84b41 100644 --- a/test/es-module/test-cjs-esm-warn.js +++ b/test/es-module/test-cjs-esm-warn.js @@ -26,7 +26,7 @@ child.on('close', common.mustCall((code, signal) => { assert.strictEqual(code, 1); assert.strictEqual(signal, null); - assert.ok(stderr.indexOf( + assert.ok(stderr.replace(/\r/g, '').includes( `Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: ${required}` + '\nrequire() of ES modules is not supported.\nrequire() of ' + `${required} from ${requiring} ` + @@ -35,10 +35,7 @@ child.on('close', common.mustCall((code, signal) => { 'files in that package scope as ES modules.\nInstead rename ' + `${basename} to end in .cjs, change the requiring code to use ` + 'import(), or remove "type": "module" from ' + - `${pjson}.\n`) !== -1); - assert.ok(stderr.indexOf( - 'Error [ERR_REQUIRE_ESM]: Must use import to load ES Module') !== -1); - - assert.strictEqual( - stderr.match(/Must use import to load ES Module/g).length, 1); + `${pjson}.\n`)); + assert.ok(stderr.includes( + 'Error [ERR_REQUIRE_ESM]: Must use import to load ES Module')); })); diff --git a/test/es-module/test-esm-specifiers-both-flags.mjs b/test/es-module/test-esm-specifiers-both-flags.mjs index fc5c7fcd0e98a9..a434684589dc07 100644 --- a/test/es-module/test-esm-specifiers-both-flags.mjs +++ b/test/es-module/test-esm-specifiers-both-flags.mjs @@ -9,8 +9,6 @@ const expectedError = const flags = '--es-module-specifier-resolution=node ' + '--experimental-specifier-resolution=node'; -exec(`${process.execPath} ${flags}`, { - timeout: 300 -}, mustCall((error) => { +exec(`${process.execPath} ${flags}`, mustCall((error) => { assert(error.message.includes(expectedError)); })); From 1d5c4e21de67eb493c88dbd3287ca5f11e6556ad Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Tue, 3 Dec 2019 18:18:37 +0800 Subject: [PATCH 037/117] doc: add documentation about node_mksnapshot and mkcodecache PR-URL: https://github.com/nodejs/node/pull/30773 Reviewed-By: Anna Henningsen Reviewed-By: Gireesh Punathil --- tools/code_cache/README.md | 38 ++++++++++++++++++++++++++++++++++ tools/snapshot/README.md | 42 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 tools/code_cache/README.md create mode 100644 tools/snapshot/README.md diff --git a/tools/code_cache/README.md b/tools/code_cache/README.md new file mode 100644 index 00000000000000..f8428c24b0dd4b --- /dev/null +++ b/tools/code_cache/README.md @@ -0,0 +1,38 @@ +# Node.js code cache builder + +This is the V8 code cache builder of Node.js. It pre-compiles all the +JavaScript native modules of Node.js and serializes the code cache (including +the bytecodes) that will be embeded into the Node.js executable. When a Node.js +JavaScript native module is `require`d at runtime, Node.js can deserialize from +the code cache instead of parsing the source code and generating the bytecode +for it before execution, which should reduce the load time of these JavaScript +native modules. + +## How it's built and used + +The code cache builder is built with the `mkcodecache` target in `node.gyp` +when `node_use_node_code_cache` is set to true, which is currently done by +default. + +In the default build of the Node.js executable, to embed the V8 code cache of +the native modules into the Node.js executable, `libnode` is first built with +these unresolved symbols: + +- `node::native_module::has_code_cache` +- `node::native_module::NativeModuleEnv::InitializeCodeCache` + +Then the `mkcodecache` executable is built with C++ files in this directory, +as well as `src/node_code_cache_stub.cc` which defines the unresolved symbols. + +`mkcodecache` is run to generate a C++ file +`<(SHARED_INTERMEDIATE_DIR)/node_code_cache.cc` that is similar to +`src/node_code_cache_stub.cc` in structure, but contains the code cache data +written as static char array literals. Then `libnode` is built with +`node_code_cache.cc` to produce the final Node.js executable with the code +cache data embedded. + +For debugging, Node.js can be built without code cache if +`--without-node-code-cache` is passed to `configure`. Note that even if the +code cache is not pre-compiled and embedded into the Node.js executable, the +internal infrastructure is still used to share code cache between the main +thread and worker threads (if there is any). diff --git a/tools/snapshot/README.md b/tools/snapshot/README.md new file mode 100644 index 00000000000000..34dc574d56cc30 --- /dev/null +++ b/tools/snapshot/README.md @@ -0,0 +1,42 @@ +# Node.js startup snapshot builder + +This is the V8 startup snapshot builder of Node.js. Not to be confused with +V8's own snapshot builder, which builds a snapshot containing JavaScript +builtins, this builds a snapshot containing Node.js builtins that can be +deserialized on top of V8's own startup snapshot. When Node.js is launched, +instead of executing code to bootstrap, it can deserialize the context from +an embedded snapshot, which readily contains the result of the bootstrap, so +that Node.js can start up faster. + +Currently only the main context of the main Node.js instance supports snapshot +deserialization, and the snapshot does not yet cover the entire bootstrap +process. Work is being done to expand the support. + +## How it's built and used + +The snapshot builder is built with the `node_mksnapshot` target in `node.gyp` +when `node_use_node_snapshot` is set to true, which is currently done by +default. + +In the default build of the Node.js executable, to embed a V8 startup snapshot +into the Node.js executable, `libnode` is first built with these unresolved +symbols: + +- `node::NodeMainInstance::GetEmbeddedSnapshotBlob` +- `node::NodeMainInstance::GetIsolateDataIndexes` + +Then the `node_mksnapshot` executable is built with C++ files in this +directory, as well as `src/node_snapshot_stub.cc` which defines the unresolved +symbols. + +`node_mksnapshot` is run to generate a C++ file +`<(SHARED_INTERMEDIATE_DIR)/node_snapshot.cc` that is similar to +`src/node_snapshot_stub.cc` in structure, but contains the snapshot data +written as static char array literals. Then `libnode` is built with +`node_snapshot.cc` to produce the final Node.js executable with the snapshot +data embedded. + +For debugging, Node.js can be built without Node.js's own snapshot if +`--without-node-snapshot` is passed to `configure`. A Node.js executable +with Node.js snapshot embedded can also be launched without deserializing +from it if the command line argument `--no-node-snapshot` is passed. From 5067463f3c3235fd25941afc1e6b6510c359da0f Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Tue, 3 Dec 2019 04:10:39 -0800 Subject: [PATCH 038/117] test: use callback arguments in getconnections test Use previously-unused callback arguments in test-child-process-fork-getconnections. PR-URL: https://github.com/nodejs/node/pull/30775 Reviewed-By: Jiawen Geng Reviewed-By: Luigi Pinca --- test/parallel/test-child-process-fork-getconnections.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/parallel/test-child-process-fork-getconnections.js b/test/parallel/test-child-process-fork-getconnections.js index 1b1ba9c0d96048..b96d61238a0dd8 100644 --- a/test/parallel/test-child-process-fork-getconnections.js +++ b/test/parallel/test-child-process-fork-getconnections.js @@ -58,8 +58,10 @@ if (process.argv[2] === 'child') { const child = fork(process.argv[1], ['child']); child.on('exit', function(code, signal) { - if (!subprocessKilled) - throw new Error('subprocess died unexpectedly!'); + if (!subprocessKilled) { + assert.fail('subprocess died unexpectedly! ' + + `code: ${code} signal: ${signal}`); + } }); const server = net.createServer(); @@ -98,6 +100,8 @@ if (process.argv[2] === 'child') { child.once('message', function(m) { assert.strictEqual(m.status, 'closed'); server.getConnections(function(err, num) { + assert.ifError(err); + assert.strictEqual(num, count - (i + 1)); closeSockets(i + 1); }); }); From 325128e469229a35f2c805ef18970a2cffb64831 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Wed, 4 Dec 2019 01:11:29 +0800 Subject: [PATCH 039/117] lib: delay access to CLI option to pre-execution CLI options should not be added through the config binding, instead they are already available in the JS land via `require('internal/options')`. Also CLI options in principle should be processed in pre-execution instead of bootstrap scripts. PR-URL: https://github.com/nodejs/node/pull/30778 Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: Yongsheng Zhang Reviewed-By: Rich Trott --- lib/internal/bootstrap/loaders.js | 3 --- lib/internal/bootstrap/pre_execution.js | 12 +++++++++++- lib/internal/main/worker_thread.js | 2 ++ src/node_config.cc | 8 ++++---- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/lib/internal/bootstrap/loaders.js b/lib/internal/bootstrap/loaders.js index 044bea3114b840..cfefc56bd81bc8 100644 --- a/lib/internal/bootstrap/loaders.js +++ b/lib/internal/bootstrap/loaders.js @@ -157,9 +157,6 @@ function NativeModule(id) { this.loaded = false; this.loading = false; this.canBeRequiredByUsers = !id.startsWith('internal/'); - - if (id === 'wasi') - this.canBeRequiredByUsers = !!internalBinding('config').experimentalWasi; } // To be called during pre-execution when --expose-internals is on. diff --git a/lib/internal/bootstrap/pre_execution.js b/lib/internal/bootstrap/pre_execution.js index b3738015922a0c..0529bd6585261d 100644 --- a/lib/internal/bootstrap/pre_execution.js +++ b/lib/internal/bootstrap/pre_execution.js @@ -61,6 +61,7 @@ function prepareMainThreadExecution(expandArgv1 = false) { initializeClusterIPC(); initializeDeprecations(); + initializeWASI(); initializeCJSLoader(); initializeESMLoader(); @@ -399,6 +400,14 @@ function initializePolicy() { } } +function initializeWASI() { + if (getOptionValue('--experimental-wasi-unstable-preview0')) { + const { NativeModule } = require('internal/bootstrap/loaders'); + const mod = NativeModule.map.get('wasi'); + mod.canBeRequiredByUsers = true; + } +} + function initializeCJSLoader() { const CJSLoader = require('internal/modules/cjs/loader'); CJSLoader.Module._initPaths(); @@ -456,5 +465,6 @@ module.exports = { setupTraceCategoryState, setupInspectorHooks, initializeReport, - initializeCJSLoader + initializeCJSLoader, + initializeWASI }; diff --git a/lib/internal/main/worker_thread.js b/lib/internal/main/worker_thread.js index 97b55ac769fb36..3b7a2ef873ffab 100644 --- a/lib/internal/main/worker_thread.js +++ b/lib/internal/main/worker_thread.js @@ -14,6 +14,7 @@ const { setupWarningHandler, setupDebugEnv, initializeDeprecations, + initializeWASI, initializeCJSLoader, initializeESMLoader, initializeFrozenIntrinsics, @@ -109,6 +110,7 @@ port.on('message', (message) => { require('internal/process/policy').setup(manifestSrc, manifestURL); } initializeDeprecations(); + initializeWASI(); initializeCJSLoader(); initializeESMLoader(); diff --git a/src/node_config.cc b/src/node_config.cc index 16050bdd5b967d..6ee3164a134fe8 100644 --- a/src/node_config.cc +++ b/src/node_config.cc @@ -15,11 +15,14 @@ using v8::Number; using v8::Object; using v8::Value; -// The config binding is used to provide an internal view of compile or runtime +// The config binding is used to provide an internal view of compile time // config options that are required internally by lib/*.js code. This is an // alternative to dropping additional properties onto the process object as // has been the practice previously in node.cc. +// Command line arguments are already accessible in the JS land via +// require('internal/options').getOptionValue('--some-option'). Do not add them +// here. static void Initialize(Local target, Local unused, Local context, @@ -84,9 +87,6 @@ static void Initialize(Local target, READONLY_PROPERTY(target, "hasCachedBuiltins", v8::Boolean::New(isolate, native_module::has_code_cache)); - - if (env->options()->experimental_wasi) - READONLY_TRUE_PROPERTY(target, "experimentalWasi"); } // InitConfig } // namespace node From 1baa6ab07576b1a2c0f4f4cfad5401ade8656d7e Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 30 Nov 2019 13:27:08 +0100 Subject: [PATCH 040/117] doc: improve napi formatting This addresses two nits: 1. Bullet points that span over multiple lines should be indented consitently. Otherwise they are not always properly highlighted. 2. Lines breaks after titles improve the readability. PR-URL: https://github.com/nodejs/node/pull/30772 Reviewed-By: Beth Griggs Reviewed-By: David Carlier Reviewed-By: Luigi Pinca Reviewed-By: Anna Henningsen Reviewed-By: Rich Trott --- doc/api/n-api.md | 358 ++++++++++++++++++++++++----------------------- 1 file changed, 180 insertions(+), 178 deletions(-) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index d89ac03ccdc102..bcb8504e948f6a 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -386,9 +386,9 @@ napi_status napi_set_instance_data(napi_env env, * `[in] env`: The environment that the N-API call is invoked under. * `[in] data`: The data item to make available to bindings of this instance. * `[in] finalize_cb`: The function to call when the environment is being torn -down. The function receives `data` so that it might free it. -* `[in] finalize_hint`: Optional hint to pass to the finalize callback -during collection. + down. The function receives `data` so that it might free it. +* `[in] finalize_hint`: Optional hint to pass to the finalize callback during + collection. Returns `napi_ok` if the API succeeded. @@ -410,7 +410,7 @@ napi_status napi_get_instance_data(napi_env env, * `[in] env`: The environment that the N-API call is invoked under. * `[out] data`: The data item that was previously associated with the currently -running Agent by a call to `napi_set_instance_data()`. + running Agent by a call to `napi_set_instance_data()`. Returns `napi_ok` if the API succeeded. @@ -487,6 +487,7 @@ typedef struct { See the [Error Handling][] section for additional information. ### napi_env + `napi_env` is used to represent a context that the underlying N-API implementation can use to persist VM-specific state. This structure is passed to native functions when they're invoked, and it must be passed back when @@ -496,6 +497,7 @@ nested N-API calls. Caching the `napi_env` for the purpose of general reuse is not allowed. ### napi_value + This is an opaque pointer that is used to represent a JavaScript value. ### napi_threadsafe_function @@ -545,6 +547,7 @@ typedef enum { ### N-API Memory Management types #### napi_handle_scope + This is an abstraction used to control and modify the lifetime of objects created within a particular scope. In general, N-API values are created within the context of a handle scope. When a native method is called from @@ -685,23 +688,26 @@ typedef void (*napi_threadsafe_function_call_js)(napi_env env, ``` * `[in] env`: The environment to use for API calls, or `NULL` if the thread-safe -function is being torn down and `data` may need to be freed. + function is being torn down and `data` may need to be freed. * `[in] js_callback`: The JavaScript function to call, or `NULL` if the -thread-safe function is being torn down and `data` may need to be freed. It may -also be `NULL` if the thread-safe function was created without `js_callback`. + thread-safe function is being torn down and `data` may need to be freed. It + may also be `NULL` if the thread-safe function was created without + `js_callback`. * `[in] context`: The optional data with which the thread-safe function was -created. + created. * `[in] data`: Data created by the secondary thread. It is the responsibility of -the callback to convert this native data to JavaScript values (with N-API -functions) that can be passed as parameters when `js_callback` is invoked. This -pointer is managed entirely by the threads and this callback. Thus this callback -should free the data. + the callback to convert this native data to JavaScript values (with N-API + functions) that can be passed as parameters when `js_callback` is invoked. + This pointer is managed entirely by the threads and this callback. Thus this + callback should free the data. ## Error Handling + N-API uses both return values and JavaScript exceptions for error handling. The following sections explain the approach for each case. ### Return values + All of the N-API functions share the same error handling pattern. The return type of all API functions is `napi_status`. @@ -785,6 +791,7 @@ logging purposes. This API can be called even if there is a pending JavaScript exception. ### Exceptions + Any N-API function call may result in a pending JavaScript exception. This is obviously the case for any function that may cause the execution of JavaScript, but N-API specifies that an exception may be pending @@ -895,8 +902,7 @@ NAPI_EXTERN napi_status napi_throw_error(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] code`: Optional error code to be set on the error. -* `[in] msg`: C string representing the text to be associated with -the error. +* `[in] msg`: C string representing the text to be associated with the error. Returns `napi_ok` if the API succeeded. @@ -916,8 +922,7 @@ NAPI_EXTERN napi_status napi_throw_type_error(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] code`: Optional error code to be set on the error. -* `[in] msg`: C string representing the text to be associated with -the error. +* `[in] msg`: C string representing the text to be associated with the error. Returns `napi_ok` if the API succeeded. @@ -937,8 +942,7 @@ NAPI_EXTERN napi_status napi_throw_range_error(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] code`: Optional error code to be set on the error. -* `[in] msg`: C string representing the text to be associated with -the error. +* `[in] msg`: C string representing the text to be associated with the error. Returns `napi_ok` if the API succeeded. @@ -959,7 +963,7 @@ NAPI_EXTERN napi_status napi_is_error(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: The `napi_value` to be checked. * `[out] result`: Boolean value that is set to true if `napi_value` represents -an error, false otherwise. + an error, false otherwise. Returns `napi_ok` if the API succeeded. @@ -979,10 +983,10 @@ NAPI_EXTERN napi_status napi_create_error(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] code`: Optional `napi_value` with the string for the error code to -be associated with the error. -* `[in] msg`: `napi_value` that references a JavaScript `String` to be -used as the message for the `Error`. +* `[in] code`: Optional `napi_value` with the string for the error code to be + associated with the error. +* `[in] msg`: `napi_value` that references a JavaScript `String` to be used as + the message for the `Error`. * `[out] result`: `napi_value` representing the error created. Returns `napi_ok` if the API succeeded. @@ -1003,10 +1007,10 @@ NAPI_EXTERN napi_status napi_create_type_error(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] code`: Optional `napi_value` with the string for the error code to -be associated with the error. -* `[in] msg`: `napi_value` that references a JavaScript `String` to be -used as the message for the `Error`. +* `[in] code`: Optional `napi_value` with the string for the error code to be + associated with the error. +* `[in] msg`: `napi_value` that references a JavaScript `String` to be used as + the message for the `Error`. * `[out] result`: `napi_value` representing the error created. Returns `napi_ok` if the API succeeded. @@ -1027,10 +1031,10 @@ NAPI_EXTERN napi_status napi_create_range_error(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] code`: Optional `napi_value` with the string for the error code to -be associated with the error. -* `[in] msg`: `napi_value` that references a JavaScript `String` to be -used as the message for the `Error`. +* `[in] code`: Optional `napi_value` with the string for the error code to be + associated with the error. +* `[in] msg`: `napi_value` that references a JavaScript `String` to be used as + the message for the `Error`. * `[out] result`: `napi_value` representing the error created. Returns `napi_ok` if the API succeeded. @@ -1112,11 +1116,10 @@ NAPI_NO_RETURN void napi_fatal_error(const char* location, * `[in] location`: Optional location at which the error occurred. * `[in] location_len`: The length of the location in bytes, or -`NAPI_AUTO_LENGTH` if it is null-terminated. + `NAPI_AUTO_LENGTH` if it is null-terminated. * `[in] message`: The message associated with the error. -* `[in] message_len`: The length of the message in bytes, or -`NAPI_AUTO_LENGTH` if it is -null-terminated. +* `[in] message_len`: The length of the message in bytes, or `NAPI_AUTO_LENGTH` + if it is null-terminated. The function call does not return, the process will be terminated. @@ -1309,9 +1312,9 @@ napi_status napi_escape_handle(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] scope`: `napi_value` representing the current scope. * `[in] escapee`: `napi_value` representing the JavaScript `Object` to be -escaped. -* `[out] result`: `napi_value` representing the handle to the escaped -`Object` in the outer scope. + escaped. +* `[out] result`: `napi_value` representing the handle to the escaped `Object` + in the outer scope. Returns `napi_ok` if the API succeeded. @@ -1374,8 +1377,8 @@ NAPI_EXTERN napi_status napi_create_reference(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] value`: `napi_value` representing the `Object` to which we want -a reference. +* `[in] value`: `napi_value` representing the `Object` to which we want a + reference. * `[in] initial_refcount`: Initial reference count for the new reference. * `[out] result`: `napi_ref` pointing to the new reference. @@ -1463,7 +1466,7 @@ object to which the reference is related. * `[in] env`: The environment that the API is invoked under. * `[in] ref`: `napi_ref` for which we requesting the corresponding `Object`. * `[out] result`: The `napi_value` for the `Object` referenced by the -`napi_ref`. + `napi_ref`. Returns `napi_ok` if the API succeeded. @@ -1825,8 +1828,8 @@ napi_status napi_create_buffer_copy(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] size`: Size in bytes of the input buffer (should be the same as the - size of the new buffer). +* `[in] size`: Size in bytes of the input buffer (should be the same as the size + of the new buffer). * `[in] data`: Raw pointer to the underlying buffer to copy from. * `[out] result_data`: Pointer to the new `Buffer`'s underlying data buffer. * `[out] result`: A `napi_value` representing a `node::Buffer`. @@ -1879,10 +1882,10 @@ napi_status napi_create_external(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] data`: Raw pointer to the external data. -* `[in] finalize_cb`: Optional callback to call when the external value -is being collected. -* `[in] finalize_hint`: Optional hint to pass to the finalize callback -during collection. +* `[in] finalize_cb`: Optional callback to call when the external value is being + collected. +* `[in] finalize_hint`: Optional hint to pass to the finalize callback during + collection. * `[out] result`: A `napi_value` representing an external value. Returns `napi_ok` if the API succeeded. @@ -1921,12 +1924,12 @@ napi_create_external_arraybuffer(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] external_data`: Pointer to the underlying byte buffer of the -`ArrayBuffer`. + `ArrayBuffer`. * `[in] byte_length`: The length in bytes of the underlying buffer. -* `[in] finalize_cb`: Optional callback to call when the `ArrayBuffer` is -being collected. -* `[in] finalize_hint`: Optional hint to pass to the finalize callback -during collection. +* `[in] finalize_cb`: Optional callback to call when the `ArrayBuffer` is being + collected. +* `[in] finalize_hint`: Optional hint to pass to the finalize callback during + collection. * `[out] result`: A `napi_value` representing a JavaScript `ArrayBuffer`. Returns `napi_ok` if the API succeeded. @@ -1963,13 +1966,13 @@ napi_status napi_create_external_buffer(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] length`: Size in bytes of the input buffer (should be the same as -the size of the new buffer). +* `[in] length`: Size in bytes of the input buffer (should be the same as the + size of the new buffer). * `[in] data`: Raw pointer to the underlying buffer to copy from. -* `[in] finalize_cb`: Optional callback to call when the `ArrayBuffer` is -being collected. -* `[in] finalize_hint`: Optional hint to pass to the finalize callback -during collection. +* `[in] finalize_cb`: Optional callback to call when the `ArrayBuffer` is being + collected. +* `[in] finalize_hint`: Optional hint to pass to the finalize callback during + collection. * `[out] result`: A `napi_value` representing a `node::Buffer`. Returns `napi_ok` if the API succeeded. @@ -2023,7 +2026,7 @@ napi_status napi_create_symbol(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] description`: Optional `napi_value` which refers to a JavaScript -`String` to be set as the description for the symbol. + `String` to be set as the description for the symbol. * `[out] result`: A `napi_value` representing a JavaScript `Symbol`. Returns `napi_ok` if the API succeeded. @@ -2053,7 +2056,7 @@ napi_status napi_create_typedarray(napi_env env, * `[in] length`: Number of elements in the `TypedArray`. * `[in] arraybuffer`: `ArrayBuffer` underlying the typed array. * `[in] byte_offset`: The byte offset within the `ArrayBuffer` from which to -start projecting the `TypedArray`. + start projecting the `TypedArray`. * `[out] result`: A `napi_value` representing a JavaScript `TypedArray`. Returns `napi_ok` if the API succeeded. @@ -2283,8 +2286,8 @@ napi_status napi_create_string_latin1(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] str`: Character buffer representing an ISO-8859-1-encoded string. -* `[in] length`: The length of the string in bytes, or -`NAPI_AUTO_LENGTH` if it is null-terminated. +* `[in] length`: The length of the string in bytes, or `NAPI_AUTO_LENGTH` if it + is null-terminated. * `[out] result`: A `napi_value` representing a JavaScript `String`. Returns `napi_ok` if the API succeeded. @@ -2311,7 +2314,7 @@ napi_status napi_create_string_utf16(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] str`: Character buffer representing a UTF16-LE-encoded string. * `[in] length`: The length of the string in two-byte code units, or -`NAPI_AUTO_LENGTH` if it is null-terminated. + `NAPI_AUTO_LENGTH` if it is null-terminated. * `[out] result`: A `napi_value` representing a JavaScript `String`. Returns `napi_ok` if the API succeeded. @@ -2337,8 +2340,8 @@ napi_status napi_create_string_utf8(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] str`: Character buffer representing a UTF8-encoded string. -* `[in] length`: The length of the string in bytes, or `NAPI_AUTO_LENGTH` -if it is null-terminated. +* `[in] length`: The length of the string in bytes, or `NAPI_AUTO_LENGTH` if it + is null-terminated. * `[out] result`: A `napi_value` representing a JavaScript `String`. Returns `napi_ok` if the API succeeded. @@ -2364,7 +2367,7 @@ napi_status napi_get_array_length(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing the JavaScript `Array` whose length is -being queried. + being queried. * `[out] result`: `uint32` representing length of the array. Returns `napi_ok` if the API succeeded. @@ -2445,8 +2448,8 @@ napi_status napi_get_prototype(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] object`: `napi_value` representing JavaScript `Object` whose prototype -to return. This returns the equivalent of `Object.getPrototypeOf` (which is -not the same as the function's `prototype` property). + to return. This returns the equivalent of `Object.getPrototypeOf` (which is + not the same as the function's `prototype` property). * `[out] result`: `napi_value` representing prototype of the given object. Returns `napi_ok` if the API succeeded. @@ -2531,8 +2534,8 @@ napi_status napi_get_date_value(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing a JavaScript `Date`. -* `[out] result`: Time value as a `double` represented as milliseconds -since midnight at the beginning of 01 January, 1970 UTC. +* `[out] result`: Time value as a `double` represented as milliseconds since + midnight at the beginning of 01 January, 1970 UTC. This API does not observe leap seconds; they are ignored, as ECMAScript aligns with POSIX time specification. @@ -2556,7 +2559,7 @@ napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result) * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing JavaScript `Boolean`. * `[out] result`: C boolean primitive equivalent of the given JavaScript -`Boolean`. + `Boolean`. Returns `napi_ok` if the API succeeded. If a non-boolean `napi_value` is passed in it returns `napi_boolean_expected`. @@ -2579,7 +2582,7 @@ napi_status napi_get_value_double(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing JavaScript `Number`. * `[out] result`: C double primitive equivalent of the given JavaScript -`Number`. + `Number`. Returns `napi_ok` if the API succeeded. If a non-number `napi_value` is passed in it returns `napi_number_expected`. @@ -2769,11 +2772,11 @@ 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 -passed in, the length of the string (in bytes) is returned. + 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. + insufficient, the returned string will be truncated. * `[out] result`: Number of bytes copied into the buffer, excluding the null -terminator. + terminator. Returns `napi_ok` if the API succeeded. If a non-`String` `napi_value` is passed in it returns `napi_string_expected`. @@ -2798,11 +2801,11 @@ 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, the length of the string (in bytes) is returned. + 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. + insufficient, the returned string will be truncated. * `[out] result`: Number of bytes copied into the buffer, excluding the null -terminator. + terminator. Returns `napi_ok` if the API succeeded. If a non-`String` `napi_value` is passed in it returns `napi_string_expected`. @@ -2826,11 +2829,11 @@ 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 -passed in, the length of the string (in 2-byte code units) is returned. + 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. + insufficient, the returned string will be truncated. * `[out] result`: Number of 2-byte code units copied into the buffer, excluding -the null terminator. + the null terminator. Returns `napi_ok` if the API succeeded. If a non-`String` `napi_value` is passed in it returns `napi_string_expected`. @@ -2852,7 +2855,7 @@ napi_status napi_get_value_uint32(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] value`: `napi_value` representing JavaScript `Number`. * `[out] result`: C primitive equivalent of the given `napi_value` as a -`uint32_t`. + `uint32_t`. Returns `napi_ok` if the API succeeded. If a non-number `napi_value` is passed in it returns `napi_number_expected`. @@ -2874,7 +2877,7 @@ napi_status napi_get_boolean(napi_env env, bool value, napi_value* result) * `[in] env`: The environment that the API is invoked under. * `[in] value`: The value of the boolean to retrieve. * `[out] result`: `napi_value` representing JavaScript `Boolean` singleton to -retrieve. + retrieve. Returns `napi_ok` if the API succeeded. @@ -3072,10 +3075,10 @@ napi_status napi_instanceof(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] object`: The JavaScript value to check. -* `[in] constructor`: The JavaScript function object of the constructor -function to check against. +* `[in] constructor`: The JavaScript function object of the constructor function + to check against. * `[out] result`: Boolean that is set to true if `object instanceof constructor` -is true. + is true. Returns `napi_ok` if the API succeeded. @@ -3132,7 +3135,7 @@ napi_status napi_is_buffer(napi_env env, napi_value value, bool* result) * `[in] env`: The environment that the API is invoked under. * `[in] value`: The JavaScript value to check. * `[out] result`: Whether the given `napi_value` represents a `node::Buffer` -object. + object. Returns `napi_ok` if the API succeeded. @@ -3151,7 +3154,7 @@ napi_status napi_is_date(napi_env env, napi_value value, bool* result) * `[in] env`: The environment that the API is invoked under. * `[in] value`: The JavaScript value to check. * `[out] result`: Whether the given `napi_value` represents a JavaScript `Date` -object. + object. Returns `napi_ok` if the API succeeded. @@ -3476,32 +3479,32 @@ typedef struct { ``` * `utf8name`: Optional `String` describing the key for the property, -encoded as UTF8. One of `utf8name` or `name` must be provided for the -property. + encoded as UTF8. One of `utf8name` or `name` must be provided for the + property. * `name`: Optional `napi_value` that points to a JavaScript string or symbol -to be used as the key for the property. One of `utf8name` or `name` must -be provided for the property. + to be used as the key for the property. One of `utf8name` or `name` must + be provided for the property. * `value`: The value that's retrieved by a get access of the property if the - property is a data property. If this is passed in, set `getter`, `setter`, - `method` and `data` to `NULL` (since these members won't be used). + property is a data property. If this is passed in, set `getter`, `setter`, + `method` and `data` to `NULL` (since these members won't be used). * `getter`: A function to call when a get access of the property is performed. -If this is passed in, set `value` and `method` to `NULL` (since these members -won't be used). The given function is called implicitly by the runtime when the -property is accessed from JavaScript code (or if a get on the property is -performed using a N-API call). + If this is passed in, set `value` and `method` to `NULL` (since these members + won't be used). The given function is called implicitly by the runtime when + the property is accessed from JavaScript code (or if a get on the property is + performed using a N-API call). * `setter`: A function to call when a set access of the property is performed. -If this is passed in, set `value` and `method` to `NULL` (since these members -won't be used). The given function is called implicitly by the runtime when the -property is set from JavaScript code (or if a set on the property is -performed using a N-API call). + If this is passed in, set `value` and `method` to `NULL` (since these members + won't be used). The given function is called implicitly by the runtime when + the property is set from JavaScript code (or if a set on the property is + performed using a N-API call). * `method`: Set this to make the property descriptor object's `value` -property to be a JavaScript function represented by `method`. If this is -passed in, set `value`, `getter` and `setter` to `NULL` (since these members -won't be used). -* `attributes`: The attributes associated with the particular property. -See [`napi_property_attributes`][]. -* `data`: The callback data passed into `method`, `getter` and `setter` if -this function is invoked. + property to be a JavaScript function represented by `method`. If this is + passed in, set `value`, `getter` and `setter` to `NULL` (since these members + won't be used). +* `attributes`: The attributes associated with the particular property. See + [`napi_property_attributes`][]. +* `data`: The callback data passed into `method`, `getter` and `setter` if this + function is invoked. ### Functions #### napi_get_property_names @@ -3519,9 +3522,9 @@ napi_status napi_get_property_names(napi_env env, * `[in] env`: The environment that the N-API call is invoked under. * `[in] object`: The object from which to retrieve the properties. * `[out] result`: A `napi_value` representing an array of JavaScript values -that represent the property names of the object. The API can be used to -iterate over `result` using [`napi_get_array_length`][] -and [`napi_get_element`][]. + that represent the property names of the object. The API can be used to + iterate over `result` using [`napi_get_array_length`][] + and [`napi_get_element`][]. Returns `napi_ok` if the API succeeded. @@ -3612,7 +3615,7 @@ napi_status napi_delete_property(napi_env env, * `[in] object`: The object to query. * `[in] key`: The name of the property to delete. * `[out] result`: Whether the property deletion succeeded or not. `result` can -optionally be ignored by passing `NULL`. + optionally be ignored by passing `NULL`. Returns `napi_ok` if the API succeeded. @@ -3795,7 +3798,7 @@ napi_status napi_delete_element(napi_env env, * `[in] object`: The object to query. * `[in] index`: The index of the property to delete. * `[out] result`: Whether the element deletion succeeded or not. `result` can -optionally be ignored by passing `NULL`. + optionally be ignored by passing `NULL`. Returns `napi_ok` if the API succeeded. @@ -3869,11 +3872,10 @@ NAPI_EXTERN napi_status napi_call_function(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] recv`: The `this` object passed to the called function. -* `[in] func`: `napi_value` representing the JavaScript function -to be invoked. +* `[in] func`: `napi_value` representing the JavaScript function to be invoked. * `[in] argc`: The count of elements in the `argv` array. -* `[in] argv`: Array of `napi_values` representing JavaScript values passed -in as arguments to the function. +* `[in] argv`: Array of `napi_values` representing JavaScript values passed in + as arguments to the function. * `[out] result`: `napi_value` representing the JavaScript object returned. Returns `napi_ok` if the API succeeded. @@ -3939,15 +3941,15 @@ napi_status napi_create_function(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] utf8Name`: The name of the function encoded as UTF8. This is visible -within JavaScript as the new function object's `name` property. -* `[in] length`: The length of the `utf8name` in bytes, or -`NAPI_AUTO_LENGTH` if it is null-terminated. + within JavaScript as the new function object's `name` property. +* `[in] length`: The length of the `utf8name` in bytes, or `NAPI_AUTO_LENGTH` if + it is null-terminated. * `[in] cb`: The native function which should be called when this function -object is invoked. + object is invoked. * `[in] data`: User-provided data context. This will be passed back into the -function when invoked later. + function when invoked later. * `[out] result`: `napi_value` representing the JavaScript function object for -the newly created function. + the newly created function. Returns `napi_ok` if the API succeeded. @@ -4020,13 +4022,13 @@ napi_status napi_get_cb_info(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] cbinfo`: The callback info passed into the callback function. -* `[in-out] argc`: Specifies the size of the provided `argv` array -and receives the actual count of arguments. -* `[out] argv`: Buffer to which the `napi_value` representing the -arguments are copied. If there are more arguments than the provided -count, only the requested number of arguments are copied. If there are fewer -arguments provided than claimed, the rest of `argv` is filled with `napi_value` -values that represent `undefined`. +* `[in-out] argc`: Specifies the size of the provided `argv` array and receives + the actual count of arguments. +* `[out] argv`: Buffer to which the `napi_value` representing the arguments are + copied. If there are more arguments than the provided count, only the + requested number of arguments are copied. If there are fewer arguments + provided than claimed, the rest of `argv` is filled with `napi_value` values + that represent `undefined`. * `[out] this`: Receives the JavaScript `this` argument for the call. * `[out] data`: Receives the data pointer for the callback. @@ -4071,13 +4073,13 @@ napi_status napi_new_instance(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] cons`: `napi_value` representing the JavaScript function -to be invoked as a constructor. +* `[in] cons`: `napi_value` representing the JavaScript function to be invoked + as a constructor. * `[in] argc`: The count of elements in the `argv` array. -* `[in] argv`: Array of JavaScript values as `napi_value` -representing the arguments to the constructor. +* `[in] argv`: Array of JavaScript values as `napi_value` representing the + arguments to the constructor. * `[out] result`: `napi_value` representing the JavaScript object returned, -which in this case is the constructed object. + which in this case is the constructed object. This method is used to instantiate a new JavaScript value using a given `napi_value` that represents the constructor for the object. For example, @@ -4448,18 +4450,18 @@ napi_status napi_create_async_work(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] async_resource`: An optional object associated with the async work that will be passed to possible `async_hooks` [`init` hooks][]. -* `[in] async_resource_name`: Identifier for the kind of resource that is -being provided for diagnostic information exposed by the `async_hooks` API. -* `[in] execute`: The native function which should be called to execute -the logic asynchronously. The given function is called from a worker pool -thread and can execute in parallel with the main event loop thread. +* `[in] async_resource_name`: Identifier for the kind of resource that is being + provided for diagnostic information exposed by the `async_hooks` API. +* `[in] execute`: The native function which should be called to execute the + logic asynchronously. The given function is called from a worker pool thread + and can execute in parallel with the main event loop thread. * `[in] complete`: The native function which will be called when the -asynchronous logic is completed or is cancelled. The given function is called -from the main event loop thread. + asynchronous logic is completed or is cancelled. The given function is called + from the main event loop thread. * `[in] data`: User-provided data context. This will be passed back into the -execute and complete functions. + execute and complete functions. * `[out] result`: `napi_async_work*` which is the handle to the newly created -async work. + async work. Returns `napi_ok` if the API succeeded. @@ -4540,6 +4542,7 @@ callback invocation, even if it has been successfully cancelled. This API can be called even if there is a pending JavaScript exception. ## Custom Asynchronous Operations + The simple asynchronous work APIs above may not be appropriate for every scenario. When using any other asynchronous mechanism, the following APIs are necessary to ensure an asynchronous operation is properly tracked by @@ -4612,11 +4615,10 @@ NAPI_EXTERN napi_status napi_make_callback(napi_env env, which indicates the current async context (if any) is to be used for the callback. * `[in] recv`: The `this` object passed to the called function. -* `[in] func`: `napi_value` representing the JavaScript function -to be invoked. +* `[in] func`: `napi_value` representing the JavaScript function to be invoked. * `[in] argc`: The count of elements in the `argv` array. -* `[in] argv`: Array of JavaScript values as `napi_value` -representing the arguments to the function. +* `[in] argv`: Array of JavaScript values as `napi_value` representing the + arguments to the function. * `[out] result`: `napi_value` representing the JavaScript object returned. Returns `napi_ok` if the API succeeded. @@ -4650,9 +4652,8 @@ NAPI_EXTERN napi_status napi_open_callback_scope(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] resource_object`: An object associated with the async work that will be passed to possible `async_hooks` [`init` hooks][]. -* `[in] context`: Context for the async operation that is -invoking the callback. This should be a value previously obtained -from [`napi_async_init`][]. +* `[in] context`: Context for the async operation that is invoking the callback. + This should be a value previously obtained from [`napi_async_init`][]. * `[out] result`: The newly created scope. There are cases (for example, resolving promises) where it is @@ -4754,8 +4755,8 @@ NAPI_EXTERN napi_status napi_adjust_external_memory(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] change_in_bytes`: The change in externally allocated memory that is -kept alive by JavaScript objects. +* `[in] change_in_bytes`: The change in externally allocated memory that is kept + alive by JavaScript objects. * `[out] result`: The adjusted value Returns `napi_ok` if the API succeeded. @@ -4836,8 +4837,8 @@ napi_status napi_create_promise(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[out] deferred`: A newly created deferred object which can later be passed to -`napi_resolve_deferred()` or `napi_reject_deferred()` to resolve resp. reject -the associated promise. + `napi_resolve_deferred()` or `napi_reject_deferred()` to resolve resp. reject + the associated promise. * `[out] promise`: The JavaScript promise associated with the deferred object. Returns `napi_ok` if the API succeeded. @@ -5087,25 +5088,25 @@ napi_create_threadsafe_function(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] func`: An optional JavaScript function to call from another thread. -It must be provided if `NULL` is passed to `call_js_cb`. +* `[in] func`: An optional JavaScript function to call from another thread. It + must be provided if `NULL` is passed to `call_js_cb`. * `[in] async_resource`: An optional object associated with the async work that -will be passed to possible `async_hooks` [`init` hooks][]. + will be passed to possible `async_hooks` [`init` hooks][]. * `[in] async_resource_name`: A JavaScript string to provide an identifier for -the kind of resource that is being provided for diagnostic information exposed -by the `async_hooks` API. + the kind of resource that is being provided for diagnostic information exposed + by the `async_hooks` API. * `[in] max_queue_size`: Maximum size of the queue. `0` for no limit. * `[in] initial_thread_count`: The initial number of threads, including the main -thread, which will be making use of this function. + thread, which will be making use of this function. * `[in] thread_finalize_data`: Optional data to be passed to `thread_finalize_cb`. * `[in] thread_finalize_cb`: Optional function to call when the -`napi_threadsafe_function` is being destroyed. + `napi_threadsafe_function` is being destroyed. * `[in] context`: Optional data to attach to the resulting -`napi_threadsafe_function`. + `napi_threadsafe_function`. * `[in] call_js_cb`: Optional callback which calls the JavaScript function in -response to a call on a different thread. This callback will be called on the -main thread. If not given, the JavaScript function will be called with no -parameters and with `undefined` as its `this` value. + response to a call on a different thread. This callback will be called on the + main thread. If not given, the JavaScript function will be called with no + parameters and with `undefined` as its `this` value. * `[out] result`: The asynchronous thread-safe JavaScript function. ### napi_get_threadsafe_function_context @@ -5142,11 +5143,11 @@ napi_call_threadsafe_function(napi_threadsafe_function func, * `[in] func`: The asynchronous thread-safe JavaScript function to invoke. * `[in] data`: Data to send into JavaScript via the callback `call_js_cb` -provided during the creation of the thread-safe JavaScript function. + provided during the creation of the thread-safe JavaScript function. * `[in] is_blocking`: Flag whose value can be either `napi_tsfn_blocking` to -indicate that the call should block if the queue is full or -`napi_tsfn_nonblocking` to indicate that the call should return immediately with -a status of `napi_queue_full` whenever the queue is full. + indicate that the call should block if the queue is full or + `napi_tsfn_nonblocking` to indicate that the call should return immediately + with a status of `napi_queue_full` whenever the queue is full. This API will return `napi_closing` if `napi_release_threadsafe_function()` was called with `abort` set to `napi_tsfn_abort` from any thread. The value is only @@ -5167,7 +5168,7 @@ napi_acquire_threadsafe_function(napi_threadsafe_function func); ``` * `[in] func`: The asynchronous thread-safe JavaScript function to start making -use of. + use of. A thread should call this API before passing `func` to any other thread-safe function APIs to indicate that it will be making use of `func`. This prevents @@ -5190,13 +5191,14 @@ napi_release_threadsafe_function(napi_threadsafe_function func, ``` * `[in] func`: The asynchronous thread-safe JavaScript function whose reference -count to decrement. + count to decrement. * `[in] mode`: Flag whose value can be either `napi_tsfn_release` to indicate -that the current thread will make no further calls to the thread-safe function, -or `napi_tsfn_abort` to indicate that in addition to the current thread, no -other thread should make any further calls to the thread-safe function. If set -to `napi_tsfn_abort`, further calls to `napi_call_threadsafe_function()` will -return `napi_closing`, and no further values will be placed in the queue. + that the current thread will make no further calls to the thread-safe + function, or `napi_tsfn_abort` to indicate that in addition to the current + thread, no other thread should make any further calls to the thread-safe + function. If set to `napi_tsfn_abort`, further calls to + `napi_call_threadsafe_function()` will return `napi_closing`, and no further + values will be placed in the queue. A thread should call this API when it stops making use of `func`. Passing `func` to any thread-safe APIs after having called this API has undefined results, as From bbbba76f2c95e82c3d958548fc3fc89c1d83bc4a Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Tue, 3 Dec 2019 13:15:10 -0800 Subject: [PATCH 041/117] doc,benchmark: move benchmark guide to benchmark directory The doc/guides directory looks like a place for guides to using Node.js but it's actually where we store development/internal documentation. Move the benchmark guide to the benchmark directory where someone (who doesn't know that bit of somewhat-surprising information) is more likely to find it. PR-URL: https://github.com/nodejs/node/pull/30781 Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat --- benchmark/README.md | 8 ++++---- benchmark/_http-benchmarkers.js | 2 +- .../writing-and-running-benchmarks.md | 0 doc/guides/contributing/pull-requests.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) rename {doc/guides => benchmark}/writing-and-running-benchmarks.md (100%) diff --git a/benchmark/README.md b/benchmark/README.md index 45256670fdd2aa..7e027c6e76f7b8 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -5,7 +5,7 @@ of different Node.js implementations and different ways of writing JavaScript run by the built-in JavaScript engine. For a detailed guide on how to write and run benchmarks in this -directory, see [the guide on benchmarks](../doc/guides/writing-and-running-benchmarks.md). +directory, see [the guide on benchmarks](writing-and-running-benchmarks.md). ## Table of Contents @@ -76,17 +76,17 @@ writing benchmarks. ### createBenchmark(fn, configs\[, options\]) -See [the guide on writing benchmarks](../doc/guides/writing-and-running-benchmarks.md#basics-of-a-benchmark). +See [the guide on writing benchmarks](writing-and-running-benchmarks.md#basics-of-a-benchmark). ### default\_http\_benchmarker The default benchmarker used to run HTTP benchmarks. -See [the guide on writing HTTP benchmarks](../doc/guides/writing-and-running-benchmarks.md#creating-an-http-benchmark). +See [the guide on writing HTTP benchmarks](writing-and-running-benchmarks.md#creating-an-http-benchmark). ### PORT The default port used to run HTTP benchmarks. -See [the guide on writing HTTP benchmarks](../doc/guides/writing-and-running-benchmarks.md#creating-an-http-benchmark). +See [the guide on writing HTTP benchmarks](writing-and-running-benchmarks.md#creating-an-http-benchmark). ### sendResult(data) diff --git a/benchmark/_http-benchmarkers.js b/benchmark/_http-benchmarkers.js index a4d623003947eb..7dd06be2655744 100644 --- a/benchmark/_http-benchmarkers.js +++ b/benchmark/_http-benchmarkers.js @@ -5,7 +5,7 @@ const path = require('path'); const fs = require('fs'); const requirementsURL = - 'https://github.com/nodejs/node/blob/master/doc/guides/writing-and-running-benchmarks.md#http-benchmark-requirements'; + 'https://github.com/nodejs/node/blob/master/benchmark/writing-and-running-benchmarks.md#http-benchmark-requirements'; // The port used by servers and wrk exports.PORT = Number(process.env.PORT) || 12346; diff --git a/doc/guides/writing-and-running-benchmarks.md b/benchmark/writing-and-running-benchmarks.md similarity index 100% rename from doc/guides/writing-and-running-benchmarks.md rename to benchmark/writing-and-running-benchmarks.md diff --git a/doc/guides/contributing/pull-requests.md b/doc/guides/contributing/pull-requests.md index cabc548be02556..cd1bccd20cd691 100644 --- a/doc/guides/contributing/pull-requests.md +++ b/doc/guides/contributing/pull-requests.md @@ -585,7 +585,7 @@ If you want to know more about the code review and the landing process, see the [Collaborator Guide][]. [approved]: #getting-approvals-for-your-pull-request -[benchmark results]: ../writing-and-running-benchmarks.md +[benchmark results]: ../../../benchmark/writing-and-running-benchmarks.md [Building guide]: ../../../BUILDING.md [CI (Continuous Integration) test run]: #ci-testing [Code of Conduct]: https://github.com/nodejs/admin/blob/master/CODE_OF_CONDUCT.md From 43e947a15595cc5744c724c27b3585055e74f6bd Mon Sep 17 00:00:00 2001 From: bcoe Date: Sun, 1 Dec 2019 12:55:54 -0800 Subject: [PATCH 042/117] build: remove (almost) unused macros/constants Macros, like CHECK, cause issues for tracking coverage because they modify the source before it's placed in V8. Upon investigation it seemed that we only used this functionality in two places: internal/vm/module.js, and internal/async_hooks.js (in comments). Given this, it seemed to make more sense to move CHECK to JavaScript, and retire a mostly unused build step. PR-URL: https://github.com/nodejs/node/pull/30755 Reviewed-By: Anna Henningsen Reviewed-By: Rich Trott Reviewed-By: Joyee Cheung Reviewed-By: James M Snell --- lib/.eslintrc.yaml | 15 --- lib/internal/vm/module.js | 10 +- node.gyp | 14 +-- tools/js2c.py | 144 +-------------------------- tools/js2c_macros/check_macros.py | 8 -- tools/js2c_macros/dcheck_macros.py | 9 -- tools/js2c_macros/nodcheck_macros.py | 9 -- tools/js2c_macros/notrace_macros.py | 12 --- 8 files changed, 13 insertions(+), 208 deletions(-) delete mode 100644 tools/js2c_macros/check_macros.py delete mode 100644 tools/js2c_macros/dcheck_macros.py delete mode 100644 tools/js2c_macros/nodcheck_macros.py delete mode 100644 tools/js2c_macros/notrace_macros.py diff --git a/lib/.eslintrc.yaml b/lib/.eslintrc.yaml index 2823b7aa0d1def..ff9a0f595d2225 100644 --- a/lib/.eslintrc.yaml +++ b/lib/.eslintrc.yaml @@ -46,21 +46,6 @@ rules: node-core/non-ascii-character: error globals: Intl: false - # Assertions - CHECK: false - CHECK_EQ: false - CHECK_GE: false - CHECK_GT: false - CHECK_LE: false - CHECK_LT: false - CHECK_NE: false - DCHECK: false - DCHECK_EQ: false - DCHECK_GE: false - DCHECK_GT: false - DCHECK_LE: false - DCHECK_LT: false - DCHECK_NE: false # Parameters passed to internal modules global: false require: false diff --git a/lib/internal/vm/module.js b/lib/internal/vm/module.js index 88a276e217a7fd..ee2fec2e431380 100644 --- a/lib/internal/vm/module.js +++ b/lib/internal/vm/module.js @@ -1,5 +1,6 @@ 'use strict'; +const { fail } = require('internal/assert'); const { ArrayIsArray, ObjectCreate, @@ -58,6 +59,11 @@ const kContext = Symbol('kContext'); const kPerContextModuleId = Symbol('kPerContextModuleId'); const kLink = Symbol('kLink'); +function failIfDebug() { + if (process.features.debug === false) return; + fail('VM Modules'); +} + class Module { constructor(options) { emitExperimentalWarning('VM Modules'); @@ -118,7 +124,7 @@ class Module { syntheticExportNames, syntheticEvaluationSteps); } else { - CHECK(false); + failIfDebug(); } wrapToModuleMap.set(this[kWrap], this); @@ -374,7 +380,7 @@ class SyntheticModule extends Module { identifier, }); - this[kLink] = () => this[kWrap].link(() => { CHECK(false); }); + this[kLink] = () => this[kWrap].link(() => { failIfDebug(); }); } setExport(name, value) { diff --git a/node.gyp b/node.gyp index 8becce9062edef..0a6bbd61009e84 100644 --- a/node.gyp +++ b/node.gyp @@ -892,23 +892,11 @@ # Put the code first so it's a dependency and can be used for invocation. 'tools/js2c.py', '<@(library_files)', - 'config.gypi', - 'tools/js2c_macros/check_macros.py' + 'config.gypi' ], 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/node_javascript.cc', ], - 'conditions': [ - [ 'node_use_dtrace=="false" and node_use_etw=="false"', { - 'inputs': [ 'tools/js2c_macros/notrace_macros.py' ] - }], - [ 'node_debug_lib=="false"', { - 'inputs': [ 'tools/js2c_macros/nodcheck_macros.py' ] - }], - [ 'node_debug_lib=="true"', { - 'inputs': [ 'tools/js2c_macros/dcheck_macros.py' ] - }] - ], 'action': [ 'python', '<@(_inputs)', '--target', '<@(_outputs)', diff --git a/tools/js2c.py b/tools/js2c.py index 1346b2a87046d3..4594694a2cab0d 100755 --- a/tools/js2c.py +++ b/tools/js2c.py @@ -45,137 +45,6 @@ def ReadFile(filename): return lines -def ReadMacroFiles(filenames): - """ - - :rtype: List(str) - """ - result = [] - for filename in filenames: - with open(filename, "rt") as f: - # strip python-like comments and whitespace padding - lines = [line.split('#')[0].strip() for line in f] - # filter empty lines - result.extend(filter(bool, lines)) - return result - - -def ExpandConstants(lines, constants): - for key, value in constants.items(): - lines = lines.replace(key, str(value)) - return lines - - -def ExpandMacros(lines, macros): - def expander(s): - return ExpandMacros(s, macros) - - for name, macro in macros.items(): - name_pattern = re.compile("\\b%s\\(" % name) - pattern_match = name_pattern.search(lines, 0) - while pattern_match is not None: - # Scan over the arguments - height = 1 - start = pattern_match.start() - end = pattern_match.end() - assert lines[end - 1] == '(' - last_match = end - arg_index = [0] # Wrap state into array, to work around Python "scoping" - mapping = {} - - def add_arg(s): - # Remember to expand recursively in the arguments - if arg_index[0] >= len(macro.args): - return - replacement = expander(s.strip()) - mapping[macro.args[arg_index[0]]] = replacement - arg_index[0] += 1 - - while end < len(lines) and height > 0: - # We don't count commas at higher nesting levels. - if lines[end] == ',' and height == 1: - add_arg(lines[last_match:end]) - last_match = end + 1 - elif lines[end] in ['(', '{', '[']: - height = height + 1 - elif lines[end] in [')', '}', ']']: - height = height - 1 - end = end + 1 - # Remember to add the last match. - add_arg(lines[last_match:end - 1]) - if arg_index[0] < len(macro.args) - 1: - lineno = lines.count(os.linesep, 0, start) + 1 - raise Exception( - 'line %s: Too few arguments for macro "%s"' % (lineno, name)) - result = macro.expand(mapping) - # Replace the occurrence of the macro with the expansion - lines = lines[:start] + result + lines[end:] - pattern_match = name_pattern.search(lines, start + len(result)) - return lines - - -class TextMacro: - def __init__(self, args, body): - self.args = args - self.body = body - - def expand(self, mapping): - result = self.body - for key, value in mapping.items(): - result = result.replace(key, value) - return result - - -class PythonMacro: - def __init__(self, args, fun): - self.args = args - self.fun = fun - - def expand(self, mapping): - args = [] - for arg in self.args: - args.append(mapping[arg]) - return str(self.fun(*args)) - - -CONST_PATTERN = re.compile('^const\s+([a-zA-Z0-9_]+)\s*=\s*([^;]*);$') -MACRO_PATTERN = re.compile('^macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$') -PYTHON_MACRO_PATTERN = re.compile('^python\s+macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$') - - -def ReadMacros(macro_files): - lines = ReadMacroFiles(macro_files) - constants = {} - macros = {} - for line in lines: - line = line.split('#')[0].strip() - if len(line) == 0: - continue - const_match = CONST_PATTERN.match(line) - if const_match: - name = const_match.group(1) - value = const_match.group(2).strip() - constants[name] = value - else: - macro_match = MACRO_PATTERN.match(line) - if macro_match: - name = macro_match.group(1) - args = [p.strip() for p in macro_match.group(2).split(',')] - body = macro_match.group(3).strip() - macros[name] = TextMacro(args, body) - else: - python_match = PYTHON_MACRO_PATTERN.match(line) - if python_match: - name = python_match.group(1) - args = [p.strip() for p in macro_match.group(2).split(',')] - body = python_match.group(3).strip() - fun = eval("lambda " + ",".join(args) + ': ' + body) - macros[name] = PythonMacro(args, fun) - else: - raise Exception("Illegal line: " + line) - return constants, macros - - TEMPLATE = """ #include "env-inl.h" #include "node_native_module.h" @@ -243,10 +112,8 @@ def GetDefinition(var, source, step=30): return definition, len(code_points) -def AddModule(filename, consts, macros, definitions, initializers): +def AddModule(filename, definitions, initializers): code = ReadFile(filename) - code = ExpandConstants(code, consts) - code = ExpandMacros(code, macros) name = NormalizeFileName(filename) slug = SLUGGER_RE.sub('_', name) var = slug + '_raw' @@ -267,15 +134,12 @@ def NormalizeFileName(filename): def JS2C(source_files, target): - # Process input from all *macro.py files - consts, macros = ReadMacros(source_files['.py']) - # Build source code lines definitions = [] initializers = [] for filename in source_files['.js']: - AddModule(filename, consts, macros, definitions, initializers) + AddModule(filename, definitions, initializers) config_def, config_size = handle_config_gypi(source_files['config.gypi']) definitions.append(config_def) @@ -341,8 +205,8 @@ def main(): global is_verbose is_verbose = options.verbose source_files = functools.reduce(SourceFileByExt, options.sources, {}) - # Should have exactly 3 types: `.js`, `.py`, and `.gypi` - assert len(source_files) == 3 + # Should have exactly 2 types: `.js`, and `.gypi` + assert len(source_files) == 2 # Currently config.gypi is the only `.gypi` file allowed assert source_files['.gypi'] == ['config.gypi'] source_files['config.gypi'] = source_files.pop('.gypi')[0] diff --git a/tools/js2c_macros/check_macros.py b/tools/js2c_macros/check_macros.py deleted file mode 100644 index f24d47c9ee40bf..00000000000000 --- a/tools/js2c_macros/check_macros.py +++ /dev/null @@ -1,8 +0,0 @@ -# flake8: noqa -macro CHECK(x) = do { if (!(x)) (process._rawDebug("CHECK: x == true"), process.abort()) } while (0); -macro CHECK_EQ(a, b) = CHECK((a) === (b)); -macro CHECK_GE(a, b) = CHECK((a) >= (b)); -macro CHECK_GT(a, b) = CHECK((a) > (b)); -macro CHECK_LE(a, b) = CHECK((a) <= (b)); -macro CHECK_LT(a, b) = CHECK((a) < (b)); -macro CHECK_NE(a, b) = CHECK((a) !== (b)); diff --git a/tools/js2c_macros/dcheck_macros.py b/tools/js2c_macros/dcheck_macros.py deleted file mode 100644 index f22c08598fd694..00000000000000 --- a/tools/js2c_macros/dcheck_macros.py +++ /dev/null @@ -1,9 +0,0 @@ -# flake8: noqa - -macro DCHECK(x) = do { if (!(x)) (process._rawDebug("DCHECK: x == true"), process.abort()) } while (0); -macro DCHECK_EQ(a, b) = DCHECK((a) === (b)); -macro DCHECK_GE(a, b) = DCHECK((a) >= (b)); -macro DCHECK_GT(a, b) = DCHECK((a) > (b)); -macro DCHECK_LE(a, b) = DCHECK((a) <= (b)); -macro DCHECK_LT(a, b) = DCHECK((a) < (b)); -macro DCHECK_NE(a, b) = DCHECK((a) !== (b)); diff --git a/tools/js2c_macros/nodcheck_macros.py b/tools/js2c_macros/nodcheck_macros.py deleted file mode 100644 index 0a59001b549fe5..00000000000000 --- a/tools/js2c_macros/nodcheck_macros.py +++ /dev/null @@ -1,9 +0,0 @@ -# flake8: noqa - -macro DCHECK(x) = void(x); -macro DCHECK_EQ(a, b) = void(a, b); -macro DCHECK_GE(a, b) = void(a, b); -macro DCHECK_GT(a, b) = void(a, b); -macro DCHECK_LE(a, b) = void(a, b); -macro DCHECK_LT(a, b) = void(a, b); -macro DCHECK_NE(a, b) = void(a, b); diff --git a/tools/js2c_macros/notrace_macros.py b/tools/js2c_macros/notrace_macros.py deleted file mode 100644 index 334f9c0c7f7a87..00000000000000 --- a/tools/js2c_macros/notrace_macros.py +++ /dev/null @@ -1,12 +0,0 @@ -# This file is used by tools/js2c.py to preprocess out the DTRACE symbols in -# builds that don't support DTrace. This is not used in builds that support -# DTrace. - -# flake8: noqa - -macro DTRACE_HTTP_CLIENT_REQUEST(x) = ; -macro DTRACE_HTTP_CLIENT_RESPONSE(x) = ; -macro DTRACE_HTTP_SERVER_REQUEST(x) = ; -macro DTRACE_HTTP_SERVER_RESPONSE(x) = ; -macro DTRACE_NET_SERVER_CONNECTION(x) = ; -macro DTRACE_NET_STREAM_END(x) = ; From 3840abed11b682e1a70f6de1a1dba04bddae547a Mon Sep 17 00:00:00 2001 From: Denys Otrishko Date: Sun, 10 Nov 2019 14:22:46 +0200 Subject: [PATCH 043/117] http2: small clean up in OnStreamRead PR-URL: https://github.com/nodejs/node/pull/30351 Reviewed-By: Anna Henningsen Reviewed-By: David Carlier Reviewed-By: James M Snell --- src/node_http2.cc | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/node_http2.cc b/src/node_http2.cc index 9421c36f3be561..2bcbcbe0784747 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -1867,14 +1867,10 @@ void Http2Session::OnStreamRead(ssize_t nread, const uv_buf_t& buf_) { // call in OnStreamAfterWrite() immediately provides data. If that does // happen, we concatenate the data we received with the already-stored // pending input data, slicing off the already processed part. - AllocatedBuffer new_buf = env()->AllocateManaged( - stream_buf_.len - stream_buf_offset_ + nread); - memcpy(new_buf.data(), - stream_buf_.base + stream_buf_offset_, - stream_buf_.len - stream_buf_offset_); - memcpy(new_buf.data() + stream_buf_.len - stream_buf_offset_, - buf.data(), - nread); + size_t pending_len = stream_buf_.len - stream_buf_offset_; + AllocatedBuffer new_buf = env()->AllocateManaged(pending_len + nread); + memcpy(new_buf.data(), stream_buf_.base + stream_buf_offset_, pending_len); + memcpy(new_buf.data() + pending_len, buf.data(), nread); buf = std::move(new_buf); nread = buf.size(); stream_buf_offset_ = 0; From 71bb026e0c1e2afb285ecb46cb82c1834dbb1ba1 Mon Sep 17 00:00:00 2001 From: Denys Otrishko Date: Sun, 1 Dec 2019 18:20:01 +0200 Subject: [PATCH 044/117] http2: streamline OnStreamRead streamline memory accounting * avoid consecutive decrement/increment session memory calls. * only Resize the buffer when it is needed. * flip `stream_buf_offset_` condition to the LIKELY case. PR-URL: https://github.com/nodejs/node/pull/30351 Reviewed-By: Anna Henningsen Reviewed-By: David Carlier Reviewed-By: James M Snell --- src/node_http2.cc | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/node_http2.cc b/src/node_http2.cc index 2bcbcbe0784747..33960af1845a15 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -1862,7 +1862,11 @@ void Http2Session::OnStreamRead(ssize_t nread, const uv_buf_t& buf_) { statistics_.data_received += nread; - if (UNLIKELY(stream_buf_offset_ > 0)) { + if (LIKELY(stream_buf_offset_ == 0)) { + // Shrink to the actual amount of used data. + buf.Resize(nread); + IncrementCurrentSessionMemory(nread); + } else { // This is a very unlikely case, and should only happen if the ReadStart() // call in OnStreamAfterWrite() immediately provides data. If that does // happen, we concatenate the data we received with the already-stored @@ -1871,20 +1875,18 @@ void Http2Session::OnStreamRead(ssize_t nread, const uv_buf_t& buf_) { AllocatedBuffer new_buf = env()->AllocateManaged(pending_len + nread); memcpy(new_buf.data(), stream_buf_.base + stream_buf_offset_, pending_len); memcpy(new_buf.data() + pending_len, buf.data(), nread); + + // The data in stream_buf_ is already accounted for, add nread received + // bytes to session memory but remove the already processed + // stream_buf_offset_ bytes. + IncrementCurrentSessionMemory(nread - stream_buf_offset_); + buf = std::move(new_buf); nread = buf.size(); stream_buf_offset_ = 0; stream_buf_ab_.Reset(); - - // We have now fully processed the stream_buf_ input chunk (by moving the - // remaining part into buf, which will be accounted for below). - DecrementCurrentSessionMemory(stream_buf_.len); } - // Shrink to the actual amount of used data. - buf.Resize(nread); - IncrementCurrentSessionMemory(nread); - // Remember the current buffer, so that OnDataChunkReceived knows the // offset of a DATA frame's data into the socket read buffer. stream_buf_ = uv_buf_init(buf.data(), nread); From c440f3fa3d4eb70c346c640ddeb99f35887c8808 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 23 Sep 2019 19:38:12 +0200 Subject: [PATCH 045/117] repl: use better uncaught exceptions indicator This switches "Thrown:" with "Uncaught" to outline clearer that the thrown error is not caught. PR-URL: https://github.com/nodejs/node/pull/29676 Reviewed-By: Gus Caplan Reviewed-By: James M Snell --- lib/repl.js | 25 +++++-- test/parallel/test-repl-harmony.js | 2 +- test/parallel/test-repl-null-thrown.js | 2 +- .../parallel/test-repl-pretty-custom-stack.js | 12 ++-- test/parallel/test-repl-pretty-stack.js | 19 +++--- test/parallel/test-repl-top-level-await.js | 10 +-- ...test-repl-uncaught-exception-standalone.js | 3 +- test/parallel/test-repl-uncaught-exception.js | 25 ++++--- test/parallel/test-repl-underscore.js | 12 ++-- test/parallel/test-repl.js | 67 +++++++------------ 10 files changed, 90 insertions(+), 87 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index c1473588d3942c..55daf2f47f6337 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -552,11 +552,28 @@ function REPLServer(prompt, }); } else { if (errStack === '') { - errStack = `Thrown: ${self.writer(e)}\n`; - } else { - const ln = errStack.endsWith('\n') ? '' : '\n'; - errStack = `Thrown:\n${errStack}${ln}`; + errStack = self.writer(e); + } + const lines = errStack.split(/(?<=\n)/); + let matched = false; + + errStack = ''; + for (const line of lines) { + if (!matched && /^\[?([A-Z][a-z0-9_]*)*Error/.test(line)) { + errStack += writer.options.breakLength >= line.length ? + `Uncaught ${line}` : + `Uncaught:\n${line}`; + matched = true; + } else { + errStack += line; + } + } + if (!matched) { + const ln = lines.length === 1 ? ' ' : ':\n'; + errStack = `Uncaught${ln}${errStack}`; } + // Normalize line endings. + errStack += errStack.endsWith('\n') ? '' : '\n'; top.outputStream.write(errStack); top.clearBufferedCommand(); top.lines.level = []; diff --git a/test/parallel/test-repl-harmony.js b/test/parallel/test-repl-harmony.js index 0aa8e56bdd6e2e..88b2c9deca1b05 100644 --- a/test/parallel/test-repl-harmony.js +++ b/test/parallel/test-repl-harmony.js @@ -30,7 +30,7 @@ const child = spawn(process.execPath, args); const input = '(function(){"use strict"; const y=1;y=2})()\n'; // This message will vary based on JavaScript engine, so don't check the message // contents beyond confirming that the `Error` is a `TypeError`. -const expectOut = /> Thrown:\nTypeError: /; +const expectOut = /> Uncaught TypeError: /; child.stderr.setEncoding('utf8'); child.stderr.on('data', (d) => { diff --git a/test/parallel/test-repl-null-thrown.js b/test/parallel/test-repl-null-thrown.js index 1fe5d30396d534..0ed4a05fd5de55 100644 --- a/test/parallel/test-repl-null-thrown.js +++ b/test/parallel/test-repl-null-thrown.js @@ -20,5 +20,5 @@ replserver.emit('line', '.exit'); setTimeout(() => { console.log(text); - assert(text.includes('Thrown: null')); + assert(text.includes('Uncaught null')); }, 0); diff --git a/test/parallel/test-repl-pretty-custom-stack.js b/test/parallel/test-repl-pretty-custom-stack.js index 0d2ada134fe2f8..8f633a4d4808c5 100644 --- a/test/parallel/test-repl-pretty-custom-stack.js +++ b/test/parallel/test-repl-pretty-custom-stack.js @@ -48,26 +48,26 @@ const tests = [ { // test .load for a file that throws command: `.load ${fixtures.path('repl-pretty-stack.js')}`, - expected: 'Thrown:\nError: Whoops!--->\nrepl:*:*--->\nd (repl:*:*)' + + expected: 'Uncaught Error: Whoops!--->\nrepl:*:*--->\nd (repl:*:*)' + '--->\nc (repl:*:*)--->\nb (repl:*:*)--->\na (repl:*:*)\n' }, { command: 'let x y;', - expected: 'Thrown:\n' + - 'let x y;\n ^\n\nSyntaxError: Unexpected identifier\n' + expected: 'let x y;\n ^\n\n' + + 'Uncaught SyntaxError: Unexpected identifier\n' }, { command: 'throw new Error(\'Whoops!\')', - expected: 'Thrown:\nError: Whoops!\n' + expected: 'Uncaught Error: Whoops!\n' }, { command: 'foo = bar;', - expected: 'Thrown:\nReferenceError: bar is not defined\n' + expected: 'Uncaught ReferenceError: bar is not defined\n' }, // test anonymous IIFE { command: '(function() { throw new Error(\'Whoops!\'); })()', - expected: 'Thrown:\nError: Whoops!--->\nrepl:*:*\n' + expected: 'Uncaught Error: Whoops!--->\nrepl:*:*\n' } ]; diff --git a/test/parallel/test-repl-pretty-stack.js b/test/parallel/test-repl-pretty-stack.js index 9f307c4f430b8c..456e866b7b20f9 100644 --- a/test/parallel/test-repl-pretty-stack.js +++ b/test/parallel/test-repl-pretty-stack.js @@ -7,7 +7,7 @@ const repl = require('repl'); const stackRegExp = /(at .*repl:)[0-9]+:[0-9]+/g; -function run({ command, expected, ...extraREPLOptions }) { +function run({ command, expected, ...extraREPLOptions }, i) { let accum = ''; const inputStream = new ArrayStream(); @@ -25,6 +25,7 @@ function run({ command, expected, ...extraREPLOptions }) { }); r.write(`${command}\n`); + console.log(i); assert.strictEqual( accum.replace(stackRegExp, '$1*:*'), expected.replace(stackRegExp, '$1*:*') @@ -36,39 +37,39 @@ const tests = [ { // Test .load for a file that throws. command: `.load ${fixtures.path('repl-pretty-stack.js')}`, - expected: 'Thrown:\nError: Whoops!\n at repl:*:*\n' + + expected: 'Uncaught Error: Whoops!\n at repl:*:*\n' + ' at d (repl:*:*)\n at c (repl:*:*)\n' + ' at b (repl:*:*)\n at a (repl:*:*)\n' }, { command: 'let x y;', - expected: 'Thrown:\n' + - 'let x y;\n ^\n\nSyntaxError: Unexpected identifier\n' + expected: 'let x y;\n ^\n\n' + + 'Uncaught SyntaxError: Unexpected identifier\n' }, { command: 'throw new Error(\'Whoops!\')', - expected: 'Thrown:\nError: Whoops!\n' + expected: 'Uncaught Error: Whoops!\n' }, { command: '(() => { const err = Error(\'Whoops!\'); ' + 'err.foo = \'bar\'; throw err; })()', - expected: "Thrown:\nError: Whoops!\n at repl:*:* {\n foo: 'bar'\n}\n", + expected: "Uncaught Error: Whoops!\n at repl:*:* {\n foo: 'bar'\n}\n", }, { command: '(() => { const err = Error(\'Whoops!\'); ' + 'err.foo = \'bar\'; throw err; })()', - expected: 'Thrown:\nError: Whoops!\n at repl:*:* {\n foo: ' + + expected: 'Uncaught Error: Whoops!\n at repl:*:* {\n foo: ' + "\u001b[32m'bar'\u001b[39m\n}\n", useColors: true }, { command: 'foo = bar;', - expected: 'Thrown:\nReferenceError: bar is not defined\n' + expected: 'Uncaught ReferenceError: bar is not defined\n' }, // Test anonymous IIFE. { command: '(function() { throw new Error(\'Whoops!\'); })()', - expected: 'Thrown:\nError: Whoops!\n at repl:*:*\n' + expected: 'Uncaught Error: Whoops!\n at repl:*:*\n' } ]; diff --git a/test/parallel/test-repl-top-level-await.js b/test/parallel/test-repl-top-level-await.js index f629d3f1d0d428..5c8aa95d40ec05 100644 --- a/test/parallel/test-repl-top-level-await.js +++ b/test/parallel/test-repl-top-level-await.js @@ -118,15 +118,15 @@ async function ordinaryTests() { [ 'if (await true) { function bar() {}; }', 'undefined' ], [ 'bar', '[Function: bar]' ], [ 'if (await true) { class Bar {}; }', 'undefined' ], - [ 'Bar', 'ReferenceError: Bar is not defined', { line: 1 } ], + [ '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', 'ReferenceError: j is not defined', { line: 1 } ], + [ 'j', 'Uncaught ReferenceError: j is not defined' ], [ 'gen', '[GeneratorFunction: gen]' ], - [ 'return 42; await 5;', 'SyntaxError: Illegal return statement', - { line: 4 } ], + [ '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' ], @@ -160,7 +160,7 @@ async function ctrlCTest() { { ctrl: true, name: 'c' } ]), [ 'await timeout(100000)\r', - 'Thrown:', + 'Uncaught:', '[Error [ERR_SCRIPT_EXECUTION_INTERRUPTED]: ' + 'Script execution was interrupted by `SIGINT`] {', " code: 'ERR_SCRIPT_EXECUTION_INTERRUPTED'", diff --git a/test/parallel/test-repl-uncaught-exception-standalone.js b/test/parallel/test-repl-uncaught-exception-standalone.js index ae7b214fefae9e..e7371f9f7c617f 100644 --- a/test/parallel/test-repl-uncaught-exception-standalone.js +++ b/test/parallel/test-repl-uncaught-exception-standalone.js @@ -18,8 +18,7 @@ child.on('exit', common.mustCall(() => { [ 'Type ".help" for more information.', // x\n - '> Thrown:', - 'ReferenceError: x is not defined', + '> Uncaught ReferenceError: x is not defined', // Added `uncaughtException` listener. '> short', 'undefined', diff --git a/test/parallel/test-repl-uncaught-exception.js b/test/parallel/test-repl-uncaught-exception.js index 447b69b1d4a29e..28e62dff22bf3a 100644 --- a/test/parallel/test-repl-uncaught-exception.js +++ b/test/parallel/test-repl-uncaught-exception.js @@ -6,7 +6,7 @@ const repl = require('repl'); let count = 0; -function run({ command, expected }) { +function run({ command, expected, useColors = false }) { let accum = ''; const output = new ArrayStream(); @@ -17,7 +17,7 @@ function run({ command, expected }) { input: new ArrayStream(), output, terminal: false, - useColors: false + useColors }); r.write(`${command}\n`); @@ -30,35 +30,40 @@ function run({ command, expected }) { // Verify that the repl is still working as expected. accum = ''; r.write('1 + 1\n'); - assert.strictEqual(accum, '2\n'); + // eslint-disable-next-line no-control-regex + assert.strictEqual(accum.replace(/\u001b\[[0-9]+m/g, ''), '2\n'); r.close(); count++; } const tests = [ { + useColors: true, command: 'x', - expected: 'Thrown:\n' + - 'ReferenceError: x is not defined\n' + expected: 'Uncaught ReferenceError: x is not defined\n' + }, + { + useColors: true, + command: 'throw { foo: "test" }', + expected: "Uncaught { foo: \x1B[32m'test'\x1B[39m }\n" }, { command: 'process.on("uncaughtException", () => console.log("Foobar"));\n', - expected: /^Thrown:\nTypeError \[ERR_INVALID_REPL_INPUT]: Listeners for `/ + expected: /^Uncaught:\nTypeError \[ERR_INVALID_REPL_INPUT]: Listeners for `/ }, { command: 'x;\n', - expected: 'Thrown:\n' + - 'ReferenceError: x is not defined\n' + expected: 'Uncaught ReferenceError: x is not defined\n' }, { command: 'process.on("uncaughtException", () => console.log("Foobar"));' + 'console.log("Baz");\n', - expected: /^Thrown:\nTypeError \[ERR_INVALID_REPL_INPUT]: Listeners for `/ + expected: /^Uncaught:\nTypeError \[ERR_INVALID_REPL_INPUT]: Listeners for `/ }, { command: 'console.log("Baz");' + 'process.on("uncaughtException", () => console.log("Foobar"));\n', - expected: /^Baz\nThrown:\nTypeError \[ERR_INVALID_REPL_INPUT]:.*uncaughtException/ + expected: /^Baz\nUncaught:\nTypeError \[ERR_INVALID_REPL_INPUT]:.*uncaughtException/ } ]; diff --git a/test/parallel/test-repl-underscore.js b/test/parallel/test-repl-underscore.js index 2e0865f5a75b16..c05c387471b59f 100644 --- a/test/parallel/test-repl-underscore.js +++ b/test/parallel/test-repl-underscore.js @@ -173,13 +173,11 @@ function testError() { 'undefined', // The error, both from the original throw and the `_error` echo. - 'Thrown:', - 'Error: foo', + 'Uncaught Error: foo', '[Error: foo]', // The sync error, with individual property echoes - 'Thrown:', - /^Error: ENOENT: no such file or directory, scandir '.*nonexistent\?'/, + /^Uncaught Error: ENOENT: no such file or directory, scandir '.*nonexistent\?'/, /Object\.readdirSync/, /^ errno: -(2|4058),$/, " syscall: 'scandir',", @@ -194,8 +192,7 @@ function testError() { 'undefined', // The message from the original throw - 'Thrown:', - 'Error: baz', + 'Uncaught Error: baz', ]; for (const line of lines) { const expected = expectedLines.shift(); @@ -218,8 +215,7 @@ function testError() { "'baz'", 'Expression assignment to _error now disabled.', '0', - 'Thrown:', - 'Error: quux', + 'Uncaught Error: quux', '0' ]); }); diff --git a/test/parallel/test-repl.js b/test/parallel/test-repl.js index 05608bd5ee6ac3..b0dad397ccc06b 100644 --- a/test/parallel/test-repl.js +++ b/test/parallel/test-repl.js @@ -126,7 +126,7 @@ const unixTests = [ const strictModeTests = [ { send: 'ref = 1', - expect: ['Thrown:', /^ReferenceError:\s/] + expect: [/^Uncaught ReferenceError:\s/] } ]; @@ -134,11 +134,11 @@ const errorTests = [ // Uncaught error throws and prints out { send: 'throw new Error(\'test error\');', - expect: ['Thrown:', 'Error: test error'] + expect: ['Uncaught Error: test error'] }, { send: "throw { foo: 'bar' };", - expect: "Thrown: { foo: 'bar' }" + expect: "Uncaught { foo: 'bar' }" }, // Common syntax error is treated as multiline command { @@ -153,7 +153,7 @@ const errorTests = [ // But passing the same string to eval() should throw { send: 'eval("function test_func() {")', - expect: ['Thrown:', /^SyntaxError: /] + expect: [/^Uncaught SyntaxError: /] }, // Can handle multiline template literals { @@ -210,89 +210,84 @@ const errorTests = [ // should throw { send: 'JSON.parse(\'{invalid: \\\'json\\\'}\');', - expect: ['Thrown:', /^SyntaxError: /] + expect: [/^Uncaught SyntaxError: /] }, // End of input to JSON.parse error is special case of syntax error, // should throw { send: 'JSON.parse(\'066\');', - expect: ['Thrown:', /^SyntaxError: /] + expect: [/^Uncaught SyntaxError: /] }, // should throw { send: 'JSON.parse(\'{\');', - expect: ['Thrown:', /^SyntaxError: /] + expect: [/^Uncaught SyntaxError: /] }, // invalid RegExps are a special case of syntax error, // should throw { send: '/(/;', - expect: ['Thrown:', /^SyntaxError: /] + expect: [/^Uncaught SyntaxError: /] }, // invalid RegExp modifiers are a special case of syntax error, // should throw (GH-4012) { send: 'new RegExp("foo", "wrong modifier");', - expect: ['Thrown:', /^SyntaxError: /] + expect: [/^Uncaught SyntaxError: /] }, // Strict mode syntax errors should be caught (GH-5178) { send: '(function() { "use strict"; return 0755; })()', expect: [ - 'Thrown:', kSource, kArrow, '', - /^SyntaxError: / + /^Uncaught SyntaxError: / ] }, { send: '(function(a, a, b) { "use strict"; return a + b + c; })()', expect: [ - 'Thrown:', kSource, kArrow, '', - /^SyntaxError: / + /^Uncaught SyntaxError: / ] }, { send: '(function() { "use strict"; with (this) {} })()', expect: [ - 'Thrown:', kSource, kArrow, '', - /^SyntaxError: / + /^Uncaught SyntaxError: / ] }, { send: '(function() { "use strict"; var x; delete x; })()', expect: [ - 'Thrown:', kSource, kArrow, '', - /^SyntaxError: / + /^Uncaught SyntaxError: / ] }, { send: '(function() { "use strict"; eval = 17; })()', expect: [ - 'Thrown:', kSource, kArrow, '', - /^SyntaxError: / + /^Uncaught SyntaxError: / ] }, { send: '(function() { "use strict"; if (true) function f() { } })()', expect: [ - 'Thrown:', kSource, kArrow, '', + 'Uncaught:', /^SyntaxError: / ] }, @@ -413,11 +408,10 @@ const errorTests = [ { send: '[] \\', expect: [ - 'Thrown:', kSource, kArrow, '', - /^SyntaxError: / + /^Uncaught SyntaxError: / ] }, // Do not fail when a String is created with line continuation @@ -548,8 +542,7 @@ const errorTests = [ { send: 'require("internal/repl")', expect: [ - 'Thrown:', - /^Error: Cannot find module 'internal\/repl'/, + /^Uncaught Error: Cannot find module 'internal\/repl'/, /^Require stack:/, /^- /, /^ at .*/, @@ -587,11 +580,10 @@ const errorTests = [ { send: 'a = 3.5e', expect: [ - 'Thrown:', kSource, kArrow, '', - /^SyntaxError: / + /^Uncaught SyntaxError: / ] }, // Mitigate https://github.com/nodejs/node/issues/548 @@ -607,22 +599,20 @@ const errorTests = [ { send: 'a = 3.5e', expect: [ - 'Thrown:', kSource, kArrow, '', - /^SyntaxError: / + /^Uncaught SyntaxError: / ] }, // Avoid emitting stack trace { send: 'a = 3.5e', expect: [ - 'Thrown:', kSource, kArrow, '', - /^SyntaxError: / + /^Uncaught SyntaxError: / ] }, @@ -687,11 +677,10 @@ const errorTests = [ { send: '...[]', expect: [ - 'Thrown:', kSource, kArrow, '', - /^SyntaxError: / + /^Uncaught SyntaxError: / ] }, // Bring back the repl to prompt @@ -702,31 +691,28 @@ const errorTests = [ { send: 'console.log("Missing comma in arg list" process.version)', expect: [ - 'Thrown:', kSource, kArrow, '', - /^SyntaxError: / + /^Uncaught SyntaxError: / ] }, { send: 'x = {\nfield\n{', expect: [ - '... ... Thrown:', - '{', + '... ... {', kArrow, '', - /^SyntaxError: / + /^Uncaught SyntaxError: / ] }, { send: '(2 + 3))', expect: [ - 'Thrown:', kSource, kArrow, '', - /^SyntaxError: / + /^Uncaught SyntaxError: / ] }, { @@ -740,11 +726,10 @@ const errorTests = [ { send: '} else {', expect: [ - 'Thrown:', kSource, kArrow, '', - /^SyntaxError: / + /^Uncaught SyntaxError: / ] }, ]; From 0cb7720dd804f629264bd02a675917c87b7f9e0a Mon Sep 17 00:00:00 2001 From: Albert Wang Date: Sat, 2 Nov 2019 18:08:46 -0700 Subject: [PATCH 046/117] tools: update icu to 65.1 Update the version of the bundled ICU (deps/icu-small) to ICU version 65.2. Fixes: https://github.com/nodejs/node/issues/30211 Fixes: https://github.com/nodejs/node/issues/29540 PR-URL: https://github.com/nodejs/node/pull/30232 Reviewed-By: Steven R Loomis Reviewed-By: Michael Dawson Reviewed-By: Ujjwal Sharma --- deps/icu-small/README-FULL-ICU.txt | 4 +- deps/icu-small/source/common/brkeng.cpp | 2 +- deps/icu-small/source/common/brkiter.cpp | 2 +- deps/icu-small/source/common/bytesinkutil.h | 2 +- .../source/common/characterproperties.cpp | 13 +- deps/icu-small/source/common/charstr.cpp | 23 + deps/icu-small/source/common/charstr.h | 14 + deps/icu-small/source/common/cmemory.h | 45 +- deps/icu-small/source/common/edits.cpp | 2 +- deps/icu-small/source/common/filteredbrk.cpp | 2 +- .../icu-small/source/common/localebuilder.cpp | 60 +- .../icu-small/source/common/localematcher.cpp | 720 ++++++++++++++++++ .../source/common/localeprioritylist.cpp | 239 ++++++ .../source/common/localeprioritylist.h | 115 +++ deps/icu-small/source/common/locavailable.cpp | 206 +++-- deps/icu-small/source/common/locbased.h | 2 +- deps/icu-small/source/common/locdistance.cpp | 364 +++++++++ deps/icu-small/source/common/locdistance.h | 109 +++ deps/icu-small/source/common/locdspnm.cpp | 100 ++- deps/icu-small/source/common/locid.cpp | 25 +- deps/icu-small/source/common/loclikely.cpp | 30 +- .../source/common/loclikelysubtags.cpp | 638 ++++++++++++++++ .../source/common/loclikelysubtags.h | 143 ++++ deps/icu-small/source/common/lsr.cpp | 101 +++ deps/icu-small/source/common/lsr.h | 72 ++ deps/icu-small/source/common/mutex.h | 72 +- .../icu-small/source/common/normalizer2impl.h | 6 +- deps/icu-small/source/common/putil.cpp | 46 +- deps/icu-small/source/common/putilimp.h | 70 -- deps/icu-small/source/common/rbbi.cpp | 12 +- deps/icu-small/source/common/rbbi_cache.cpp | 2 +- deps/icu-small/source/common/resbund.cpp | 3 +- deps/icu-small/source/common/resource.h | 24 +- deps/icu-small/source/common/restrace.cpp | 130 ++++ deps/icu-small/source/common/restrace.h | 147 ++++ deps/icu-small/source/common/schriter.cpp | 2 +- deps/icu-small/source/common/serv.cpp | 21 +- deps/icu-small/source/common/servls.cpp | 2 +- deps/icu-small/source/common/servnotf.cpp | 13 +- deps/icu-small/source/common/uarrsort.cpp | 50 +- deps/icu-small/source/common/ubidiimp.h | 82 +- .../source/common/ubiditransform.cpp | 10 +- deps/icu-small/source/common/ucase.cpp | 5 +- deps/icu-small/source/common/uchar.cpp | 2 +- deps/icu-small/source/common/uchriter.cpp | 2 +- deps/icu-small/source/common/ucln_cmn.cpp | 15 +- deps/icu-small/source/common/ucln_cmn.h | 5 +- deps/icu-small/source/common/ucnv.cpp | 24 +- deps/icu-small/source/common/ucnv2022.cpp | 15 +- deps/icu-small/source/common/ucnv_bld.cpp | 27 +- deps/icu-small/source/common/ucnv_lmb.cpp | 12 +- deps/icu-small/source/common/ucnvbocu.cpp | 4 +- deps/icu-small/source/common/ucnvhz.cpp | 18 +- deps/icu-small/source/common/ucnvisci.cpp | 12 +- deps/icu-small/source/common/ucnvsel.cpp | 36 +- deps/icu-small/source/common/ucptrie.cpp | 2 +- deps/icu-small/source/common/ucurr.cpp | 41 +- deps/icu-small/source/common/udata.cpp | 45 +- deps/icu-small/source/common/uhash.cpp | 15 +- deps/icu-small/source/common/uidna.cpp | 7 +- deps/icu-small/source/common/uinvchar.cpp | 15 +- deps/icu-small/source/common/uinvchar.h | 89 +++ deps/icu-small/source/common/uloc.cpp | 53 +- deps/icu-small/source/common/uloc_tag.cpp | 6 +- deps/icu-small/source/common/umutex.cpp | 122 +-- deps/icu-small/source/common/umutex.h | 119 +-- deps/icu-small/source/common/unames.cpp | 4 +- .../source/common/unicode/appendable.h | 5 + .../icu-small/source/common/unicode/brkiter.h | 10 +- .../source/common/unicode/bytestream.h | 5 + .../source/common/unicode/bytestrie.h | 47 ++ .../source/common/unicode/bytestriebuilder.h | 5 + .../icu-small/source/common/unicode/caniter.h | 4 + .../icu-small/source/common/unicode/casemap.h | 5 + .../source/common/unicode/char16ptr.h | 7 +- .../source/common/unicode/chariter.h | 8 +- deps/icu-small/source/common/unicode/dbbi.h | 6 + .../icu-small/source/common/unicode/docmain.h | 4 +- .../icu-small/source/common/unicode/dtintrv.h | 6 +- deps/icu-small/source/common/unicode/edits.h | 7 +- .../source/common/unicode/errorcode.h | 5 + .../source/common/unicode/filteredbrk.h | 7 + deps/icu-small/source/common/unicode/idna.h | 5 + .../source/common/unicode/localebuilder.h | 27 +- .../source/common/unicode/localematcher.h | 605 +++++++++++++++ .../source/common/unicode/locdspnm.h | 4 + deps/icu-small/source/common/unicode/locid.h | 163 +++- .../source/common/unicode/messagepattern.h | 4 + .../source/common/unicode/normalizer2.h | 5 + .../icu-small/source/common/unicode/normlzr.h | 11 +- .../source/common/unicode/parsepos.h | 5 + .../source/common/unicode/platform.h | 74 +- deps/icu-small/source/common/unicode/rbbi.h | 15 +- deps/icu-small/source/common/unicode/rep.h | 9 +- .../icu-small/source/common/unicode/resbund.h | 6 + .../source/common/unicode/schriter.h | 8 +- .../source/common/unicode/simpleformatter.h | 5 + .../source/common/unicode/std_string.h | 4 + .../icu-small/source/common/unicode/strenum.h | 9 +- .../source/common/unicode/stringpiece.h | 35 + .../source/common/unicode/stringtriebuilder.h | 5 + .../source/common/unicode/symtable.h | 5 + deps/icu-small/source/common/unicode/uchar.h | 23 +- .../source/common/unicode/ucharstrie.h | 47 ++ .../source/common/unicode/ucharstriebuilder.h | 5 + .../source/common/unicode/uchriter.h | 8 +- .../icu-small/source/common/unicode/uconfig.h | 2 +- deps/icu-small/source/common/unicode/ucpmap.h | 19 +- .../icu-small/source/common/unicode/ucptrie.h | 116 ++- deps/icu-small/source/common/unicode/ucurr.h | 15 +- deps/icu-small/source/common/unicode/udata.h | 38 +- deps/icu-small/source/common/unicode/uloc.h | 84 +- .../source/common/unicode/umachine.h | 36 + .../source/common/unicode/umutablecptrie.h | 27 +- .../icu-small/source/common/unicode/unifilt.h | 14 + .../source/common/unicode/unifunct.h | 5 + .../source/common/unicode/unimatch.h | 3 + deps/icu-small/source/common/unicode/uniset.h | 15 +- deps/icu-small/source/common/unicode/unistr.h | 46 +- deps/icu-small/source/common/unicode/unorm.h | 4 + .../icu-small/source/common/unicode/uobject.h | 12 +- .../icu-small/source/common/unicode/urename.h | 24 +- .../source/common/unicode/usetiter.h | 5 + deps/icu-small/source/common/unicode/utext.h | 14 +- deps/icu-small/source/common/unicode/utf16.h | 92 +-- deps/icu-small/source/common/unicode/utf8.h | 93 +-- .../icu-small/source/common/unicode/utf_old.h | 205 +++-- deps/icu-small/source/common/unicode/utrace.h | 71 +- deps/icu-small/source/common/unicode/utypes.h | 28 +- .../icu-small/source/common/unicode/uvernum.h | 12 +- .../source/common/unicode/uversion.h | 32 +- deps/icu-small/source/common/unifiedcache.cpp | 51 +- deps/icu-small/source/common/uniset.cpp | 6 +- deps/icu-small/source/common/uniset_props.cpp | 5 +- deps/icu-small/source/common/unisetspan.cpp | 4 +- deps/icu-small/source/common/unistr.cpp | 2 +- deps/icu-small/source/common/uresbund.cpp | 278 ++++--- deps/icu-small/source/common/uresdata.cpp | 96 ++- deps/icu-small/source/common/uresdata.h | 76 +- deps/icu-small/source/common/uresimp.h | 8 + deps/icu-small/source/common/usprep.cpp | 30 +- .../source/common/ustr_titlecase_brkiter.cpp | 14 +- deps/icu-small/source/common/ustring.cpp | 10 +- deps/icu-small/source/common/utext.cpp | 4 +- deps/icu-small/source/common/util.cpp | 10 + deps/icu-small/source/common/util.h | 15 +- deps/icu-small/source/common/utrace.cpp | 12 + deps/icu-small/source/common/utracimp.h | 93 ++- deps/icu-small/source/common/utrie.h | 19 +- deps/icu-small/source/common/utrie2.h | 16 +- .../in/{icudt64l.dat.bz2 => icudt65l.dat.bz2} | Bin 9780309 -> 9881112 bytes deps/icu-small/source/i18n/alphaindex.cpp | 7 +- deps/icu-small/source/i18n/anytrans.cpp | 2 +- deps/icu-small/source/i18n/anytrans.h | 2 +- deps/icu-small/source/i18n/astro.cpp | 17 +- deps/icu-small/source/i18n/bocsu.h | 4 +- deps/icu-small/source/i18n/brktrans.cpp | 2 +- deps/icu-small/source/i18n/brktrans.h | 2 +- deps/icu-small/source/i18n/buddhcal.cpp | 4 +- deps/icu-small/source/i18n/buddhcal.h | 2 +- deps/icu-small/source/i18n/calendar.cpp | 7 +- deps/icu-small/source/i18n/casetrn.cpp | 2 +- deps/icu-small/source/i18n/casetrn.h | 2 +- deps/icu-small/source/i18n/chnsecal.cpp | 19 +- deps/icu-small/source/i18n/chnsecal.h | 2 +- deps/icu-small/source/i18n/choicfmt.cpp | 2 +- deps/icu-small/source/i18n/coll.cpp | 2 +- .../source/i18n/collationiterator.cpp | 4 +- .../source/i18n/compactdecimalformat.cpp | 8 +- deps/icu-small/source/i18n/coptccal.cpp | 2 +- deps/icu-small/source/i18n/coptccal.h | 2 +- deps/icu-small/source/i18n/cpdtrans.cpp | 2 +- deps/icu-small/source/i18n/cpdtrans.h | 2 +- deps/icu-small/source/i18n/csdetect.cpp | 2 +- deps/icu-small/source/i18n/curramt.cpp | 2 +- deps/icu-small/source/i18n/currfmt.cpp | 2 +- deps/icu-small/source/i18n/currfmt.h | 2 +- deps/icu-small/source/i18n/currunit.cpp | 2 +- deps/icu-small/source/i18n/dangical.cpp | 2 +- deps/icu-small/source/i18n/dangical.h | 2 +- deps/icu-small/source/i18n/datefmt.cpp | 4 +- deps/icu-small/source/i18n/decNumberLocal.h | 4 +- deps/icu-small/source/i18n/decimfmt.cpp | 369 +++++---- .../i18n/double-conversion-bignum-dtoa.cpp | 40 +- .../source/i18n/double-conversion-bignum.cpp | 581 +++++++------- .../source/i18n/double-conversion-bignum.h | 68 +- .../i18n/double-conversion-cached-powers.cpp | 204 ++--- .../i18n/double-conversion-cached-powers.h | 26 +- .../source/i18n/double-conversion-diy-fp.cpp | 74 -- .../source/i18n/double-conversion-diy-fp.h | 59 +- .../double-conversion-double-to-string.cpp | 450 +++++++++++ .../i18n/double-conversion-double-to-string.h | 419 ++++++++++ .../i18n/double-conversion-fast-dtoa.cpp | 54 +- .../source/i18n/double-conversion-ieee.h | 38 +- ...=> double-conversion-string-to-double.cpp} | 462 +---------- .../i18n/double-conversion-string-to-double.h | 244 ++++++ .../source/i18n/double-conversion-strtod.cpp | 146 ++-- .../source/i18n/double-conversion-strtod.h | 5 + .../source/i18n/double-conversion-utils.h | 107 ++- .../icu-small/source/i18n/double-conversion.h | 557 +------------- deps/icu-small/source/i18n/dtfmtsym.cpp | 26 +- deps/icu-small/source/i18n/dtitv_impl.h | 2 +- deps/icu-small/source/i18n/dtitvfmt.cpp | 31 +- deps/icu-small/source/i18n/dtitvinf.cpp | 4 +- deps/icu-small/source/i18n/dtptngen.cpp | 76 +- deps/icu-small/source/i18n/esctrn.cpp | 2 +- deps/icu-small/source/i18n/esctrn.h | 2 +- deps/icu-small/source/i18n/ethpccal.cpp | 2 +- deps/icu-small/source/i18n/ethpccal.h | 2 +- deps/icu-small/source/i18n/fmtable.cpp | 2 +- ...ilder.cpp => formatted_string_builder.cpp} | 230 +----- .../source/i18n/formatted_string_builder.h | 253 ++++++ .../icu-small/source/i18n/formattedval_impl.h | 39 +- .../source/i18n/formattedval_sbimpl.cpp | 182 ++++- deps/icu-small/source/i18n/funcrepl.cpp | 2 +- deps/icu-small/source/i18n/funcrepl.h | 2 +- deps/icu-small/source/i18n/gender.cpp | 2 +- deps/icu-small/source/i18n/gregocal.cpp | 32 +- deps/icu-small/source/i18n/hebrwcal.cpp | 2 +- deps/icu-small/source/i18n/hebrwcal.h | 2 +- deps/icu-small/source/i18n/indiancal.cpp | 2 +- deps/icu-small/source/i18n/indiancal.h | 2 +- deps/icu-small/source/i18n/islamcal.cpp | 4 +- deps/icu-small/source/i18n/islamcal.h | 2 +- deps/icu-small/source/i18n/japancal.cpp | 2 +- deps/icu-small/source/i18n/japancal.h | 2 +- deps/icu-small/source/i18n/listformatter.cpp | 6 +- deps/icu-small/source/i18n/measfmt.cpp | 239 +++--- deps/icu-small/source/i18n/measunit.cpp | 576 ++++++++------ deps/icu-small/source/i18n/measure.cpp | 4 +- deps/icu-small/source/i18n/msgfmt.cpp | 6 +- deps/icu-small/source/i18n/name2uni.cpp | 2 +- deps/icu-small/source/i18n/name2uni.h | 2 +- deps/icu-small/source/i18n/nortrans.cpp | 2 +- deps/icu-small/source/i18n/nortrans.h | 2 +- deps/icu-small/source/i18n/nounit.cpp | 2 +- deps/icu-small/source/i18n/nultrans.cpp | 2 +- deps/icu-small/source/i18n/nultrans.h | 2 +- .../source/i18n/number_affixutils.cpp | 8 +- .../icu-small/source/i18n/number_affixutils.h | 10 +- .../icu-small/source/i18n/number_asformat.cpp | 10 +- deps/icu-small/source/i18n/number_asformat.h | 2 +- deps/icu-small/source/i18n/number_compact.cpp | 6 +- .../source/i18n/number_currencysymbols.cpp | 6 +- .../source/i18n/number_decimalquantity.cpp | 21 +- .../source/i18n/number_decimalquantity.h | 11 +- deps/icu-small/source/i18n/number_decnum.h | 2 + deps/icu-small/source/i18n/number_fluent.cpp | 4 +- .../source/i18n/number_formatimpl.cpp | 76 +- .../icu-small/source/i18n/number_formatimpl.h | 24 +- .../source/i18n/number_longnames.cpp | 29 +- deps/icu-small/source/i18n/number_longnames.h | 9 +- deps/icu-small/source/i18n/number_mapper.h | 12 +- .../source/i18n/number_modifiers.cpp | 22 +- deps/icu-small/source/i18n/number_modifiers.h | 56 +- deps/icu-small/source/i18n/number_output.cpp | 13 +- deps/icu-small/source/i18n/number_padding.cpp | 6 +- .../source/i18n/number_patternmodifier.cpp | 38 +- .../source/i18n/number_patternmodifier.h | 16 +- .../source/i18n/number_patternstring.cpp | 7 +- .../source/i18n/number_patternstring.h | 2 +- .../icu-small/source/i18n/number_rounding.cpp | 14 +- .../source/i18n/number_scientific.cpp | 12 +- .../icu-small/source/i18n/number_scientific.h | 2 +- .../source/i18n/number_skeletons.cpp | 11 +- deps/icu-small/source/i18n/number_skeletons.h | 6 +- .../source/i18n/number_stringbuilder.h | 164 ---- deps/icu-small/source/i18n/number_types.h | 28 +- deps/icu-small/source/i18n/number_utils.cpp | 11 + deps/icu-small/source/i18n/number_utils.h | 45 +- deps/icu-small/source/i18n/number_utypes.h | 6 +- deps/icu-small/source/i18n/numfmt.cpp | 30 +- .../source/i18n/numparse_affixes.cpp | 5 +- .../source/i18n/numparse_compositions.cpp | 1 + .../source/i18n/numparse_currency.cpp | 1 + .../source/i18n/numparse_decimal.cpp | 1 + deps/icu-small/source/i18n/numparse_impl.cpp | 6 +- deps/icu-small/source/i18n/numparse_impl.h | 1 + .../source/i18n/numparse_parsednumber.cpp | 5 +- .../source/i18n/numparse_scientific.cpp | 65 +- .../source/i18n/numparse_scientific.h | 2 + .../source/i18n/numparse_stringsegment.h | 24 - .../source/i18n/numparse_symbols.cpp | 9 +- deps/icu-small/source/i18n/numparse_symbols.h | 2 +- deps/icu-small/source/i18n/numparse_types.h | 115 +-- .../icu-small/source/i18n/numrange_fluent.cpp | 4 +- deps/icu-small/source/i18n/numrange_impl.cpp | 2 +- deps/icu-small/source/i18n/numrange_impl.h | 6 +- deps/icu-small/source/i18n/numsys.cpp | 2 +- deps/icu-small/source/i18n/olsontz.cpp | 9 +- deps/icu-small/source/i18n/olsontz.h | 4 +- deps/icu-small/source/i18n/persncal.cpp | 2 +- deps/icu-small/source/i18n/persncal.h | 2 +- deps/icu-small/source/i18n/plurfmt.cpp | 15 +- deps/icu-small/source/i18n/quant.cpp | 2 +- deps/icu-small/source/i18n/quant.h | 2 +- .../source/i18n/quantityformatter.cpp | 10 +- .../icu-small/source/i18n/quantityformatter.h | 11 +- deps/icu-small/source/i18n/rbnf.cpp | 53 +- deps/icu-small/source/i18n/rbt.cpp | 6 +- deps/icu-small/source/i18n/rbt.h | 2 +- deps/icu-small/source/i18n/rbt_pars.cpp | 2 +- deps/icu-small/source/i18n/rbt_rule.cpp | 6 +- deps/icu-small/source/i18n/rbtz.cpp | 6 +- deps/icu-small/source/i18n/regexcmp.cpp | 64 +- deps/icu-small/source/i18n/regeximp.h | 2 +- deps/icu-small/source/i18n/region.cpp | 40 +- deps/icu-small/source/i18n/reldatefmt.cpp | 18 +- deps/icu-small/source/i18n/reldtfmt.cpp | 4 +- deps/icu-small/source/i18n/reldtfmt.h | 2 +- deps/icu-small/source/i18n/rematch.cpp | 144 ++-- deps/icu-small/source/i18n/remtrans.cpp | 6 +- deps/icu-small/source/i18n/remtrans.h | 2 +- deps/icu-small/source/i18n/repattrn.cpp | 4 +- .../source/i18n/rulebasedcollator.cpp | 2 +- .../source/i18n/scientificnumberformatter.cpp | 4 +- deps/icu-small/source/i18n/selfmt.cpp | 2 +- deps/icu-small/source/i18n/simpletz.cpp | 5 +- deps/icu-small/source/i18n/smpdtfmt.cpp | 50 +- ...e_stringsegment.cpp => string_segment.cpp} | 7 +- deps/icu-small/source/i18n/string_segment.h | 134 ++++ deps/icu-small/source/i18n/strmatch.cpp | 2 +- deps/icu-small/source/i18n/strmatch.h | 2 +- deps/icu-small/source/i18n/strrepl.cpp | 2 +- deps/icu-small/source/i18n/strrepl.h | 2 +- deps/icu-small/source/i18n/stsearch.cpp | 2 +- deps/icu-small/source/i18n/taiwncal.cpp | 2 +- deps/icu-small/source/i18n/taiwncal.h | 2 +- deps/icu-small/source/i18n/timezone.cpp | 20 +- deps/icu-small/source/i18n/titletrn.cpp | 2 +- deps/icu-small/source/i18n/titletrn.h | 2 +- deps/icu-small/source/i18n/tmunit.cpp | 2 +- deps/icu-small/source/i18n/tmutamt.cpp | 2 +- deps/icu-small/source/i18n/tmutfmt.cpp | 10 +- deps/icu-small/source/i18n/tolowtrn.cpp | 2 +- deps/icu-small/source/i18n/tolowtrn.h | 2 +- deps/icu-small/source/i18n/toupptrn.cpp | 2 +- deps/icu-small/source/i18n/toupptrn.h | 2 +- deps/icu-small/source/i18n/translit.cpp | 65 +- deps/icu-small/source/i18n/transreg.cpp | 8 +- deps/icu-small/source/i18n/tridpars.cpp | 12 +- deps/icu-small/source/i18n/tzfmt.cpp | 29 +- deps/icu-small/source/i18n/tzgnames.cpp | 52 +- deps/icu-small/source/i18n/tznames.cpp | 19 +- deps/icu-small/source/i18n/tznames_impl.cpp | 39 +- deps/icu-small/source/i18n/tznames_impl.h | 4 +- deps/icu-small/source/i18n/tzrule.cpp | 2 +- deps/icu-small/source/i18n/ucal.cpp | 29 +- deps/icu-small/source/i18n/udat.cpp | 8 +- deps/icu-small/source/i18n/unesctrn.cpp | 2 +- deps/icu-small/source/i18n/unesctrn.h | 2 +- deps/icu-small/source/i18n/uni2name.cpp | 2 +- deps/icu-small/source/i18n/uni2name.h | 2 +- .../source/i18n/unicode/alphaindex.h | 6 + deps/icu-small/source/i18n/unicode/basictz.h | 12 + deps/icu-small/source/i18n/unicode/calendar.h | 27 +- deps/icu-small/source/i18n/unicode/choicfmt.h | 9 +- deps/icu-small/source/i18n/unicode/coleitr.h | 4 + deps/icu-small/source/i18n/unicode/coll.h | 24 +- .../i18n/unicode/compactdecimalformat.h | 7 +- deps/icu-small/source/i18n/unicode/curramt.h | 7 +- deps/icu-small/source/i18n/unicode/currpinf.h | 4 + deps/icu-small/source/i18n/unicode/currunit.h | 7 +- deps/icu-small/source/i18n/unicode/datefmt.h | 12 + deps/icu-small/source/i18n/unicode/dcfmtsym.h | 8 +- deps/icu-small/source/i18n/unicode/decimfmt.h | 31 +- deps/icu-small/source/i18n/unicode/dtfmtsym.h | 4 + deps/icu-small/source/i18n/unicode/dtitvfmt.h | 6 +- deps/icu-small/source/i18n/unicode/dtitvinf.h | 6 +- deps/icu-small/source/i18n/unicode/dtptngen.h | 12 +- deps/icu-small/source/i18n/unicode/dtrule.h | 6 +- deps/icu-small/source/i18n/unicode/fieldpos.h | 4 + deps/icu-small/source/i18n/unicode/fmtable.h | 4 + deps/icu-small/source/i18n/unicode/format.h | 4 + .../source/i18n/unicode/formattedvalue.h | 23 +- deps/icu-small/source/i18n/unicode/fpositer.h | 5 + deps/icu-small/source/i18n/unicode/gender.h | 4 + deps/icu-small/source/i18n/unicode/gregocal.h | 8 +- .../source/i18n/unicode/listformatter.h | 6 +- deps/icu-small/source/i18n/unicode/measfmt.h | 17 +- deps/icu-small/source/i18n/unicode/measunit.h | 229 +++++- deps/icu-small/source/i18n/unicode/measure.h | 7 +- deps/icu-small/source/i18n/unicode/msgfmt.h | 10 +- deps/icu-small/source/i18n/unicode/nounit.h | 9 +- .../source/i18n/unicode/numberformatter.h | 281 ++++--- .../i18n/unicode/numberrangeformatter.h | 135 ++-- deps/icu-small/source/i18n/unicode/numfmt.h | 16 +- deps/icu-small/source/i18n/unicode/numsys.h | 4 + deps/icu-small/source/i18n/unicode/plurfmt.h | 17 +- deps/icu-small/source/i18n/unicode/plurrule.h | 4 + deps/icu-small/source/i18n/unicode/rbnf.h | 28 +- deps/icu-small/source/i18n/unicode/rbtz.h | 8 +- deps/icu-small/source/i18n/unicode/regex.h | 5 + deps/icu-small/source/i18n/unicode/region.h | 7 +- .../source/i18n/unicode/reldatefmt.h | 25 +- .../i18n/unicode/scientificnumberformatter.h | 9 +- deps/icu-small/source/i18n/unicode/search.h | 7 +- deps/icu-small/source/i18n/unicode/selfmt.h | 9 +- deps/icu-small/source/i18n/unicode/simpletz.h | 8 +- deps/icu-small/source/i18n/unicode/smpdtfmt.h | 8 +- deps/icu-small/source/i18n/unicode/sortkey.h | 4 + deps/icu-small/source/i18n/unicode/stsearch.h | 9 +- deps/icu-small/source/i18n/unicode/tblcoll.h | 11 +- deps/icu-small/source/i18n/unicode/timezone.h | 14 +- deps/icu-small/source/i18n/unicode/tmunit.h | 7 +- deps/icu-small/source/i18n/unicode/tmutamt.h | 12 +- deps/icu-small/source/i18n/unicode/tmutfmt.h | 8 +- deps/icu-small/source/i18n/unicode/translit.h | 4 + deps/icu-small/source/i18n/unicode/tzfmt.h | 7 +- deps/icu-small/source/i18n/unicode/tznames.h | 5 + deps/icu-small/source/i18n/unicode/tzrule.h | 12 +- deps/icu-small/source/i18n/unicode/tztrans.h | 6 +- deps/icu-small/source/i18n/unicode/ucal.h | 40 +- deps/icu-small/source/i18n/unicode/ucol.h | 2 + deps/icu-small/source/i18n/unicode/udat.h | 2 + deps/icu-small/source/i18n/unicode/udatpg.h | 2 + .../source/i18n/unicode/uformattedvalue.h | 3 +- .../source/i18n/unicode/ulistformatter.h | 4 +- deps/icu-small/source/i18n/unicode/unirepl.h | 4 + deps/icu-small/source/i18n/unicode/unum.h | 4 +- .../source/i18n/unicode/unumberformatter.h | 71 +- deps/icu-small/source/i18n/unicode/usearch.h | 18 +- deps/icu-small/source/i18n/unicode/uspoof.h | 496 ++++++------ deps/icu-small/source/i18n/unicode/utrans.h | 11 +- deps/icu-small/source/i18n/unicode/vtzone.h | 8 +- deps/icu-small/source/i18n/unum.cpp | 5 + deps/icu-small/source/i18n/usearch.cpp | 28 +- deps/icu-small/source/i18n/uspoof.cpp | 2 +- deps/icu-small/source/i18n/uspoof_impl.cpp | 4 +- deps/icu-small/source/i18n/vtzone.cpp | 14 +- deps/icu-small/source/i18n/windtfmt.cpp | 2 +- deps/icu-small/source/i18n/windtfmt.h | 2 +- deps/icu-small/source/i18n/winnmfmt.cpp | 2 +- deps/icu-small/source/i18n/winnmfmt.h | 2 +- deps/icu-small/source/i18n/zonemeta.cpp | 29 +- .../databuilder/filtration_schema.json | 169 ++++ .../source/tools/genccode/genccode.c | 15 +- deps/icu-small/source/tools/genrb/derb.cpp | 2 +- .../icu-small/source/tools/genrb/filterrb.cpp | 3 + deps/icu-small/source/tools/genrb/genrb.cpp | 8 +- deps/icu-small/source/tools/genrb/parse.cpp | 104 +-- deps/icu-small/source/tools/genrb/reslist.cpp | 2 +- deps/icu-small/source/tools/genrb/rle.c | 4 +- deps/icu-small/source/tools/genrb/ustr.h | 8 +- .../source/tools/pkgdata/pkgdata.cpp | 80 +- .../source/tools/toolutil/filetools.cpp | 2 +- .../source/tools/toolutil/pkg_genc.cpp | 242 ++++-- .../source/tools/toolutil/pkg_genc.h | 25 +- .../source/tools/toolutil/pkgitems.cpp | 3 +- .../source/tools/toolutil/toolutil.cpp | 2 +- deps/icu-small/source/tools/toolutil/ucbuf.h | 4 +- .../source/tools/toolutil/xmlparser.cpp | 2 +- tools/icu/current_ver.dep | 4 +- 453 files changed, 11832 insertions(+), 5897 deletions(-) create mode 100644 deps/icu-small/source/common/localematcher.cpp create mode 100644 deps/icu-small/source/common/localeprioritylist.cpp create mode 100644 deps/icu-small/source/common/localeprioritylist.h create mode 100644 deps/icu-small/source/common/locdistance.cpp create mode 100644 deps/icu-small/source/common/locdistance.h create mode 100644 deps/icu-small/source/common/loclikelysubtags.cpp create mode 100644 deps/icu-small/source/common/loclikelysubtags.h create mode 100644 deps/icu-small/source/common/lsr.cpp create mode 100644 deps/icu-small/source/common/lsr.h create mode 100644 deps/icu-small/source/common/restrace.cpp create mode 100644 deps/icu-small/source/common/restrace.h create mode 100644 deps/icu-small/source/common/unicode/localematcher.h rename deps/icu-small/source/data/in/{icudt64l.dat.bz2 => icudt65l.dat.bz2} (54%) delete mode 100644 deps/icu-small/source/i18n/double-conversion-diy-fp.cpp create mode 100644 deps/icu-small/source/i18n/double-conversion-double-to-string.cpp create mode 100644 deps/icu-small/source/i18n/double-conversion-double-to-string.h rename deps/icu-small/source/i18n/{double-conversion.cpp => double-conversion-string-to-double.cpp} (63%) create mode 100644 deps/icu-small/source/i18n/double-conversion-string-to-double.h rename deps/icu-small/source/i18n/{number_stringbuilder.cpp => formatted_string_builder.cpp} (58%) create mode 100644 deps/icu-small/source/i18n/formatted_string_builder.h delete mode 100644 deps/icu-small/source/i18n/number_stringbuilder.h delete mode 100644 deps/icu-small/source/i18n/numparse_stringsegment.h rename deps/icu-small/source/i18n/{numparse_stringsegment.cpp => string_segment.cpp} (96%) create mode 100644 deps/icu-small/source/i18n/string_segment.h create mode 100644 deps/icu-small/source/python/icutools/databuilder/filtration_schema.json diff --git a/deps/icu-small/README-FULL-ICU.txt b/deps/icu-small/README-FULL-ICU.txt index d954e58a5fa0e3..99a75bed1defdd 100644 --- a/deps/icu-small/README-FULL-ICU.txt +++ b/deps/icu-small/README-FULL-ICU.txt @@ -1,8 +1,8 @@ ICU sources - auto generated by shrink-icu-src.py This directory contains the ICU subset used by --with-intl=full-icu -It is a strict subset of ICU 64 source files with the following exception(s): -* deps/icu-small/source/data/in/icudt64l.dat.bz2 : compressed data file +It is a strict subset of ICU 65 source files with the following exception(s): +* deps/icu-small/source/data/in/icudt65l.dat.bz2 : compressed data file To rebuild this directory, see ../../tools/icu/README.md diff --git a/deps/icu-small/source/common/brkeng.cpp b/deps/icu-small/source/common/brkeng.cpp index 42771b3617747d..68c74f2359c4a1 100644 --- a/deps/icu-small/source/common/brkeng.cpp +++ b/deps/icu-small/source/common/brkeng.cpp @@ -129,7 +129,7 @@ ICULanguageBreakFactory::getEngineFor(UChar32 c) { const LanguageBreakEngine *lbe = NULL; UErrorCode status = U_ZERO_ERROR; - static UMutex gBreakEngineMutex = U_MUTEX_INITIALIZER; + static UMutex gBreakEngineMutex; Mutex m(&gBreakEngineMutex); if (fEngines == NULL) { diff --git a/deps/icu-small/source/common/brkiter.cpp b/deps/icu-small/source/common/brkiter.cpp index 23e0cc3c153392..2fc4c345c7a038 100644 --- a/deps/icu-small/source/common/brkiter.cpp +++ b/deps/icu-small/source/common/brkiter.cpp @@ -277,7 +277,7 @@ ICUBreakIteratorService::~ICUBreakIteratorService() {} // defined in ucln_cmn.h U_NAMESPACE_END -static icu::UInitOnce gInitOnceBrkiter; +static icu::UInitOnce gInitOnceBrkiter = U_INITONCE_INITIALIZER; static icu::ICULocaleService* gService = NULL; diff --git a/deps/icu-small/source/common/bytesinkutil.h b/deps/icu-small/source/common/bytesinkutil.h index 69e4cbcd263932..6808fbe6777837 100644 --- a/deps/icu-small/source/common/bytesinkutil.h +++ b/deps/icu-small/source/common/bytesinkutil.h @@ -59,7 +59,7 @@ class U_COMMON_API ByteSinkUtil { ByteSink &sink, uint32_t options, Edits *edits); }; -class CharStringByteSink : public ByteSink { +class U_COMMON_API CharStringByteSink : public ByteSink { public: CharStringByteSink(CharString* dest); ~CharStringByteSink() override; diff --git a/deps/icu-small/source/common/characterproperties.cpp b/deps/icu-small/source/common/characterproperties.cpp index 5a57364375b372..7b50a4e2051b97 100644 --- a/deps/icu-small/source/common/characterproperties.cpp +++ b/deps/icu-small/source/common/characterproperties.cpp @@ -38,8 +38,8 @@ UBool U_CALLCONV characterproperties_cleanup(); constexpr int32_t NUM_INCLUSIONS = UPROPS_SRC_COUNT + UCHAR_INT_LIMIT - UCHAR_INT_START; struct Inclusion { - UnicodeSet *fSet; - UInitOnce fInitOnce; + UnicodeSet *fSet = nullptr; + UInitOnce fInitOnce = U_INITONCE_INITIALIZER; }; Inclusion gInclusions[NUM_INCLUSIONS]; // cached getInclusions() @@ -47,10 +47,7 @@ UnicodeSet *sets[UCHAR_BINARY_LIMIT] = {}; UCPMap *maps[UCHAR_INT_LIMIT - UCHAR_INT_START] = {}; -icu::UMutex *cpMutex() { - static icu::UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +icu::UMutex cpMutex; //---------------------------------------------------------------- // Inclusions list @@ -361,7 +358,7 @@ u_getBinaryPropertySet(UProperty property, UErrorCode *pErrorCode) { *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; return nullptr; } - Mutex m(cpMutex()); + Mutex m(&cpMutex); UnicodeSet *set = sets[property]; if (set == nullptr) { sets[property] = set = makeSet(property, *pErrorCode); @@ -377,7 +374,7 @@ u_getIntPropertyMap(UProperty property, UErrorCode *pErrorCode) { *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; return nullptr; } - Mutex m(cpMutex()); + Mutex m(&cpMutex); UCPMap *map = maps[property - UCHAR_INT_START]; if (map == nullptr) { maps[property - UCHAR_INT_START] = map = makeMap(property, *pErrorCode); diff --git a/deps/icu-small/source/common/charstr.cpp b/deps/icu-small/source/common/charstr.cpp index 852cc539457760..dda29dac63273c 100644 --- a/deps/icu-small/source/common/charstr.cpp +++ b/deps/icu-small/source/common/charstr.cpp @@ -35,6 +35,17 @@ CharString& CharString::operator=(CharString&& src) U_NOEXCEPT { return *this; } +char *CharString::cloneData(UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return nullptr; } + char *p = static_cast(uprv_malloc(len + 1)); + if (p == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + uprv_memcpy(p, buffer.getAlias(), len + 1); + return p; +} + CharString &CharString::copyFrom(const CharString &s, UErrorCode &errorCode) { if(U_SUCCESS(errorCode) && this!=&s && ensureCapacity(s.len+1, 0, errorCode)) { len=s.len; @@ -52,6 +63,18 @@ int32_t CharString::lastIndexOf(char c) const { return -1; } +bool CharString::contains(StringPiece s) const { + if (s.empty()) { return false; } + const char *p = buffer.getAlias(); + int32_t lastStart = len - s.length(); + for (int32_t i = 0; i <= lastStart; ++i) { + if (uprv_memcmp(p + i, s.data(), s.length()) == 0) { + return true; + } + } + return false; +} + CharString &CharString::truncate(int32_t newLength) { if(newLength<0) { newLength=0; diff --git a/deps/icu-small/source/common/charstr.h b/deps/icu-small/source/common/charstr.h index 1a97e01988f991..23b950ed6ecc76 100644 --- a/deps/icu-small/source/common/charstr.h +++ b/deps/icu-small/source/common/charstr.h @@ -82,10 +82,24 @@ class U_COMMON_API CharString : public UMemory { const char *data() const { return buffer.getAlias(); } char *data() { return buffer.getAlias(); } + /** + * Allocates length()+1 chars and copies the NUL-terminated data(). + * The caller must uprv_free() the result. + */ + char *cloneData(UErrorCode &errorCode) const; + + bool operator==(StringPiece other) const { + return len == other.length() && (len == 0 || uprv_memcmp(data(), other.data(), len) == 0); + } + bool operator!=(StringPiece other) const { + return !operator==(other); + } /** @return last index of c, or -1 if c is not in this string */ int32_t lastIndexOf(char c) const; + bool contains(StringPiece s) const; + CharString &clear() { len=0; buffer[0]=0; return *this; } CharString &truncate(int32_t newLength); diff --git a/deps/icu-small/source/common/cmemory.h b/deps/icu-small/source/common/cmemory.h index f501b20a14ca13..b24bd0ead2761c 100644 --- a/deps/icu-small/source/common/cmemory.h +++ b/deps/icu-small/source/common/cmemory.h @@ -64,38 +64,37 @@ uprv_free(void *mem); U_CAPI void * U_EXPORT2 uprv_calloc(size_t num, size_t size) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR2(1,2); -/** - * This should align the memory properly on any machine. - * This is very useful for the safeClone functions. - */ -typedef union { - long t1; - double t2; - void *t3; -} UAlignedMemory; - /** * Get the least significant bits of a pointer (a memory address). * For example, with a mask of 3, the macro gets the 2 least significant bits, * which will be 0 if the pointer is 32-bit (4-byte) aligned. * - * ptrdiff_t is the most appropriate integer type to cast to. - * size_t should work too, since on most (or all?) platforms it has the same - * width as ptrdiff_t. + * uintptr_t is the most appropriate integer type to cast to. */ -#define U_POINTER_MASK_LSB(ptr, mask) (((ptrdiff_t)(char *)(ptr)) & (mask)) +#define U_POINTER_MASK_LSB(ptr, mask) ((uintptr_t)(ptr) & (mask)) /** - * Get the amount of bytes that a pointer is off by from - * the previous UAlignedMemory-aligned pointer. - */ -#define U_ALIGNMENT_OFFSET(ptr) U_POINTER_MASK_LSB(ptr, sizeof(UAlignedMemory) - 1) - -/** - * Get the amount of bytes to add to a pointer - * in order to get the next UAlignedMemory-aligned address. + * Create & return an instance of "type" in statically allocated storage. + * e.g. + * static std::mutex *myMutex = STATIC_NEW(std::mutex); + * To destroy an object created in this way, invoke the destructor explicitly, e.g. + * myMutex->~mutex(); + * DO NOT use delete. + * DO NOT use with class UMutex, which has specific support for static instances. + * + * STATIC_NEW is intended for use when + * - We want a static (or global) object. + * - We don't want it to ever be destructed, or to explicitly control destruction, + * to avoid use-after-destruction problems. + * - We want to avoid an ordinary heap allocated object, + * to avoid the possibility of memory allocation failures, and + * to avoid memory leak reports, from valgrind, for example. + * This is defined as a macro rather than a template function because each invocation + * must define distinct static storage for the object being returned. */ -#define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr)) +#define STATIC_NEW(type) [] () { \ + alignas(type) static char storage[sizeof(type)]; \ + return new(storage) type();} () /** * Heap clean up function, called from u_cleanup() diff --git a/deps/icu-small/source/common/edits.cpp b/deps/icu-small/source/common/edits.cpp index 00a8d601a1cc80..95f0c19a728cf4 100644 --- a/deps/icu-small/source/common/edits.cpp +++ b/deps/icu-small/source/common/edits.cpp @@ -243,7 +243,7 @@ UBool Edits::growArray() { return TRUE; } -UBool Edits::copyErrorTo(UErrorCode &outErrorCode) { +UBool Edits::copyErrorTo(UErrorCode &outErrorCode) const { if (U_FAILURE(outErrorCode)) { return TRUE; } if (U_SUCCESS(errorCode_)) { return FALSE; } outErrorCode = errorCode_; diff --git a/deps/icu-small/source/common/filteredbrk.cpp b/deps/icu-small/source/common/filteredbrk.cpp index 162b38de5d6fa2..ae7cf5270aeabf 100644 --- a/deps/icu-small/source/common/filteredbrk.cpp +++ b/deps/icu-small/source/common/filteredbrk.cpp @@ -173,7 +173,7 @@ class SimpleFilteredSentenceBreakIterator : public BreakIterator { status = U_SAFECLONE_ALLOCATED_WARNING; return clone(); } - virtual BreakIterator* clone(void) const { return new SimpleFilteredSentenceBreakIterator(*this); } + virtual SimpleFilteredSentenceBreakIterator* clone() const { return new SimpleFilteredSentenceBreakIterator(*this); } virtual UClassID getDynamicClassID(void) const { return NULL; } virtual UBool operator==(const BreakIterator& o) const { if(this==&o) return true; return false; } diff --git a/deps/icu-small/source/common/localebuilder.cpp b/deps/icu-small/source/common/localebuilder.cpp index fe931fcf759dfd..1dd8131e5895a5 100644 --- a/deps/icu-small/source/common/localebuilder.cpp +++ b/deps/icu-small/source/common/localebuilder.cpp @@ -157,13 +157,18 @@ _isKeywordValue(const char* key, const char* value, int32_t value_len) } static void -_copyExtensions(const Locale& from, Locale* to, bool validate, UErrorCode& errorCode) +_copyExtensions(const Locale& from, icu::StringEnumeration *keywords, + Locale& to, bool validate, UErrorCode& errorCode) { if (U_FAILURE(errorCode)) { return; } - LocalPointer iter(from.createKeywords(errorCode)); - if (U_FAILURE(errorCode) || iter.isNull()) { return; } + LocalPointer ownedKeywords; + if (keywords == nullptr) { + ownedKeywords.adoptInstead(from.createKeywords(errorCode)); + if (U_FAILURE(errorCode) || ownedKeywords.isNull()) { return; } + keywords = ownedKeywords.getAlias(); + } const char* key; - while ((key = iter->next(nullptr, errorCode)) != nullptr) { + while ((key = keywords->next(nullptr, errorCode)) != nullptr) { CharString value; CharStringByteSink sink(&value); from.getKeywordValue(key, sink, errorCode); @@ -176,34 +181,34 @@ _copyExtensions(const Locale& from, Locale* to, bool validate, UErrorCode& error errorCode = U_ILLEGAL_ARGUMENT_ERROR; return; } - to->setKeywordValue(key, value.data(), errorCode); + to.setKeywordValue(key, value.data(), errorCode); if (U_FAILURE(errorCode)) { return; } } } void static -_clearUAttributesAndKeyType(Locale* locale, UErrorCode& errorCode) +_clearUAttributesAndKeyType(Locale& locale, UErrorCode& errorCode) { // Clear Unicode attributes - locale->setKeywordValue(kAttributeKey, "", errorCode); + locale.setKeywordValue(kAttributeKey, "", errorCode); // Clear all Unicode keyword values - LocalPointer iter(locale->createUnicodeKeywords(errorCode)); + LocalPointer iter(locale.createUnicodeKeywords(errorCode)); if (U_FAILURE(errorCode) || iter.isNull()) { return; } const char* key; while ((key = iter->next(nullptr, errorCode)) != nullptr) { - locale->setUnicodeKeywordValue(key, nullptr, errorCode); + locale.setUnicodeKeywordValue(key, nullptr, errorCode); } } static void -_setUnicodeExtensions(Locale* locale, const CharString& value, UErrorCode& errorCode) +_setUnicodeExtensions(Locale& locale, const CharString& value, UErrorCode& errorCode) { // Add the unicode extensions to extensions_ CharString locale_str("und-u-", errorCode); locale_str.append(value, errorCode); _copyExtensions( - Locale::forLanguageTag(locale_str.data(), errorCode), + Locale::forLanguageTag(locale_str.data(), errorCode), nullptr, locale, false, errorCode); } @@ -235,10 +240,10 @@ LocaleBuilder& LocaleBuilder::setExtension(char key, StringPiece value) status_); return *this; } - _clearUAttributesAndKeyType(extensions_, status_); + _clearUAttributesAndKeyType(*extensions_, status_); if (U_FAILURE(status_)) { return *this; } if (!value.empty()) { - _setUnicodeExtensions(extensions_, value_str, status_); + _setUnicodeExtensions(*extensions_, value_str, status_); } return *this; } @@ -401,6 +406,24 @@ Locale makeBogusLocale() { return bogus; } +void LocaleBuilder::copyExtensionsFrom(const Locale& src, UErrorCode& errorCode) +{ + if (U_FAILURE(errorCode)) { return; } + LocalPointer keywords(src.createKeywords(errorCode)); + if (U_FAILURE(errorCode) || keywords.isNull() || keywords->count(errorCode) == 0) { + // Error, or no extensions to copy. + return; + } + if (extensions_ == nullptr) { + extensions_ = new Locale(); + if (extensions_ == nullptr) { + status_ = U_MEMORY_ALLOCATION_ERROR; + return; + } + } + _copyExtensions(src, keywords.getAlias(), *extensions_, false, errorCode); +} + Locale LocaleBuilder::build(UErrorCode& errorCode) { if (U_FAILURE(errorCode)) { @@ -425,7 +448,7 @@ Locale LocaleBuilder::build(UErrorCode& errorCode) } Locale product(locale_str.data()); if (extensions_ != nullptr) { - _copyExtensions(*extensions_, &product, true, errorCode); + _copyExtensions(*extensions_, nullptr, product, true, errorCode); } if (U_FAILURE(errorCode)) { return makeBogusLocale(); @@ -433,4 +456,13 @@ Locale LocaleBuilder::build(UErrorCode& errorCode) return product; } +UBool LocaleBuilder::copyErrorTo(UErrorCode &outErrorCode) const { + if (U_FAILURE(outErrorCode)) { + // Do not overwrite the older error code + return TRUE; + } + outErrorCode = status_; + return U_FAILURE(outErrorCode); +} + U_NAMESPACE_END diff --git a/deps/icu-small/source/common/localematcher.cpp b/deps/icu-small/source/common/localematcher.cpp new file mode 100644 index 00000000000000..d975fe759b4ce1 --- /dev/null +++ b/deps/icu-small/source/common/localematcher.cpp @@ -0,0 +1,720 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// localematcher.cpp +// created: 2019may08 Markus W. Scherer + +#ifndef __LOCMATCHER_H__ +#define __LOCMATCHER_H__ + +#include "unicode/utypes.h" +#include "unicode/localebuilder.h" +#include "unicode/localematcher.h" +#include "unicode/locid.h" +#include "unicode/stringpiece.h" +#include "unicode/uobject.h" +#include "cstring.h" +#include "localeprioritylist.h" +#include "loclikelysubtags.h" +#include "locdistance.h" +#include "lsr.h" +#include "uassert.h" +#include "uhash.h" +#include "uvector.h" + +#define UND_LSR LSR("und", "", "") + +/** + * Indicator for the lifetime of desired-locale objects passed into the LocaleMatcher. + * + * @draft ICU 65 + */ +enum ULocMatchLifetime { + /** + * Locale objects are temporary. + * The matcher will make a copy of a locale that will be used beyond one function call. + * + * @draft ICU 65 + */ + ULOCMATCH_TEMPORARY_LOCALES, + /** + * Locale objects are stored at least as long as the matcher is used. + * The matcher will keep only a pointer to a locale that will be used beyond one function call, + * avoiding a copy. + * + * @draft ICU 65 + */ + ULOCMATCH_STORED_LOCALES // TODO: permanent? cached? clone? +}; +#ifndef U_IN_DOXYGEN +typedef enum ULocMatchLifetime ULocMatchLifetime; +#endif + +U_NAMESPACE_BEGIN + +LocaleMatcher::Result::Result(LocaleMatcher::Result &&src) U_NOEXCEPT : + desiredLocale(src.desiredLocale), + supportedLocale(src.supportedLocale), + desiredIndex(src.desiredIndex), + supportedIndex(src.supportedIndex), + desiredIsOwned(src.desiredIsOwned) { + if (desiredIsOwned) { + src.desiredLocale = nullptr; + src.desiredIndex = -1; + src.desiredIsOwned = FALSE; + } +} + +LocaleMatcher::Result::~Result() { + if (desiredIsOwned) { + delete desiredLocale; + } +} + +LocaleMatcher::Result &LocaleMatcher::Result::operator=(LocaleMatcher::Result &&src) U_NOEXCEPT { + this->~Result(); + + desiredLocale = src.desiredLocale; + supportedLocale = src.supportedLocale; + desiredIndex = src.desiredIndex; + supportedIndex = src.supportedIndex; + desiredIsOwned = src.desiredIsOwned; + + if (desiredIsOwned) { + src.desiredLocale = nullptr; + src.desiredIndex = -1; + src.desiredIsOwned = FALSE; + } + return *this; +} + +Locale LocaleMatcher::Result::makeResolvedLocale(UErrorCode &errorCode) const { + if (U_FAILURE(errorCode) || supportedLocale == nullptr) { + return Locale::getRoot(); + } + const Locale *bestDesired = getDesiredLocale(); + if (bestDesired == nullptr || *supportedLocale == *bestDesired) { + return *supportedLocale; + } + LocaleBuilder b; + b.setLocale(*supportedLocale); + + // Copy the region from bestDesired, if there is one. + const char *region = bestDesired->getCountry(); + if (*region != 0) { + b.setRegion(region); + } + + // Copy the variants from bestDesired, if there are any. + // Note that this will override any supportedLocale variants. + // For example, "sco-ulster-fonipa" + "...-fonupa" => "sco-fonupa" (replacing ulster). + const char *variants = bestDesired->getVariant(); + if (*variants != 0) { + b.setVariant(variants); + } + + // Copy the extensions from bestDesired, if there are any. + // C++ note: The following note, copied from Java, may not be true, + // as long as C++ copies by legacy ICU keyword, not by extension singleton. + // Note that this will override any supportedLocale extensions. + // For example, "th-u-nu-latn-ca-buddhist" + "...-u-nu-native" => "th-u-nu-native" + // (replacing calendar). + b.copyExtensionsFrom(*bestDesired, errorCode); + return b.build(errorCode); +} + +LocaleMatcher::Builder::Builder(LocaleMatcher::Builder &&src) U_NOEXCEPT : + errorCode_(src.errorCode_), + supportedLocales_(src.supportedLocales_), + thresholdDistance_(src.thresholdDistance_), + demotion_(src.demotion_), + defaultLocale_(src.defaultLocale_), + favor_(src.favor_) { + src.supportedLocales_ = nullptr; + src.defaultLocale_ = nullptr; +} + +LocaleMatcher::Builder::~Builder() { + delete supportedLocales_; + delete defaultLocale_; +} + +LocaleMatcher::Builder &LocaleMatcher::Builder::operator=(LocaleMatcher::Builder &&src) U_NOEXCEPT { + this->~Builder(); + + errorCode_ = src.errorCode_; + supportedLocales_ = src.supportedLocales_; + thresholdDistance_ = src.thresholdDistance_; + demotion_ = src.demotion_; + defaultLocale_ = src.defaultLocale_; + favor_ = src.favor_; + + src.supportedLocales_ = nullptr; + src.defaultLocale_ = nullptr; + return *this; +} + +void LocaleMatcher::Builder::clearSupportedLocales() { + if (supportedLocales_ != nullptr) { + supportedLocales_->removeAllElements(); + } +} + +bool LocaleMatcher::Builder::ensureSupportedLocaleVector() { + if (U_FAILURE(errorCode_)) { return false; } + if (supportedLocales_ != nullptr) { return true; } + supportedLocales_ = new UVector(uprv_deleteUObject, nullptr, errorCode_); + if (U_FAILURE(errorCode_)) { return false; } + if (supportedLocales_ == nullptr) { + errorCode_ = U_MEMORY_ALLOCATION_ERROR; + return false; + } + return true; +} + +LocaleMatcher::Builder &LocaleMatcher::Builder::setSupportedLocalesFromListString( + StringPiece locales) { + LocalePriorityList list(locales, errorCode_); + if (U_FAILURE(errorCode_)) { return *this; } + clearSupportedLocales(); + if (!ensureSupportedLocaleVector()) { return *this; } + int32_t length = list.getLengthIncludingRemoved(); + for (int32_t i = 0; i < length; ++i) { + Locale *locale = list.orphanLocaleAt(i); + if (locale == nullptr) { continue; } + supportedLocales_->addElement(locale, errorCode_); + if (U_FAILURE(errorCode_)) { + delete locale; + break; + } + } + return *this; +} + +LocaleMatcher::Builder &LocaleMatcher::Builder::setSupportedLocales(Locale::Iterator &locales) { + if (U_FAILURE(errorCode_)) { return *this; } + clearSupportedLocales(); + if (!ensureSupportedLocaleVector()) { return *this; } + while (locales.hasNext()) { + const Locale &locale = locales.next(); + Locale *clone = locale.clone(); + if (clone == nullptr) { + errorCode_ = U_MEMORY_ALLOCATION_ERROR; + break; + } + supportedLocales_->addElement(clone, errorCode_); + if (U_FAILURE(errorCode_)) { + delete clone; + break; + } + } + return *this; +} + +LocaleMatcher::Builder &LocaleMatcher::Builder::addSupportedLocale(const Locale &locale) { + if (!ensureSupportedLocaleVector()) { return *this; } + Locale *clone = locale.clone(); + if (clone == nullptr) { + errorCode_ = U_MEMORY_ALLOCATION_ERROR; + return *this; + } + supportedLocales_->addElement(clone, errorCode_); + if (U_FAILURE(errorCode_)) { + delete clone; + } + return *this; +} + +LocaleMatcher::Builder &LocaleMatcher::Builder::setDefaultLocale(const Locale *defaultLocale) { + if (U_FAILURE(errorCode_)) { return *this; } + Locale *clone = nullptr; + if (defaultLocale != nullptr) { + clone = defaultLocale->clone(); + if (clone == nullptr) { + errorCode_ = U_MEMORY_ALLOCATION_ERROR; + return *this; + } + } + delete defaultLocale_; + defaultLocale_ = clone; + return *this; +} + +LocaleMatcher::Builder &LocaleMatcher::Builder::setFavorSubtag(ULocMatchFavorSubtag subtag) { + if (U_FAILURE(errorCode_)) { return *this; } + favor_ = subtag; + return *this; +} + +LocaleMatcher::Builder &LocaleMatcher::Builder::setDemotionPerDesiredLocale(ULocMatchDemotion demotion) { + if (U_FAILURE(errorCode_)) { return *this; } + demotion_ = demotion; + return *this; +} + +#if 0 +/** + * Internal only! + * + * @param thresholdDistance the thresholdDistance to set, with -1 = default + * @return this Builder object + * @internal + * @deprecated This API is ICU internal only. + */ +@Deprecated +LocaleMatcher::Builder &LocaleMatcher::Builder::internalSetThresholdDistance(int32_t thresholdDistance) { + if (U_FAILURE(errorCode_)) { return *this; } + if (thresholdDistance > 100) { + thresholdDistance = 100; + } + thresholdDistance_ = thresholdDistance; + return *this; +} +#endif + +UBool LocaleMatcher::Builder::copyErrorTo(UErrorCode &outErrorCode) const { + if (U_FAILURE(outErrorCode)) { return TRUE; } + if (U_SUCCESS(errorCode_)) { return FALSE; } + outErrorCode = errorCode_; + return TRUE; +} + +LocaleMatcher LocaleMatcher::Builder::build(UErrorCode &errorCode) const { + if (U_SUCCESS(errorCode) && U_FAILURE(errorCode_)) { + errorCode = errorCode_; + } + return LocaleMatcher(*this, errorCode); +} + +namespace { + +LSR getMaximalLsrOrUnd(const XLikelySubtags &likelySubtags, const Locale &locale, + UErrorCode &errorCode) { + if (U_FAILURE(errorCode) || locale.isBogus() || *locale.getName() == 0 /* "und" */) { + return UND_LSR; + } else { + return likelySubtags.makeMaximizedLsrFrom(locale, errorCode); + } +} + +int32_t hashLSR(const UHashTok token) { + const LSR *lsr = static_cast(token.pointer); + return lsr->hashCode; +} + +UBool compareLSRs(const UHashTok t1, const UHashTok t2) { + const LSR *lsr1 = static_cast(t1.pointer); + const LSR *lsr2 = static_cast(t2.pointer); + 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 + +LocaleMatcher::LocaleMatcher(const Builder &builder, UErrorCode &errorCode) : + likelySubtags(*XLikelySubtags::getSingleton(errorCode)), + localeDistance(*LocaleDistance::getSingleton(errorCode)), + thresholdDistance(builder.thresholdDistance_), + demotionPerDesiredLocale(0), + favorSubtag(builder.favor_), + supportedLocales(nullptr), lsrs(nullptr), supportedLocalesLength(0), + supportedLsrToIndex(nullptr), + supportedLSRs(nullptr), supportedIndexes(nullptr), supportedLSRsLength(0), + ownedDefaultLocale(nullptr), defaultLocale(nullptr), defaultLocaleIndex(-1) { + if (U_FAILURE(errorCode)) { return; } + if (thresholdDistance < 0) { + thresholdDistance = localeDistance.getDefaultScriptDistance(); + } + 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) + // we can return those by parallel index. + supportedLocales = static_cast( + uprv_malloc(supportedLocalesLength * sizeof(const Locale *))); + // Supported LRSs in input order. + // In C++, we store these permanently to simplify ownership management + // in the hash tables. Duplicate LSRs (if any) are unused overhead. + lsrs = new LSR[supportedLocalesLength]; + if (supportedLocales == nullptr || lsrs == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + // 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(); + if (supportedLocales[i] == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + const Locale &supportedLocale = *supportedLocales[i]; + 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: + // 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 *))); + supportedIndexes = static_cast( + uprv_malloc(suppLSRsCapacity * 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; + } + 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. + } 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; + } + } + } + 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)); + } + supportedLSRsLength = otherIndex - (paradigmLimit - paradigmIndex); + } + + if (def != nullptr && (idef < 0 || def != supportedLocales[idef])) { + ownedDefaultLocale = def->clone(); + if (ownedDefaultLocale == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + def = ownedDefaultLocale; + } + defaultLocale = def; + defaultLocaleIndex = idef; + + if (builder.demotion_ == ULOCMATCH_DEMOTION_REGION) { + demotionPerDesiredLocale = localeDistance.getDefaultDemotionPerDesiredLocale(); + } +} + +LocaleMatcher::LocaleMatcher(LocaleMatcher &&src) U_NOEXCEPT : + likelySubtags(src.likelySubtags), + localeDistance(src.localeDistance), + thresholdDistance(src.thresholdDistance), + demotionPerDesiredLocale(src.demotionPerDesiredLocale), + favorSubtag(src.favorSubtag), + 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) { + src.supportedLocales = nullptr; + src.lsrs = nullptr; + src.supportedLocalesLength = 0; + src.supportedLsrToIndex = nullptr; + src.supportedLSRs = nullptr; + src.supportedIndexes = nullptr; + src.supportedLSRsLength = 0; + src.ownedDefaultLocale = nullptr; + src.defaultLocale = nullptr; + src.defaultLocaleIndex = -1; +} + +LocaleMatcher::~LocaleMatcher() { + for (int32_t i = 0; i < supportedLocalesLength; ++i) { + delete supportedLocales[i]; + } + uprv_free(supportedLocales); + delete[] lsrs; + uhash_close(supportedLsrToIndex); + uprv_free(supportedLSRs); + uprv_free(supportedIndexes); + delete ownedDefaultLocale; +} + +LocaleMatcher &LocaleMatcher::operator=(LocaleMatcher &&src) U_NOEXCEPT { + this->~LocaleMatcher(); + + thresholdDistance = src.thresholdDistance; + demotionPerDesiredLocale = src.demotionPerDesiredLocale; + favorSubtag = src.favorSubtag; + 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; + + src.supportedLocales = nullptr; + src.lsrs = nullptr; + src.supportedLocalesLength = 0; + src.supportedLsrToIndex = nullptr; + src.supportedLSRs = nullptr; + src.supportedIndexes = nullptr; + src.supportedLSRsLength = 0; + src.ownedDefaultLocale = nullptr; + src.defaultLocale = nullptr; + src.defaultLocaleIndex = -1; + return *this; +} + +class LocaleLsrIterator { +public: + LocaleLsrIterator(const XLikelySubtags &likelySubtags, Locale::Iterator &locales, + ULocMatchLifetime lifetime) : + likelySubtags(likelySubtags), locales(locales), lifetime(lifetime) {} + + ~LocaleLsrIterator() { + if (lifetime == ULOCMATCH_TEMPORARY_LOCALES) { + delete remembered; + } + } + + bool hasNext() const { + return locales.hasNext(); + } + + LSR next(UErrorCode &errorCode) { + current = &locales.next(); + return getMaximalLsrOrUnd(likelySubtags, *current, errorCode); + } + + void rememberCurrent(int32_t desiredIndex, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return; } + bestDesiredIndex = desiredIndex; + if (lifetime == ULOCMATCH_STORED_LOCALES) { + remembered = current; + } else { + // ULOCMATCH_TEMPORARY_LOCALES + delete remembered; + remembered = new Locale(*current); + if (remembered == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + } + } + } + + const Locale *orphanRemembered() { + const Locale *rem = remembered; + remembered = nullptr; + return rem; + } + + int32_t getBestDesiredIndex() const { + return bestDesiredIndex; + } + +private: + const XLikelySubtags &likelySubtags; + Locale::Iterator &locales; + ULocMatchLifetime lifetime; + const Locale *current = nullptr, *remembered = nullptr; + int32_t bestDesiredIndex = -1; +}; + +const Locale *LocaleMatcher::getBestMatch(const Locale &desiredLocale, UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return nullptr; } + int32_t suppIndex = getBestSuppIndex( + getMaximalLsrOrUnd(likelySubtags, desiredLocale, errorCode), + nullptr, errorCode); + return U_SUCCESS(errorCode) && suppIndex >= 0 ? supportedLocales[suppIndex] : defaultLocale; +} + +const Locale *LocaleMatcher::getBestMatch(Locale::Iterator &desiredLocales, + UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return nullptr; } + if (!desiredLocales.hasNext()) { + return defaultLocale; + } + LocaleLsrIterator lsrIter(likelySubtags, desiredLocales, ULOCMATCH_TEMPORARY_LOCALES); + int32_t suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode); + return U_SUCCESS(errorCode) && suppIndex >= 0 ? supportedLocales[suppIndex] : defaultLocale; +} + +const Locale *LocaleMatcher::getBestMatchForListString( + StringPiece desiredLocaleList, UErrorCode &errorCode) const { + LocalePriorityList list(desiredLocaleList, errorCode); + LocalePriorityList::Iterator iter = list.iterator(); + return getBestMatch(iter, errorCode); +} + +LocaleMatcher::Result LocaleMatcher::getBestMatchResult( + const Locale &desiredLocale, UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { + return Result(nullptr, defaultLocale, -1, defaultLocaleIndex, FALSE); + } + int32_t suppIndex = getBestSuppIndex( + getMaximalLsrOrUnd(likelySubtags, desiredLocale, errorCode), + nullptr, errorCode); + if (U_FAILURE(errorCode) || suppIndex < 0) { + return Result(nullptr, defaultLocale, -1, defaultLocaleIndex, FALSE); + } else { + return Result(&desiredLocale, supportedLocales[suppIndex], 0, suppIndex, FALSE); + } +} + +LocaleMatcher::Result LocaleMatcher::getBestMatchResult( + Locale::Iterator &desiredLocales, UErrorCode &errorCode) const { + if (U_FAILURE(errorCode) || !desiredLocales.hasNext()) { + return Result(nullptr, defaultLocale, -1, defaultLocaleIndex, 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); + } else { + return Result(lsrIter.orphanRemembered(), supportedLocales[suppIndex], + lsrIter.getBestDesiredIndex(), suppIndex, TRUE); + } +} + +int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, + UErrorCode &errorCode) const { + if (U_FAILURE(errorCode)) { return -1; } + int32_t desiredIndex = 0; + int32_t bestSupportedLsrIndex = -1; + for (int32_t bestDistance = thresholdDistance;;) { + // Quick check for exact maximized LSR. + // Returns suppIndex+1 where 0 means not found. + if (supportedLsrToIndex != nullptr) { + desiredLSR.setHashCode(); + int32_t index = uhash_geti(supportedLsrToIndex, &desiredLSR); + if (index != 0) { + int32_t suppIndex = index - 1; + if (remainingIter != nullptr) { + remainingIter->rememberCurrent(desiredIndex, errorCode); + } + return suppIndex; + } + } + int32_t bestIndexAndDistance = localeDistance.getBestIndexAndDistance( + desiredLSR, supportedLSRs, supportedLSRsLength, bestDistance, favorSubtag); + if (bestIndexAndDistance >= 0) { + bestDistance = bestIndexAndDistance & 0xff; + if (remainingIter != nullptr) { + remainingIter->rememberCurrent(desiredIndex, errorCode); + if (U_FAILURE(errorCode)) { return -1; } + } + bestSupportedLsrIndex = bestIndexAndDistance >= 0 ? bestIndexAndDistance >> 8 : -1; + } + if ((bestDistance -= demotionPerDesiredLocale) <= 0) { + break; + } + if (remainingIter == nullptr || !remainingIter->hasNext()) { + break; + } + desiredLSR = remainingIter->next(errorCode); + if (U_FAILURE(errorCode)) { return -1; } + ++desiredIndex; + } + if (bestSupportedLsrIndex < 0) { + // no good match + return -1; + } + return supportedIndexes[bestSupportedLsrIndex]; +} + +double LocaleMatcher::internalMatch(const Locale &desired, const Locale &supported, UErrorCode &errorCode) const { + // Returns the inverse of the distance: That is, 1-distance(desired, supported). + LSR suppLSR = getMaximalLsrOrUnd(likelySubtags, supported, errorCode); + if (U_FAILURE(errorCode)) { return 0; } + const LSR *pSuppLSR = &suppLSR; + int32_t distance = localeDistance.getBestIndexAndDistance( + getMaximalLsrOrUnd(likelySubtags, desired, errorCode), + &pSuppLSR, 1, + thresholdDistance, favorSubtag) & 0xff; + return (100 - distance) / 100.0; +} + +U_NAMESPACE_END + +#endif // __LOCMATCHER_H__ diff --git a/deps/icu-small/source/common/localeprioritylist.cpp b/deps/icu-small/source/common/localeprioritylist.cpp new file mode 100644 index 00000000000000..06442fb46a83ad --- /dev/null +++ b/deps/icu-small/source/common/localeprioritylist.cpp @@ -0,0 +1,239 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// localeprioritylist.cpp +// created: 2019jul11 Markus W. Scherer + +#include "unicode/utypes.h" +#include "unicode/localpointer.h" +#include "unicode/locid.h" +#include "unicode/stringpiece.h" +#include "unicode/uobject.h" +#include "charstr.h" +#include "cmemory.h" +#include "localeprioritylist.h" +#include "uarrsort.h" +#include "uassert.h" +#include "uhash.h" + +U_NAMESPACE_BEGIN + +namespace { + +int32_t hashLocale(const UHashTok token) { + auto *locale = static_cast(token.pointer); + return locale->hashCode(); +} + +UBool compareLocales(const UHashTok t1, const UHashTok t2) { + auto *l1 = static_cast(t1.pointer); + auto *l2 = static_cast(t2.pointer); + return *l1 == *l2; +} + +constexpr int32_t WEIGHT_ONE = 1000; + +struct LocaleAndWeight { + Locale *locale; + int32_t weight; // 0..1000 = 0.0..1.0 + int32_t index; // force stable sort + + int32_t compare(const LocaleAndWeight &other) const { + int32_t diff = other.weight - weight; // descending: other-this + if (diff != 0) { return diff; } + return index - other.index; + } +}; + +int32_t U_CALLCONV +compareLocaleAndWeight(const void * /*context*/, const void *left, const void *right) { + return static_cast(left)-> + compare(*static_cast(right)); +} + +const char *skipSpaces(const char *p, const char *limit) { + while (p < limit && *p == ' ') { ++p; } + return p; +} + +int32_t findTagLength(const char *p, const char *limit) { + // Look for accept-language delimiters. + // Leave other validation up to the Locale constructor. + const char *q; + for (q = p; q < limit; ++q) { + char c = *q; + if (c == ' ' || c == ',' || c == ';') { break; } + } + return static_cast(q - p); +} + +/** + * Parses and returns a qvalue weight in millis. + * Advances p to after the parsed substring. + * Returns a negative value if parsing fails. + */ +int32_t parseWeight(const char *&p, const char *limit) { + p = skipSpaces(p, limit); + char c; + if (p == limit || ((c = *p) != '0' && c != '1')) { return -1; } + int32_t weight = (c - '0') * 1000; + if (++p == limit || *p != '.') { return weight; } + int32_t multiplier = 100; + while (++p != limit && '0' <= (c = *p) && c <= '9') { + c -= '0'; + if (multiplier > 0) { + weight += c * multiplier; + multiplier /= 10; + } else if (multiplier == 0) { + // round up + if (c >= 5) { ++weight; } + multiplier = -1; + } // else ignore further fraction digits + } + return weight <= WEIGHT_ONE ? weight : -1; // bad if > 1.0 +} + +} // namespace + +/** + * Nothing but a wrapper over a MaybeStackArray of LocaleAndWeight. + * + * This wrapper exists (and is not in an anonymous namespace) + * so that we can forward-declare it in the header file and + * don't have to expose the MaybeStackArray specialization and + * the LocaleAndWeight to code (like the test) that #includes localeprioritylist.h. + * Also, otherwise we would have to do a platform-specific + * template export declaration of some kind for the MaybeStackArray specialization + * to be properly exported from the common DLL. + */ +struct LocaleAndWeightArray : public UMemory { + MaybeStackArray array; +}; + +LocalePriorityList::LocalePriorityList(StringPiece s, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return; } + list = new LocaleAndWeightArray(); + if (list == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + const char *p = s.data(); + const char *limit = p + s.length(); + while ((p = skipSpaces(p, limit)) != limit) { + if (*p == ',') { // empty range field + ++p; + continue; + } + int32_t tagLength = findTagLength(p, limit); + if (tagLength == 0) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + CharString tag(p, tagLength, errorCode); + if (U_FAILURE(errorCode)) { return; } + Locale locale = Locale(tag.data()); + if (locale.isBogus()) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + int32_t weight = WEIGHT_ONE; + if ((p = skipSpaces(p + tagLength, limit)) != limit && *p == ';') { + if ((p = skipSpaces(p + 1, limit)) == limit || *p != 'q' || + (p = skipSpaces(p + 1, limit)) == limit || *p != '=' || + (++p, (weight = parseWeight(p, limit)) < 0)) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + p = skipSpaces(p, limit); + } + if (p != limit && *p != ',') { // trailing junk + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + add(locale, weight, errorCode); + if (p == limit) { break; } + ++p; + } + sort(errorCode); +} + +LocalePriorityList::~LocalePriorityList() { + if (list != nullptr) { + for (int32_t i = 0; i < listLength; ++i) { + delete list->array[i].locale; + } + delete list; + } + uhash_close(map); +} + +const Locale *LocalePriorityList::localeAt(int32_t i) const { + return list->array[i].locale; +} + +Locale *LocalePriorityList::orphanLocaleAt(int32_t i) { + if (list == nullptr) { return nullptr; } + LocaleAndWeight &lw = list->array[i]; + Locale *l = lw.locale; + lw.locale = nullptr; + return l; +} + +bool LocalePriorityList::add(const Locale &locale, int32_t weight, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return false; } + if (map == nullptr) { + if (weight <= 0) { return true; } // do not add q=0 + map = uhash_open(hashLocale, compareLocales, uhash_compareLong, &errorCode); + if (U_FAILURE(errorCode)) { return false; } + } + LocalPointer clone; + int32_t index = uhash_geti(map, &locale); + if (index != 0) { + // Duplicate: Remove the old item and append it anew. + LocaleAndWeight &lw = list->array[index - 1]; + clone.adoptInstead(lw.locale); + lw.locale = nullptr; + lw.weight = 0; + ++numRemoved; + } + if (weight <= 0) { // do not add q=0 + if (index != 0) { + // Not strictly necessary but cleaner. + uhash_removei(map, &locale); + } + return true; + } + if (clone.isNull()) { + clone.adoptInstead(locale.clone()); + if (clone.isNull() || (clone->isBogus() && !locale.isBogus())) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return false; + } + } + if (listLength == list->array.getCapacity()) { + int32_t newCapacity = listLength < 50 ? 100 : 4 * listLength; + if (list->array.resize(newCapacity, listLength) == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return false; + } + } + uhash_puti(map, clone.getAlias(), listLength + 1, &errorCode); + if (U_FAILURE(errorCode)) { return false; } + LocaleAndWeight &lw = list->array[listLength]; + lw.locale = clone.orphan(); + lw.weight = weight; + lw.index = listLength++; + if (weight < WEIGHT_ONE) { hasWeights = true; } + U_ASSERT(uhash_count(map) == getLength()); + return true; +} + +void LocalePriorityList::sort(UErrorCode &errorCode) { + // Sort by descending weights if there is a mix of weights. + // The comparator forces a stable sort via the item index. + if (U_FAILURE(errorCode) || getLength() <= 1 || !hasWeights) { return; } + uprv_sortArray(list->array.getAlias(), listLength, sizeof(LocaleAndWeight), + compareLocaleAndWeight, nullptr, FALSE, &errorCode); +} + +U_NAMESPACE_END diff --git a/deps/icu-small/source/common/localeprioritylist.h b/deps/icu-small/source/common/localeprioritylist.h new file mode 100644 index 00000000000000..80ca38a7b52892 --- /dev/null +++ b/deps/icu-small/source/common/localeprioritylist.h @@ -0,0 +1,115 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// localeprioritylist.h +// created: 2019jul11 Markus W. Scherer + +#ifndef __LOCALEPRIORITYLIST_H__ +#define __LOCALEPRIORITYLIST_H__ + +#include "unicode/utypes.h" +#include "unicode/locid.h" +#include "unicode/stringpiece.h" +#include "unicode/uobject.h" + +struct UHashtable; + +U_NAMESPACE_BEGIN + +struct LocaleAndWeightArray; + +/** + * Parses a list of locales from an accept-language string. + * We are a bit more lenient than the spec: + * We accept extra whitespace in more places, empty range fields, + * and any number of qvalue fraction digits. + * + * https://tools.ietf.org/html/rfc2616#section-14.4 + * 14.4 Accept-Language + * + * Accept-Language = "Accept-Language" ":" + * 1#( language-range [ ";" "q" "=" qvalue ] ) + * language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) + * + * Each language-range MAY be given an associated quality value which + * represents an estimate of the user's preference for the languages + * specified by that range. The quality value defaults to "q=1". For + * example, + * + * Accept-Language: da, en-gb;q=0.8, en;q=0.7 + * + * https://tools.ietf.org/html/rfc2616#section-3.9 + * 3.9 Quality Values + * + * HTTP content negotiation (section 12) uses short "floating point" + * numbers to indicate the relative importance ("weight") of various + * negotiable parameters. A weight is normalized to a real number in + * the range 0 through 1, where 0 is the minimum and 1 the maximum + * value. If a parameter has a quality value of 0, then content with + * this parameter is `not acceptable' for the client. HTTP/1.1 + * applications MUST NOT generate more than three digits after the + * decimal point. User configuration of these values SHOULD also be + * limited in this fashion. + * + * qvalue = ( "0" [ "." 0*3DIGIT ] ) + * | ( "1" [ "." 0*3("0") ] ) + */ +class U_COMMON_API LocalePriorityList : public UMemory { +public: + class Iterator : public Locale::Iterator { + public: + UBool hasNext() const override { return count < length; } + + const Locale &next() override { + for(;;) { + const Locale *locale = list.localeAt(index++); + if (locale != nullptr) { + ++count; + return *locale; + } + } + } + + private: + friend class LocalePriorityList; + + Iterator(const LocalePriorityList &list) : list(list), length(list.getLength()) {} + + const LocalePriorityList &list; + int32_t index = 0; + int32_t count = 0; + const int32_t length; + }; + + LocalePriorityList(StringPiece s, UErrorCode &errorCode); + + ~LocalePriorityList(); + + int32_t getLength() const { return listLength - numRemoved; } + + int32_t getLengthIncludingRemoved() const { return listLength; } + + Iterator iterator() const { return Iterator(*this); } + + const Locale *localeAt(int32_t i) const; + + Locale *orphanLocaleAt(int32_t i); + +private: + LocalePriorityList(const LocalePriorityList &) = delete; + LocalePriorityList &operator=(const LocalePriorityList &) = delete; + + bool add(const Locale &locale, int32_t weight, UErrorCode &errorCode); + + void sort(UErrorCode &errorCode); + + LocaleAndWeightArray *list = nullptr; + int32_t listLength = 0; + int32_t numRemoved = 0; + bool hasWeights = false; // other than 1.0 + UHashtable *map = nullptr; +}; + +U_NAMESPACE_END + +#endif // __LOCALEPRIORITYLIST_H__ diff --git a/deps/icu-small/source/common/locavailable.cpp b/deps/icu-small/source/common/locavailable.cpp index 1e608ffb9e1c84..ad9d2ca8c7bb53 100644 --- a/deps/icu-small/source/common/locavailable.cpp +++ b/deps/icu-small/source/common/locavailable.cpp @@ -19,11 +19,13 @@ * that then do not depend on resource bundle code and res_index bundles. */ +#include "unicode/errorcode.h" #include "unicode/utypes.h" #include "unicode/locid.h" #include "unicode/uloc.h" #include "unicode/ures.h" #include "cmemory.h" +#include "cstring.h" #include "ucln_cmn.h" #include "uassert.h" #include "umutex.h" @@ -95,84 +97,174 @@ U_NAMESPACE_USE /* ### Constants **************************************************/ -/* These strings describe the resources we attempt to load from - the locale ResourceBundle data file.*/ -static const char _kIndexLocaleName[] = "res_index"; -static const char _kIndexTag[] = "InstalledLocales"; +namespace { -static char** _installedLocales = NULL; -static int32_t _installedLocalesCount = 0; -static icu::UInitOnce _installedLocalesInitOnce; +// Enough capacity for the two lists in the res_index.res file +const char** gAvailableLocaleNames[2] = {}; +int32_t gAvailableLocaleCounts[2] = {}; +icu::UInitOnce ginstalledLocalesInitOnce = U_INITONCE_INITIALIZER; -/* ### Get available **************************************************/ +class AvailableLocalesSink : public ResourceSink { + public: + void put(const char *key, ResourceValue &value, UBool /*noFallback*/, UErrorCode &status) U_OVERRIDE { + ResourceTable resIndexTable = value.getTable(status); + if (U_FAILURE(status)) { + return; + } + for (int32_t i = 0; resIndexTable.getKeyAndValue(i, key, value); ++i) { + ULocAvailableType type; + if (uprv_strcmp(key, "InstalledLocales") == 0) { + type = ULOC_AVAILABLE_DEFAULT; + } else if (uprv_strcmp(key, "AliasLocales") == 0) { + type = ULOC_AVAILABLE_ONLY_LEGACY_ALIASES; + } else { + // CLDRVersion, etc. + continue; + } + ResourceTable availableLocalesTable = value.getTable(status); + if (U_FAILURE(status)) { + return; + } + gAvailableLocaleCounts[type] = availableLocalesTable.getSize(); + gAvailableLocaleNames[type] = static_cast( + uprv_malloc(gAvailableLocaleCounts[type] * sizeof(const char*))); + if (gAvailableLocaleNames[type] == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + for (int32_t j = 0; availableLocalesTable.getKeyAndValue(j, key, value); ++j) { + gAvailableLocaleNames[type][j] = key; + } + } + } +}; -static UBool U_CALLCONV uloc_cleanup(void) { - char ** temp; +class AvailableLocalesStringEnumeration : public StringEnumeration { + public: + AvailableLocalesStringEnumeration(ULocAvailableType type) : fType(type) { + } + + const char* next(int32_t *resultLength, UErrorCode&) override { + ULocAvailableType actualType = fType; + int32_t actualIndex = fIndex++; + + // If the "combined" list was requested, resolve that now + if (fType == ULOC_AVAILABLE_WITH_LEGACY_ALIASES) { + int32_t defaultLocalesCount = gAvailableLocaleCounts[ULOC_AVAILABLE_DEFAULT]; + if (actualIndex < defaultLocalesCount) { + actualType = ULOC_AVAILABLE_DEFAULT; + } else { + actualIndex -= defaultLocalesCount; + actualType = ULOC_AVAILABLE_ONLY_LEGACY_ALIASES; + } + } + + // Return the requested string + int32_t count = gAvailableLocaleCounts[actualType]; + const char* result; + if (actualIndex < count) { + result = gAvailableLocaleNames[actualType][actualIndex]; + if (resultLength != nullptr) { + *resultLength = static_cast(uprv_strlen(result)); + } + } else { + result = nullptr; + if (resultLength != nullptr) { + *resultLength = 0; + } + } + return result; + } + + void reset(UErrorCode&) override { + fIndex = 0; + } + + int32_t count(UErrorCode&) const override { + if (fType == ULOC_AVAILABLE_WITH_LEGACY_ALIASES) { + return gAvailableLocaleCounts[ULOC_AVAILABLE_DEFAULT] + + gAvailableLocaleCounts[ULOC_AVAILABLE_ONLY_LEGACY_ALIASES]; + } else { + return gAvailableLocaleCounts[fType]; + } + } - if (_installedLocales) { - temp = _installedLocales; - _installedLocales = NULL; + private: + ULocAvailableType fType; + int32_t fIndex = 0; +}; - _installedLocalesCount = 0; - _installedLocalesInitOnce.reset(); +/* ### Get available **************************************************/ - uprv_free(temp); +static UBool U_CALLCONV uloc_cleanup(void) { + for (int32_t i = 0; i < UPRV_LENGTHOF(gAvailableLocaleNames); i++) { + uprv_free(gAvailableLocaleNames[i]); + gAvailableLocaleNames[i] = nullptr; + gAvailableLocaleCounts[i] = 0; } + ginstalledLocalesInitOnce.reset(); return TRUE; } // Load Installed Locales. This function will be called exactly once // via the initOnce mechanism. -static void U_CALLCONV loadInstalledLocales() { - UErrorCode status = U_ZERO_ERROR; - int32_t i = 0; - int32_t localeCount; - - U_ASSERT(_installedLocales == NULL); - U_ASSERT(_installedLocalesCount == 0); +static void U_CALLCONV loadInstalledLocales(UErrorCode& status) { + ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup); - _installedLocalesCount = 0; + icu::LocalUResourceBundlePointer rb(ures_openDirect(NULL, "res_index", &status)); + AvailableLocalesSink sink; + ures_getAllItemsWithFallback(rb.getAlias(), "", sink, status); +} - icu::LocalUResourceBundlePointer indexLocale(ures_openDirect(NULL, _kIndexLocaleName, &status)); - icu::StackUResourceBundle installed; +void _load_installedLocales(UErrorCode& status) { + umtx_initOnce(ginstalledLocalesInitOnce, &loadInstalledLocales, status); +} - ures_getByKey(indexLocale.getAlias(), _kIndexTag, installed.getAlias(), &status); +} // namespace - if(U_SUCCESS(status)) { - localeCount = ures_getSize(installed.getAlias()); - _installedLocales = (char **) uprv_malloc(sizeof(char*) * (localeCount+1)); - if (_installedLocales != NULL) { - ures_resetIterator(installed.getAlias()); - while(ures_hasNext(installed.getAlias())) { - ures_getNextString(installed.getAlias(), NULL, (const char **)&_installedLocales[i++], &status); - } - _installedLocales[i] = NULL; - _installedLocalesCount = localeCount; - ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup); - } +U_CAPI const char* U_EXPORT2 +uloc_getAvailable(int32_t offset) { + icu::ErrorCode status; + _load_installedLocales(status); + if (status.isFailure()) { + return nullptr; + } + if (offset > gAvailableLocaleCounts[0]) { + // *status = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; } + return gAvailableLocaleNames[0][offset]; } -static void _load_installedLocales() -{ - umtx_initOnce(_installedLocalesInitOnce, &loadInstalledLocales); +U_CAPI int32_t U_EXPORT2 +uloc_countAvailable() { + icu::ErrorCode status; + _load_installedLocales(status); + if (status.isFailure()) { + return 0; + } + return gAvailableLocaleCounts[0]; } -U_CAPI const char* U_EXPORT2 -uloc_getAvailable(int32_t offset) -{ - - _load_installedLocales(); - - if (offset > _installedLocalesCount) - return NULL; - return _installedLocales[offset]; +U_CAPI UEnumeration* U_EXPORT2 +uloc_openAvailableByType(ULocAvailableType type, UErrorCode* status) { + if (U_FAILURE(*status)) { + return nullptr; + } + if (type < 0 || type >= ULOC_AVAILABLE_COUNT) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + _load_installedLocales(*status); + if (U_FAILURE(*status)) { + return nullptr; + } + LocalPointer result( + new AvailableLocalesStringEnumeration(type), *status); + if (U_FAILURE(*status)) { + return nullptr; + } + return uenum_openFromStringEnumeration(result.orphan(), status); } -U_CAPI int32_t U_EXPORT2 -uloc_countAvailable() -{ - _load_installedLocales(); - return _installedLocalesCount; -} diff --git a/deps/icu-small/source/common/locbased.h b/deps/icu-small/source/common/locbased.h index 6db6a41dc416df..9163bd11cfe65f 100644 --- a/deps/icu-small/source/common/locbased.h +++ b/deps/icu-small/source/common/locbased.h @@ -22,7 +22,7 @@ * `actualLocale' of size ULOC_FULLNAME_CAPACITY */ #define U_LOCALE_BASED(varname, objname) \ - LocaleBased varname((objname).validLocale, (objname).actualLocale); + LocaleBased varname((objname).validLocale, (objname).actualLocale) U_NAMESPACE_BEGIN diff --git a/deps/icu-small/source/common/locdistance.cpp b/deps/icu-small/source/common/locdistance.cpp new file mode 100644 index 00000000000000..800d0eacf2b605 --- /dev/null +++ b/deps/icu-small/source/common/locdistance.cpp @@ -0,0 +1,364 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// locdistance.cpp +// created: 2019may08 Markus W. Scherer + +#include "unicode/utypes.h" +#include "unicode/bytestrie.h" +#include "unicode/localematcher.h" +#include "unicode/locid.h" +#include "unicode/uobject.h" +#include "unicode/ures.h" +#include "cstring.h" +#include "locdistance.h" +#include "loclikelysubtags.h" +#include "uassert.h" +#include "ucln_cmn.h" +#include "uinvchar.h" +#include "umutex.h" + +U_NAMESPACE_BEGIN + +namespace { + +/** + * Bit flag used on the last character of a subtag in the trie. + * Must be set consistently by the builder and the lookup code. + */ +constexpr int32_t END_OF_SUBTAG = 0x80; +/** Distance value bit flag, set by the builder. */ +constexpr int32_t DISTANCE_SKIP_SCRIPT = 0x80; +/** Distance value bit flag, set by trieNext(). */ +constexpr int32_t DISTANCE_IS_FINAL = 0x100; +constexpr int32_t DISTANCE_IS_FINAL_OR_SKIP_SCRIPT = DISTANCE_IS_FINAL | DISTANCE_SKIP_SCRIPT; + +constexpr int32_t ABOVE_THRESHOLD = 100; + +// Indexes into array of distances. +enum { + IX_DEF_LANG_DISTANCE, + IX_DEF_SCRIPT_DISTANCE, + IX_DEF_REGION_DISTANCE, + IX_MIN_REGION_DISTANCE, + IX_LIMIT +}; + +LocaleDistance *gLocaleDistance = nullptr; +UInitOnce gInitOnce = U_INITONCE_INITIALIZER; + +UBool U_CALLCONV cleanup() { + delete gLocaleDistance; + gLocaleDistance = nullptr; + gInitOnce.reset(); + return TRUE; +} + +} // namespace + +void U_CALLCONV LocaleDistance::initLocaleDistance(UErrorCode &errorCode) { + // This function is invoked only via umtx_initOnce(). + U_ASSERT(gLocaleDistance == nullptr); + const XLikelySubtags &likely = *XLikelySubtags::getSingleton(errorCode); + if (U_FAILURE(errorCode)) { return; } + const LocaleDistanceData &data = likely.getDistanceData(); + if (data.distanceTrieBytes == nullptr || + data.regionToPartitions == nullptr || data.partitions == nullptr || + // ok if no paradigms + data.distances == nullptr) { + errorCode = U_MISSING_RESOURCE_ERROR; + return; + } + gLocaleDistance = new LocaleDistance(data); + if (gLocaleDistance == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + ucln_common_registerCleanup(UCLN_COMMON_LOCALE_DISTANCE, cleanup); +} + +const LocaleDistance *LocaleDistance::getSingleton(UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return nullptr; } + umtx_initOnce(gInitOnce, &LocaleDistance::initLocaleDistance, errorCode); + return gLocaleDistance; +} + +LocaleDistance::LocaleDistance(const LocaleDistanceData &data) : + trie(data.distanceTrieBytes), + regionToPartitionsIndex(data.regionToPartitions), partitionArrays(data.partitions), + paradigmLSRs(data.paradigms), paradigmLSRsLength(data.paradigmsLength), + defaultLanguageDistance(data.distances[IX_DEF_LANG_DISTANCE]), + defaultScriptDistance(data.distances[IX_DEF_SCRIPT_DISTANCE]), + defaultRegionDistance(data.distances[IX_DEF_REGION_DISTANCE]), + minRegionDistance(data.distances[IX_MIN_REGION_DISTANCE]) { + // For the default demotion value, use the + // default region distance between unrelated Englishes. + // Thus, unless demotion is turned off, + // 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"); + const LSR *p_enGB = &enGB; + defaultDemotionPerDesiredLocale = getBestIndexAndDistance(en, &p_enGB, 1, + 50, ULOCMATCH_FAVOR_LANGUAGE) & 0xff; +} + +int32_t LocaleDistance::getBestIndexAndDistance( + const LSR &desired, + const LSR **supportedLSRs, int32_t supportedLSRsLength, + int32_t threshold, ULocMatchFavorSubtag favorSubtag) 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. + // Note: The data builder verifies that there are no <*, supported> or rules. + int32_t desLangDistance = trieNext(iter, desired.language, false); + uint64_t desLangState = desLangDistance >= 0 && supportedLSRsLength > 1 ? iter.getState64() : 0; + // Index of the supported LSR with the lowest distance. + int32_t bestIndex = -1; + for (int32_t slIndex = 0; slIndex < supportedLSRsLength; ++slIndex) { + const LSR &supported = *supportedLSRs[slIndex]; + bool star = false; + int32_t distance = desLangDistance; + if (distance >= 0) { + U_ASSERT((distance & DISTANCE_IS_FINAL) == 0); + if (slIndex != 0) { + iter.resetToState64(desLangState); + } + distance = trieNext(iter, supported.language, true); + } + // Note: The data builder verifies that there are no rules with "any" (*) language and + // real (non *) script or region subtags. + // This means that if the lookup for either language fails we can use + // the default distances without further lookups. + int32_t flags; + if (distance >= 0) { + flags = distance & DISTANCE_IS_FINAL_OR_SKIP_SCRIPT; + distance &= ~DISTANCE_IS_FINAL_OR_SKIP_SCRIPT; + } else { // <*, *> + if (uprv_strcmp(desired.language, supported.language) == 0) { + distance = 0; + } else { + distance = defaultLanguageDistance; + } + flags = 0; + star = true; + } + U_ASSERT(0 <= distance && distance <= 100); + // 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. + // For example, given a default language distance of 80, we reduce it to 20, + // which is below the default threshold of 50, which is the default script distance. + if (favorSubtag == ULOCMATCH_FAVOR_SCRIPT) { + distance >>= 2; + } + if (distance >= threshold) { + continue; + } + + int32_t scriptDistance; + if (star || flags != 0) { + if (uprv_strcmp(desired.script, supported.script) == 0) { + scriptDistance = 0; + } else { + scriptDistance = defaultScriptDistance; + } + } else { + scriptDistance = getDesSuppScriptDistance(iter, iter.getState64(), + desired.script, supported.script); + flags = scriptDistance & DISTANCE_IS_FINAL; + scriptDistance &= ~DISTANCE_IS_FINAL; + } + distance += scriptDistance; + if (distance >= threshold) { + continue; + } + + if (uprv_strcmp(desired.region, supported.region) == 0) { + // regionDistance = 0 + } else if (star || (flags & DISTANCE_IS_FINAL) != 0) { + distance += defaultRegionDistance; + } else { + int32_t remainingThreshold = threshold - distance; + if (minRegionDistance >= remainingThreshold) { + continue; + } + + // From here on we know the regions are not equal. + // Map each region to zero or more partitions. (zero = one non-matching string) + // (Each array of single-character partition strings is encoded as one string.) + // If either side has more than one, then we find the maximum distance. + // This could be optimized by adding some more structure, but probably not worth it. + distance += getRegionPartitionsDistance( + iter, iter.getState64(), + partitionsForRegion(desired), + partitionsForRegion(supported), + remainingThreshold); + } + if (distance < threshold) { + if (distance == 0) { + return slIndex << 8; + } + bestIndex = slIndex; + threshold = distance; + } + } + return bestIndex >= 0 ? (bestIndex << 8) | threshold : 0xffffff00 | ABOVE_THRESHOLD; +} + +int32_t LocaleDistance::getDesSuppScriptDistance( + BytesTrie &iter, uint64_t startState, const char *desired, const char *supported) { + // Note: The data builder verifies that there are no <*, supported> or rules. + int32_t distance = trieNext(iter, desired, false); + if (distance >= 0) { + distance = trieNext(iter, supported, true); + } + if (distance < 0) { + UStringTrieResult result = iter.resetToState64(startState).next(u'*'); // <*, *> + U_ASSERT(USTRINGTRIE_HAS_VALUE(result)); + if (uprv_strcmp(desired, supported) == 0) { + distance = 0; // same script + } else { + distance = iter.getValue(); + U_ASSERT(distance >= 0); + } + if (result == USTRINGTRIE_FINAL_VALUE) { + distance |= DISTANCE_IS_FINAL; + } + } + return distance; +} + +int32_t LocaleDistance::getRegionPartitionsDistance( + BytesTrie &iter, uint64_t startState, + const char *desiredPartitions, const char *supportedPartitions, int32_t threshold) { + char desired = *desiredPartitions++; + char supported = *supportedPartitions++; + U_ASSERT(desired != 0 && supported != 0); + // See if we have single desired/supported partitions, from NUL-terminated + // partition strings without explicit length. + bool suppLengthGt1 = *supportedPartitions != 0; // gt1: more than 1 character + // equivalent to: if (desLength == 1 && suppLength == 1) + if (*desiredPartitions == 0 && !suppLengthGt1) { + // Fastpath for single desired/supported partitions. + UStringTrieResult result = iter.next(uprv_invCharToAscii(desired) | END_OF_SUBTAG); + if (USTRINGTRIE_HAS_NEXT(result)) { + result = iter.next(uprv_invCharToAscii(supported) | END_OF_SUBTAG); + if (USTRINGTRIE_HAS_VALUE(result)) { + return iter.getValue(); + } + } + return getFallbackRegionDistance(iter, startState); + } + + const char *supportedStart = supportedPartitions - 1; // for restart of inner loop + int32_t regionDistance = 0; + // Fall back to * only once, not for each pair of partition strings. + bool star = false; + for (;;) { + // Look up each desired-partition string only once, + // not for each (desired, supported) pair. + UStringTrieResult result = iter.next(uprv_invCharToAscii(desired) | END_OF_SUBTAG); + if (USTRINGTRIE_HAS_NEXT(result)) { + uint64_t desState = suppLengthGt1 ? iter.getState64() : 0; + for (;;) { + result = iter.next(uprv_invCharToAscii(supported) | END_OF_SUBTAG); + int32_t d; + if (USTRINGTRIE_HAS_VALUE(result)) { + d = iter.getValue(); + } else if (star) { + d = 0; + } else { + d = getFallbackRegionDistance(iter, startState); + star = true; + } + if (d >= threshold) { + return d; + } else if (regionDistance < d) { + regionDistance = d; + } + if ((supported = *supportedPartitions++) != 0) { + iter.resetToState64(desState); + } else { + break; + } + } + } else if (!star) { + int32_t d = getFallbackRegionDistance(iter, startState); + if (d >= threshold) { + return d; + } else if (regionDistance < d) { + regionDistance = d; + } + star = true; + } + if ((desired = *desiredPartitions++) != 0) { + iter.resetToState64(startState); + supportedPartitions = supportedStart; + supported = *supportedPartitions++; + } else { + break; + } + } + return regionDistance; +} + +int32_t LocaleDistance::getFallbackRegionDistance(BytesTrie &iter, uint64_t startState) { +#if U_DEBUG + UStringTrieResult result = +#endif + iter.resetToState64(startState).next(u'*'); // <*, *> + U_ASSERT(USTRINGTRIE_HAS_VALUE(result)); + int32_t distance = iter.getValue(); + U_ASSERT(distance >= 0); + return distance; +} + +int32_t LocaleDistance::trieNext(BytesTrie &iter, const char *s, bool wantValue) { + uint8_t c; + if ((c = *s) == 0) { + return -1; // no empty subtags in the distance data + } + for (;;) { + c = uprv_invCharToAscii(c); + // EBCDIC: If *s is not an invariant character, + // then c is now 0 and will simply not match anything, which is harmless. + uint8_t next = *++s; + if (next != 0) { + if (!USTRINGTRIE_HAS_NEXT(iter.next(c))) { + return -1; + } + } else { + // last character of this subtag + UStringTrieResult result = iter.next(c | END_OF_SUBTAG); + if (wantValue) { + if (USTRINGTRIE_HAS_VALUE(result)) { + int32_t value = iter.getValue(); + if (result == USTRINGTRIE_FINAL_VALUE) { + value |= DISTANCE_IS_FINAL; + } + return value; + } + } else { + if (USTRINGTRIE_HAS_NEXT(result)) { + return 0; + } + } + return -1; + } + c = next; + } +} + +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. + U_ASSERT(paradigmLSRsLength <= 15); + for (int32_t i = 0; i < paradigmLSRsLength; ++i) { + if (lsr == paradigmLSRs[i]) { return true; } + } + return false; +} + +U_NAMESPACE_END diff --git a/deps/icu-small/source/common/locdistance.h b/deps/icu-small/source/common/locdistance.h new file mode 100644 index 00000000000000..7439f51c56bf8c --- /dev/null +++ b/deps/icu-small/source/common/locdistance.h @@ -0,0 +1,109 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// locdistance.h +// created: 2019may08 Markus W. Scherer + +#ifndef __LOCDISTANCE_H__ +#define __LOCDISTANCE_H__ + +#include "unicode/utypes.h" +#include "unicode/bytestrie.h" +#include "unicode/localematcher.h" +#include "unicode/locid.h" +#include "unicode/uobject.h" +#include "lsr.h" + +U_NAMESPACE_BEGIN + +struct LocaleDistanceData; + +/** + * Offline-built data for LocaleMatcher. + * Mostly but not only the data for mapping locales to their maximized forms. + */ +class LocaleDistance final : public UMemory { +public: + static const LocaleDistance *getSingleton(UErrorCode &errorCode); + + /** + * 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 + * (negative if none has a distance below the threshold), + * and its distance (0..ABOVE_THRESHOLD) in bits 7..0. + */ + int32_t getBestIndexAndDistance(const LSR &desired, + const LSR **supportedLSRs, int32_t supportedLSRsLength, + int32_t threshold, ULocMatchFavorSubtag favorSubtag) const; + + int32_t getParadigmLSRsLength() const { return paradigmLSRsLength; } + + UBool isParadigmLSR(const LSR &lsr) const; + + int32_t getDefaultScriptDistance() const { + return defaultScriptDistance; + } + + int32_t getDefaultDemotionPerDesiredLocale() const { + return defaultDemotionPerDesiredLocale; + } + +private: + LocaleDistance(const LocaleDistanceData &data); + LocaleDistance(const LocaleDistance &other) = delete; + LocaleDistance &operator=(const LocaleDistance &other) = delete; + + static void initLocaleDistance(UErrorCode &errorCode); + + static int32_t getDesSuppScriptDistance(BytesTrie &iter, uint64_t startState, + const char *desired, const char *supported); + + static int32_t getRegionPartitionsDistance( + BytesTrie &iter, uint64_t startState, + const char *desiredPartitions, const char *supportedPartitions, + int32_t threshold); + + static int32_t getFallbackRegionDistance(BytesTrie &iter, uint64_t startState); + + static int32_t trieNext(BytesTrie &iter, const char *s, bool wantValue); + + const char *partitionsForRegion(const LSR &lsr) const { + // ill-formed region -> one non-matching string + int32_t pIndex = regionToPartitionsIndex[lsr.regionIndex]; + return partitionArrays[pIndex]; + } + + int32_t getDefaultRegionDistance() const { + return defaultRegionDistance; + } + + // 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. + // One '*' is used for a (desired, supported) pair of "und", "Zzzz"/"", or "ZZ"/"". + BytesTrie trie; + + /** + * Maps each region to zero or more single-character partitions. + */ + const uint8_t *regionToPartitionsIndex; + const char **partitionArrays; + + /** + * Used to get the paradigm region for a cluster, if there is one. + */ + const LSR *paradigmLSRs; + int32_t paradigmLSRsLength; + + int32_t defaultLanguageDistance; + int32_t defaultScriptDistance; + int32_t defaultRegionDistance; + int32_t minRegionDistance; + int32_t defaultDemotionPerDesiredLocale; +}; + +U_NAMESPACE_END + +#endif // __LOCDISTANCE_H__ diff --git a/deps/icu-small/source/common/locdspnm.cpp b/deps/icu-small/source/common/locdspnm.cpp index da35be9e766e50..43334f51964622 100644 --- a/deps/icu-small/source/common/locdspnm.cpp +++ b/deps/icu-small/source/common/locdspnm.cpp @@ -291,6 +291,7 @@ class LocaleDisplayNamesImpl : public LocaleDisplayNames { UnicodeString formatCloseParen; UnicodeString formatReplaceCloseParen; UDisplayContext nameLength; + UDisplayContext substitute; // Constants for capitalization context usage types. enum CapContextUsage { @@ -337,7 +338,7 @@ class LocaleDisplayNamesImpl : public LocaleDisplayNames { UnicodeString& result) const; private: UnicodeString& localeIdName(const char* localeId, - UnicodeString& result) const; + UnicodeString& result, bool substitute) const; UnicodeString& appendWithSep(UnicodeString& buffer, const UnicodeString& src) const; UnicodeString& adjustForUsageAndContext(CapContextUsage usage, UnicodeString& result) const; UnicodeString& scriptDisplayName(const char* script, UnicodeString& result, UBool skipAdjust) const; @@ -359,6 +360,7 @@ LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale, , capitalizationContext(UDISPCTX_CAPITALIZATION_NONE) , capitalizationBrkIter(NULL) , nameLength(UDISPCTX_LENGTH_FULL) + , substitute(UDISPCTX_SUBSTITUTE) { initialize(); } @@ -371,6 +373,7 @@ LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale, , capitalizationContext(UDISPCTX_CAPITALIZATION_NONE) , capitalizationBrkIter(NULL) , nameLength(UDISPCTX_LENGTH_FULL) + , substitute(UDISPCTX_SUBSTITUTE) { while (length-- > 0) { UDisplayContext value = *contexts++; @@ -385,6 +388,9 @@ LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale, case UDISPCTX_TYPE_DISPLAY_LENGTH: nameLength = value; break; + case UDISPCTX_TYPE_SUBSTITUTE_HANDLING: + substitute = value; + break; default: break; } @@ -535,6 +541,8 @@ LocaleDisplayNamesImpl::getContext(UDisplayContextType type) const { return capitalizationContext; case UDISPCTX_TYPE_DISPLAY_LENGTH: return nameLength; + case UDISPCTX_TYPE_SUBSTITUTE_HANDLING: + return substitute; default: break; } @@ -549,7 +557,7 @@ LocaleDisplayNamesImpl::adjustForUsageAndContext(CapContextUsage usage, if ( result.length() > 0 && u_islower(result.char32At(0)) && capitalizationBrkIter!= NULL && ( capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE || fCapitalization[usage] ) ) { // note fCapitalization[usage] won't be set unless capitalizationContext is UI_LIST_OR_MENU or STANDALONE - static UMutex capitalizationBrkIterLock = U_MUTEX_INITIALIZER; + static UMutex capitalizationBrkIterLock; Mutex lock(&capitalizationBrkIterLock); result.toTitle(capitalizationBrkIter, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); } @@ -583,7 +591,7 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc, do { // loop construct is so we can break early out of search if (hasScript && hasCountry) { ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, "_", country, (char *)0); - localeIdName(buffer, resultName); + localeIdName(buffer, resultName, false); if (!resultName.isBogus()) { hasScript = FALSE; hasCountry = FALSE; @@ -592,7 +600,7 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc, } if (hasScript) { ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, (char *)0); - localeIdName(buffer, resultName); + localeIdName(buffer, resultName, false); if (!resultName.isBogus()) { hasScript = FALSE; break; @@ -600,7 +608,7 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc, } if (hasCountry) { ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", country, (char*)0); - localeIdName(buffer, resultName); + localeIdName(buffer, resultName, false); if (!resultName.isBogus()) { hasCountry = FALSE; break; @@ -609,7 +617,11 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc, } while (FALSE); } if (resultName.isBogus() || resultName.isEmpty()) { - localeIdName(lang, resultName); + localeIdName(lang, resultName, substitute == UDISPCTX_SUBSTITUTE); + if (resultName.isBogus()) { + result.setToBogus(); + return result; + } } UnicodeString resultRemainder; @@ -617,13 +629,28 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc, UErrorCode status = U_ZERO_ERROR; if (hasScript) { - resultRemainder.append(scriptDisplayName(script, temp, TRUE)); + UnicodeString script_str = scriptDisplayName(script, temp, TRUE); + if (script_str.isBogus()) { + result.setToBogus(); + return result; + } + resultRemainder.append(script_str); } if (hasCountry) { - appendWithSep(resultRemainder, regionDisplayName(country, temp, TRUE)); + UnicodeString region_str = regionDisplayName(country, temp, TRUE); + if (region_str.isBogus()) { + result.setToBogus(); + return result; + } + appendWithSep(resultRemainder, region_str); } if (hasVariant) { - appendWithSep(resultRemainder, variantDisplayName(variant, temp, TRUE)); + UnicodeString variant_str = variantDisplayName(variant, temp, TRUE); + if (variant_str.isBogus()) { + result.setToBogus(); + return result; + } + appendWithSep(resultRemainder, variant_str); } resultRemainder.findAndReplace(formatOpenParen, formatReplaceOpenParen); resultRemainder.findAndReplace(formatCloseParen, formatReplaceCloseParen); @@ -689,14 +716,18 @@ LocaleDisplayNamesImpl::localeDisplayName(const char* localeId, // private UnicodeString& LocaleDisplayNamesImpl::localeIdName(const char* localeId, - UnicodeString& result) const { + UnicodeString& result, bool substitute) const { if (nameLength == UDISPCTX_LENGTH_SHORT) { langData.getNoFallback("Languages%short", localeId, result); if (!result.isBogus()) { return result; } } - return langData.getNoFallback("Languages", localeId, result); + if (substitute) { + return langData.get("Languages", localeId, result); + } else { + return langData.getNoFallback("Languages", localeId, result); + } } UnicodeString& @@ -706,12 +737,16 @@ LocaleDisplayNamesImpl::languageDisplayName(const char* lang, return result = UnicodeString(lang, -1, US_INV); } if (nameLength == UDISPCTX_LENGTH_SHORT) { - langData.get("Languages%short", lang, result); + langData.getNoFallback("Languages%short", lang, result); if (!result.isBogus()) { return adjustForUsageAndContext(kCapContextUsageLanguage, result); } } - langData.get("Languages", lang, result); + if (substitute == UDISPCTX_SUBSTITUTE) { + langData.get("Languages", lang, result); + } else { + langData.getNoFallback("Languages", lang, result); + } return adjustForUsageAndContext(kCapContextUsageLanguage, result); } @@ -720,12 +755,16 @@ LocaleDisplayNamesImpl::scriptDisplayName(const char* script, UnicodeString& result, UBool skipAdjust) const { if (nameLength == UDISPCTX_LENGTH_SHORT) { - langData.get("Scripts%short", script, result); + langData.getNoFallback("Scripts%short", script, result); if (!result.isBogus()) { return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageScript, result); } } - langData.get("Scripts", script, result); + if (substitute == UDISPCTX_SUBSTITUTE) { + langData.get("Scripts", script, result); + } else { + langData.getNoFallback("Scripts", script, result); + } return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageScript, result); } @@ -746,12 +785,16 @@ LocaleDisplayNamesImpl::regionDisplayName(const char* region, UnicodeString& result, UBool skipAdjust) const { if (nameLength == UDISPCTX_LENGTH_SHORT) { - regionData.get("Countries%short", region, result); + regionData.getNoFallback("Countries%short", region, result); if (!result.isBogus()) { return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageTerritory, result); } } - regionData.get("Countries", region, result); + if (substitute == UDISPCTX_SUBSTITUTE) { + regionData.get("Countries", region, result); + } else { + regionData.getNoFallback("Countries", region, result); + } return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageTerritory, result); } @@ -767,7 +810,11 @@ LocaleDisplayNamesImpl::variantDisplayName(const char* variant, UnicodeString& result, UBool skipAdjust) const { // don't have a resource for short variant names - langData.get("Variants", variant, result); + if (substitute == UDISPCTX_SUBSTITUTE) { + langData.get("Variants", variant, result); + } else { + langData.getNoFallback("Variants", variant, result); + } return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageVariant, result); } @@ -782,7 +829,11 @@ LocaleDisplayNamesImpl::keyDisplayName(const char* key, UnicodeString& result, UBool skipAdjust) const { // don't have a resource for short key names - langData.get("Keys", key, result); + if (substitute == UDISPCTX_SUBSTITUTE) { + langData.get("Keys", key, result); + } else { + langData.getNoFallback("Keys", key, result); + } return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageKey, result); } @@ -802,9 +853,8 @@ LocaleDisplayNamesImpl::keyValueDisplayName(const char* key, UErrorCode sts = U_ZERO_ERROR; UnicodeString ustrValue(value, -1, US_INV); int32_t len; - UBool isChoice = FALSE; const UChar *currencyName = ucurr_getName(ustrValue.getTerminatedBuffer(), - locale.getBaseName(), UCURR_LONG_NAME, &isChoice, &len, &sts); + locale.getBaseName(), UCURR_LONG_NAME, nullptr /* isChoiceFormat */, &len, &sts); if (U_FAILURE(sts)) { // Return the value as is on failure result = ustrValue; @@ -815,12 +865,16 @@ LocaleDisplayNamesImpl::keyValueDisplayName(const char* key, } if (nameLength == UDISPCTX_LENGTH_SHORT) { - langData.get("Types%short", key, value, result); + langData.getNoFallback("Types%short", key, value, result); if (!result.isBogus()) { return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageKeyValue, result); } } - langData.get("Types", key, value, result); + if (substitute == UDISPCTX_SUBSTITUTE) { + langData.get("Types", key, value, result); + } else { + langData.getNoFallback("Types", key, value, result); + } return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageKeyValue, result); } diff --git a/deps/icu-small/source/common/locid.cpp b/deps/icu-small/source/common/locid.cpp index 06986b636adc31..c6d3f88fc3be07 100644 --- a/deps/icu-small/source/common/locid.cpp +++ b/deps/icu-small/source/common/locid.cpp @@ -38,19 +38,19 @@ #include "unicode/strenum.h" #include "unicode/stringpiece.h" #include "unicode/uloc.h" -#include "putilimp.h" -#include "mutex.h" -#include "umutex.h" -#include "uassert.h" + +#include "bytesinkutil.h" +#include "charstr.h" #include "cmemory.h" #include "cstring.h" +#include "mutex.h" +#include "putilimp.h" #include "uassert.h" +#include "ucln_cmn.h" #include "uhash.h" #include "ulocimp.h" -#include "ucln_cmn.h" +#include "umutex.h" #include "ustr_imp.h" -#include "charstr.h" -#include "bytesinkutil.h" U_CDECL_BEGIN static UBool U_CALLCONV locale_cleanup(void); @@ -62,10 +62,7 @@ static Locale *gLocaleCache = NULL; static UInitOnce gLocaleCacheInitOnce = U_INITONCE_INITIALIZER; // gDefaultLocaleMutex protects all access to gDefaultLocalesHashT and gDefaultLocale. -static UMutex *gDefaultLocaleMutex() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex gDefaultLocaleMutex; static UHashtable *gDefaultLocalesHashT = NULL; static Locale *gDefaultLocale = NULL; @@ -174,7 +171,7 @@ U_NAMESPACE_BEGIN Locale *locale_set_default_internal(const char *id, UErrorCode& status) { // Synchronize this entire function. - Mutex lock(gDefaultLocaleMutex()); + Mutex lock(&gDefaultLocaleMutex); UBool canonicalize = FALSE; @@ -711,7 +708,7 @@ const Locale& U_EXPORT2 Locale::getDefault() { { - Mutex lock(gDefaultLocaleMutex()); + Mutex lock(&gDefaultLocaleMutex); if (gDefaultLocale != NULL) { return *gDefaultLocale; } @@ -1399,5 +1396,7 @@ Locale::getBaseName() const { return baseName; } +Locale::Iterator::~Iterator() = default; + //eof U_NAMESPACE_END diff --git a/deps/icu-small/source/common/loclikely.cpp b/deps/icu-small/source/common/loclikely.cpp index 50cc2a65de0b2d..3b71708e549d5f 100644 --- a/deps/icu-small/source/common/loclikely.cpp +++ b/deps/icu-small/source/common/loclikely.cpp @@ -807,24 +807,24 @@ createLikelySubtagsString( return FALSE; } -#define CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength) \ - { int32_t count = 0; \ - int32_t i; \ - for (i = 0; i < trailingLength; i++) { \ - if (trailing[i] == '-' || trailing[i] == '_') { \ - count = 0; \ - if (count > 8) { \ - goto error; \ - } \ - } else if (trailing[i] == '@') { \ - break; \ - } else if (count > 8) { \ +#define CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength) UPRV_BLOCK_MACRO_BEGIN { \ + int32_t count = 0; \ + int32_t i; \ + for (i = 0; i < trailingLength; i++) { \ + if (trailing[i] == '-' || trailing[i] == '_') { \ + count = 0; \ + if (count > 8) { \ goto error; \ - } else { \ - count++; \ } \ + } else if (trailing[i] == '@') { \ + break; \ + } else if (count > 8) { \ + goto error; \ + } else { \ + count++; \ } \ - } + } \ +} UPRV_BLOCK_MACRO_END static void _uloc_addLikelySubtags(const char* localeID, diff --git a/deps/icu-small/source/common/loclikelysubtags.cpp b/deps/icu-small/source/common/loclikelysubtags.cpp new file mode 100644 index 00000000000000..d7f5e124c2c790 --- /dev/null +++ b/deps/icu-small/source/common/loclikelysubtags.cpp @@ -0,0 +1,638 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// loclikelysubtags.cpp +// created: 2019may08 Markus W. Scherer + +#include +#include "unicode/utypes.h" +#include "unicode/bytestrie.h" +#include "unicode/localpointer.h" +#include "unicode/locid.h" +#include "unicode/uobject.h" +#include "unicode/ures.h" +#include "charstr.h" +#include "cstring.h" +#include "loclikelysubtags.h" +#include "lsr.h" +#include "uassert.h" +#include "ucln_cmn.h" +#include "uhash.h" +#include "uinvchar.h" +#include "umutex.h" +#include "uresdata.h" +#include "uresimp.h" + +U_NAMESPACE_BEGIN + +namespace { + +constexpr char PSEUDO_ACCENTS_PREFIX = '\''; // -XA, -PSACCENT +constexpr char PSEUDO_BIDI_PREFIX = '+'; // -XB, -PSBIDI +constexpr char PSEUDO_CRACKED_PREFIX = ','; // -XC, -PSCRACK + +/** + * Stores NUL-terminated strings with duplicate elimination. + * Checks for unique UTF-16 string pointers and converts to invariant characters. + */ +class UniqueCharStrings { +public: + UniqueCharStrings(UErrorCode &errorCode) : strings(nullptr) { + uhash_init(&map, uhash_hashUChars, uhash_compareUChars, uhash_compareLong, &errorCode); + if (U_FAILURE(errorCode)) { return; } + strings = new CharString(); + if (strings == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + } + } + ~UniqueCharStrings() { + uhash_close(&map); + delete strings; + } + + /** Returns/orphans the CharString that contains all strings. */ + CharString *orphanCharStrings() { + CharString *result = strings; + strings = nullptr; + return result; + } + + /** Adds a string and returns a unique number for it. */ + int32_t add(const UnicodeString &s, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return 0; } + if (isFrozen) { + errorCode = U_NO_WRITE_PERMISSION; + return 0; + } + // The string points into the resource bundle. + const char16_t *p = s.getBuffer(); + int32_t oldIndex = uhash_geti(&map, p); + if (oldIndex != 0) { // found duplicate + return oldIndex; + } + // Explicit NUL terminator for the previous string. + // The strings object is also terminated with one implicit NUL. + strings->append(0, errorCode); + int32_t newIndex = strings->length(); + strings->appendInvariantChars(s, errorCode); + uhash_puti(&map, const_cast(p), newIndex, &errorCode); + return newIndex; + } + + void freeze() { isFrozen = true; } + + /** + * Returns a string pointer for its unique number, if this object is frozen. + * Otherwise nullptr. + */ + const char *get(int32_t i) const { + U_ASSERT(isFrozen); + return isFrozen && i > 0 ? strings->data() + i : nullptr; + } + +private: + UHashtable map; + CharString *strings; + bool isFrozen = false; +}; + +} // namespace + +LocaleDistanceData::LocaleDistanceData(LocaleDistanceData &&data) : + distanceTrieBytes(data.distanceTrieBytes), + regionToPartitions(data.regionToPartitions), + partitions(data.partitions), + paradigms(data.paradigms), paradigmsLength(data.paradigmsLength), + distances(data.distances) { + data.partitions = nullptr; + data.paradigms = nullptr; +} + +LocaleDistanceData::~LocaleDistanceData() { + uprv_free(partitions); + delete[] paradigms; +} + +// TODO(ICU-20777): Rename to just LikelySubtagsData. +struct XLikelySubtagsData { + UResourceBundle *langInfoBundle = nullptr; + UniqueCharStrings strings; + CharStringMap languageAliases; + CharStringMap regionAliases; + const uint8_t *trieBytes = nullptr; + LSR *lsrs = nullptr; + int32_t lsrsLength = 0; + + LocaleDistanceData distanceData; + + XLikelySubtagsData(UErrorCode &errorCode) : strings(errorCode) {} + + ~XLikelySubtagsData() { + ures_close(langInfoBundle); + delete[] lsrs; + } + + void load(UErrorCode &errorCode) { + langInfoBundle = ures_openDirect(nullptr, "langInfo", &errorCode); + if (U_FAILURE(errorCode)) { return; } + StackUResourceBundle stackTempBundle; + ResourceDataValue value; + ures_getValueWithFallback(langInfoBundle, "likely", stackTempBundle.getAlias(), + value, errorCode); + ResourceTable likelyTable = value.getTable(errorCode); + if (U_FAILURE(errorCode)) { return; } + + // Read all strings in the resource bundle and convert them to invariant char *. + LocalMemory languageIndexes, regionIndexes, lsrSubtagIndexes; + int32_t languagesLength = 0, regionsLength = 0, lsrSubtagsLength = 0; + if (!readStrings(likelyTable, "languageAliases", value, + languageIndexes, languagesLength, errorCode) || + !readStrings(likelyTable, "regionAliases", value, + regionIndexes, regionsLength, errorCode) || + !readStrings(likelyTable, "lsrs", value, + lsrSubtagIndexes,lsrSubtagsLength, errorCode)) { + return; + } + if ((languagesLength & 1) != 0 || + (regionsLength & 1) != 0 || + (lsrSubtagsLength % 3) != 0) { + errorCode = U_INVALID_FORMAT_ERROR; + return; + } + if (lsrSubtagsLength == 0) { + errorCode = U_MISSING_RESOURCE_ERROR; + return; + } + + if (!likelyTable.findValue("trie", value)) { + errorCode = U_MISSING_RESOURCE_ERROR; + return; + } + int32_t length; + trieBytes = value.getBinary(length, errorCode); + if (U_FAILURE(errorCode)) { return; } + + // Also read distance/matcher data if available, + // to open & keep only one resource bundle pointer + // and to use one single UniqueCharStrings. + UErrorCode matchErrorCode = U_ZERO_ERROR; + ures_getValueWithFallback(langInfoBundle, "match", stackTempBundle.getAlias(), + value, matchErrorCode); + LocalMemory partitionIndexes, paradigmSubtagIndexes; + int32_t partitionsLength = 0, paradigmSubtagsLength = 0; + if (U_SUCCESS(matchErrorCode)) { + ResourceTable matchTable = value.getTable(errorCode); + if (U_FAILURE(errorCode)) { return; } + + if (matchTable.findValue("trie", value)) { + distanceData.distanceTrieBytes = value.getBinary(length, errorCode); + if (U_FAILURE(errorCode)) { return; } + } + + if (matchTable.findValue("regionToPartitions", value)) { + distanceData.regionToPartitions = value.getBinary(length, errorCode); + if (U_FAILURE(errorCode)) { return; } + if (length < LSR::REGION_INDEX_LIMIT) { + errorCode = U_INVALID_FORMAT_ERROR; + return; + } + } + + if (!readStrings(matchTable, "partitions", value, + partitionIndexes, partitionsLength, errorCode) || + !readStrings(matchTable, "paradigms", value, + paradigmSubtagIndexes, paradigmSubtagsLength, errorCode)) { + return; + } + if ((paradigmSubtagsLength % 3) != 0) { + errorCode = U_INVALID_FORMAT_ERROR; + return; + } + + if (matchTable.findValue("distances", value)) { + distanceData.distances = value.getIntVector(length, errorCode); + if (U_FAILURE(errorCode)) { return; } + if (length < 4) { // LocaleDistance IX_LIMIT + errorCode = U_INVALID_FORMAT_ERROR; + return; + } + } + } else if (matchErrorCode == U_MISSING_RESOURCE_ERROR) { + // ok for likely subtags + } else { // error other than missing resource + errorCode = matchErrorCode; + return; + } + + // Fetch & store invariant-character versions of strings + // only after we have collected and de-duplicated all of them. + strings.freeze(); + + languageAliases = CharStringMap(languagesLength / 2, errorCode); + for (int32_t i = 0; i < languagesLength; i += 2) { + languageAliases.put(strings.get(languageIndexes[i]), + strings.get(languageIndexes[i + 1]), errorCode); + } + + regionAliases = CharStringMap(regionsLength / 2, errorCode); + for (int32_t i = 0; i < regionsLength; i += 2) { + regionAliases.put(strings.get(regionIndexes[i]), + strings.get(regionIndexes[i + 1]), errorCode); + } + if (U_FAILURE(errorCode)) { return; } + + lsrsLength = lsrSubtagsLength / 3; + lsrs = new LSR[lsrsLength]; + if (lsrs == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + 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])); + } + + if (partitionsLength > 0) { + distanceData.partitions = static_cast( + uprv_malloc(partitionsLength * sizeof(const char *))); + if (distanceData.partitions == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + for (int32_t i = 0; i < partitionsLength; ++i) { + distanceData.partitions[i] = strings.get(partitionIndexes[i]); + } + } + + if (paradigmSubtagsLength > 0) { + distanceData.paradigmsLength = paradigmSubtagsLength / 3; + LSR *paradigms = new LSR[distanceData.paradigmsLength]; + if (paradigms == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + 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])); + } + distanceData.paradigms = paradigms; + } + } + +private: + bool readStrings(const ResourceTable &table, const char *key, ResourceValue &value, + LocalMemory &indexes, int32_t &length, UErrorCode &errorCode) { + if (table.findValue(key, value)) { + ResourceArray stringArray = value.getArray(errorCode); + if (U_FAILURE(errorCode)) { return false; } + length = stringArray.getSize(); + if (length == 0) { return true; } + int32_t *rawIndexes = indexes.allocateInsteadAndCopy(length); + if (rawIndexes == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return false; + } + for (int i = 0; i < length; ++i) { + stringArray.getValue(i, value); // returns TRUE because i < length + rawIndexes[i] = strings.add(value.getUnicodeString(errorCode), errorCode); + if (U_FAILURE(errorCode)) { return false; } + } + } + return true; + } +}; + +namespace { + +XLikelySubtags *gLikelySubtags = nullptr; +UInitOnce gInitOnce = U_INITONCE_INITIALIZER; + +UBool U_CALLCONV cleanup() { + delete gLikelySubtags; + gLikelySubtags = nullptr; + gInitOnce.reset(); + return TRUE; +} + +} // namespace + +void U_CALLCONV XLikelySubtags::initLikelySubtags(UErrorCode &errorCode) { + // This function is invoked only via umtx_initOnce(). + U_ASSERT(gLikelySubtags == nullptr); + XLikelySubtagsData data(errorCode); + data.load(errorCode); + if (U_FAILURE(errorCode)) { return; } + gLikelySubtags = new XLikelySubtags(data); + if (gLikelySubtags == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + ucln_common_registerCleanup(UCLN_COMMON_LIKELY_SUBTAGS, cleanup); +} + +const XLikelySubtags *XLikelySubtags::getSingleton(UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return nullptr; } + umtx_initOnce(gInitOnce, &XLikelySubtags::initLikelySubtags, errorCode); + return gLikelySubtags; +} + +XLikelySubtags::XLikelySubtags(XLikelySubtagsData &data) : + langInfoBundle(data.langInfoBundle), + strings(data.strings.orphanCharStrings()), + languageAliases(std::move(data.languageAliases)), + regionAliases(std::move(data.regionAliases)), + trie(data.trieBytes), + lsrs(data.lsrs), +#if U_DEBUG + lsrsLength(data.lsrsLength), +#endif + distanceData(std::move(data.distanceData)) { + data.langInfoBundle = nullptr; + data.lsrs = nullptr; + + // Cache the result of looking up language="und" encoded as "*", and "und-Zzzz" ("**"). + UStringTrieResult result = trie.next(u'*'); + U_ASSERT(USTRINGTRIE_HAS_NEXT(result)); + trieUndState = trie.getState64(); + result = trie.next(u'*'); + U_ASSERT(USTRINGTRIE_HAS_NEXT(result)); + trieUndZzzzState = trie.getState64(); + result = trie.next(u'*'); + U_ASSERT(USTRINGTRIE_HAS_VALUE(result)); + defaultLsrIndex = trie.getValue(); + trie.reset(); + + for (char16_t c = u'a'; c <= u'z'; ++c) { + result = trie.next(c); + if (result == USTRINGTRIE_NO_VALUE) { + trieFirstLetterStates[c - u'a'] = trie.getState64(); + } + trie.reset(); + } +} + +XLikelySubtags::~XLikelySubtags() { + ures_close(langInfoBundle); + delete strings; + delete[] lsrs; +} + +LSR XLikelySubtags::makeMaximizedLsrFrom(const Locale &locale, UErrorCode &errorCode) const { + 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 makeMaximizedLsr(locale.getLanguage(), locale.getScript(), locale.getCountry(), + locale.getVariant(), errorCode); +} + +namespace { + +const char *getCanonical(const CharStringMap &aliases, const char *alias) { + const char *canonical = aliases.get(alias); + return canonical == nullptr ? alias : canonical; +} + +} // namespace + +LSR XLikelySubtags::makeMaximizedLsr(const char *language, const char *script, const char *region, + const char *variant, UErrorCode &errorCode) const { + // Handle pseudolocales like en-XA, ar-XB, fr-PSCRACK. + // They should match only themselves, + // not other locales with what looks like the same language and script subtags. + char c1; + if (region[0] == 'X' && (c1 = region[1]) != 0 && region[2] == 0) { + switch (c1) { + case 'A': + return LSR(PSEUDO_ACCENTS_PREFIX, language, script, region, errorCode); + case 'B': + return LSR(PSEUDO_BIDI_PREFIX, language, script, region, errorCode); + case 'C': + return LSR(PSEUDO_CRACKED_PREFIX, language, script, region, errorCode); + default: // normal locale + break; + } + } + + if (variant[0] == 'P' && variant[1] == 'S') { + if (uprv_strcmp(variant, "PSACCENT") == 0) { + return LSR(PSEUDO_ACCENTS_PREFIX, language, script, + *region == 0 ? "XA" : region, errorCode); + } else if (uprv_strcmp(variant, "PSBIDI") == 0) { + return LSR(PSEUDO_BIDI_PREFIX, language, script, + *region == 0 ? "XB" : region, errorCode); + } else if (uprv_strcmp(variant, "PSCRACK") == 0) { + return LSR(PSEUDO_CRACKED_PREFIX, language, script, + *region == 0 ? "XC" : region, errorCode); + } + // else normal locale + } + + language = getCanonical(languageAliases, language); + // (We have no script mappings.) + region = getCanonical(regionAliases, region); + return maximize(language, script, region); +} + +LSR XLikelySubtags::maximize(const char *language, const char *script, const char *region) const { + if (uprv_strcmp(language, "und") == 0) { + language = ""; + } + if (uprv_strcmp(script, "Zzzz") == 0) { + script = ""; + } + if (uprv_strcmp(region, "ZZ") == 0) { + region = ""; + } + if (*script != 0 && *region != 0 && *language != 0) { + return LSR(language, script, region); // already maximized + } + + uint32_t retainOldMask = 0; + 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) { + if (*language != 0) { + retainOldMask |= 4; + } + state = iter.getState64(); + } else { + retainOldMask |= 4; + iter.resetToState64(trieUndState); // "und" ("*") + state = 0; + } + + if (value > 0) { + // Intermediate or final value from just language. + if (value == SKIP_SCRIPT) { + value = 0; + } + if (*script != 0) { + retainOldMask |= 2; + } + } else { + value = trieNext(iter, script, 0); + if (value >= 0) { + if (*script != 0) { + retainOldMask |= 2; + } + state = iter.getState64(); + } else { + retainOldMask |= 2; + 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. + if (*region != 0) { + retainOldMask |= 1; + } + } else { + value = trieNext(iter, region, 0); + if (value >= 0) { + if (*region != 0) { + retainOldMask |= 1; + } + } else { + retainOldMask |= 1; + if (state == 0) { + value = defaultLsrIndex; + } else { + iter.resetToState64(state); + value = trieNext(iter, "", 0); + U_ASSERT(value > 0); + } + } + } + U_ASSERT(value < lsrsLength); + const LSR &result = lsrs[value]; + + if (*language == 0) { + language = "und"; + } + + 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); + } + if ((retainOldMask & 4) == 0) { + language = result.language; + } + if ((retainOldMask & 2) == 0) { + script = result.script; + } + if ((retainOldMask & 1) == 0) { + region = result.region; + } + return LSR(language, script, region); +} + +int32_t XLikelySubtags::trieNext(BytesTrie &iter, const char *s, int32_t i) { + UStringTrieResult result; + uint8_t c; + if ((c = s[i]) == 0) { + result = iter.next(u'*'); + } else { + for (;;) { + c = uprv_invCharToAscii(c); + // EBCDIC: If s[i] is not an invariant character, + // then c is now 0 and will simply not match anything, which is harmless. + uint8_t next = s[++i]; + if (next != 0) { + if (!USTRINGTRIE_HAS_NEXT(iter.next(c))) { + return -1; + } + } else { + // last character of this subtag + result = iter.next(c | 0x80); + break; + } + c = next; + } + } + switch (result) { + case USTRINGTRIE_NO_MATCH: return -1; + case USTRINGTRIE_NO_VALUE: return 0; + case USTRINGTRIE_INTERMEDIATE_VALUE: + U_ASSERT(iter.getValue() == SKIP_SCRIPT); + return SKIP_SCRIPT; + case USTRINGTRIE_FINAL_VALUE: return iter.getValue(); + default: return -1; + } +} + +// 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. +#if 0 +LSR XLikelySubtags::minimizeSubtags(const char *languageIn, const char *scriptIn, + const char *regionIn, ULocale.Minimize fieldToFavor, + UErrorCode &errorCode) const { + LSR result = maximize(languageIn, scriptIn, regionIn); + + // We could try just a series of checks, like: + // LSR result2 = addLikelySubtags(languageIn, "", ""); + // if result.equals(result2) return result2; + // However, we can optimize 2 of the cases: + // (languageIn, "", "") + // (languageIn, "", regionIn) + + // value00 = lookup(result.language, "", "") + BytesTrie iter = new BytesTrie(trie); + int value = trieNext(iter, result.language, 0); + U_ASSERT(value >= 0); + if (value == 0) { + value = trieNext(iter, "", 0); + U_ASSERT(value >= 0); + if (value == 0) { + value = trieNext(iter, "", 0); + } + } + U_ASSERT(value > 0); + LSR value00 = lsrs[value]; + boolean favorRegionOk = false; + if (result.script.equals(value00.script)) { //script is default + if (result.region.equals(value00.region)) { + return new LSR(result.language, "", ""); + } else if (fieldToFavor == ULocale.Minimize.FAVOR_REGION) { + return new LSR(result.language, "", result.region); + } else { + favorRegionOk = true; + } + } + + // The last case is not as easy to optimize. + // 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, ""); + } else if (favorRegionOk) { + return new LSR(result.language, "", result.region); + } + return result; +} +#endif + +U_NAMESPACE_END diff --git a/deps/icu-small/source/common/loclikelysubtags.h b/deps/icu-small/source/common/loclikelysubtags.h new file mode 100644 index 00000000000000..8c8a08ac5e314e --- /dev/null +++ b/deps/icu-small/source/common/loclikelysubtags.h @@ -0,0 +1,143 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// loclikelysubtags.h +// created: 2019may08 Markus W. Scherer + +#ifndef __LOCLIKELYSUBTAGS_H__ +#define __LOCLIKELYSUBTAGS_H__ + +#include +#include "unicode/utypes.h" +#include "unicode/bytestrie.h" +#include "unicode/locid.h" +#include "unicode/uobject.h" +#include "unicode/ures.h" +#include "lsr.h" +#include "uhash.h" + +U_NAMESPACE_BEGIN + +struct XLikelySubtagsData; + +/** + * Map of const char * keys & values. + * Stores pointers as is: Does not own/copy/adopt/release strings. + */ +class CharStringMap final : public UMemory { +public: + /** Constructs an unusable non-map. */ + CharStringMap() : map(nullptr) {} + CharStringMap(int32_t size, UErrorCode &errorCode) { + map = uhash_openSize(uhash_hashChars, uhash_compareChars, uhash_compareChars, + size, &errorCode); + } + CharStringMap(CharStringMap &&other) U_NOEXCEPT : map(other.map) { + other.map = nullptr; + } + CharStringMap(const CharStringMap &other) = delete; + ~CharStringMap() { + uhash_close(map); + } + + CharStringMap &operator=(CharStringMap &&other) U_NOEXCEPT { + map = other.map; + other.map = nullptr; + return *this; + } + CharStringMap &operator=(const CharStringMap &other) = delete; + + const char *get(const char *key) const { return static_cast(uhash_get(map, key)); } + void put(const char *key, const char *value, UErrorCode &errorCode) { + uhash_put(map, const_cast(key), const_cast(value), &errorCode); + } + +private: + UHashtable *map; +}; + +struct LocaleDistanceData { + LocaleDistanceData() = default; + LocaleDistanceData(LocaleDistanceData &&data); + ~LocaleDistanceData(); + + const uint8_t *distanceTrieBytes = nullptr; + const uint8_t *regionToPartitions = nullptr; + const char **partitions = nullptr; + const LSR *paradigms = nullptr; + int32_t paradigmsLength = 0; + const int32_t *distances = nullptr; + +private: + LocaleDistanceData &operator=(const LocaleDistanceData &) = delete; +}; + +// TODO(ICU-20777): Rename to just LikelySubtags. +class XLikelySubtags final : public UMemory { +public: + ~XLikelySubtags(); + + static constexpr int32_t SKIP_SCRIPT = 1; + + // VisibleForTesting + static const XLikelySubtags *getSingleton(UErrorCode &errorCode); + + // VisibleForTesting + LSR makeMaximizedLsrFrom(const Locale &locale, UErrorCode &errorCode) 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. +#if 0 + LSR minimizeSubtags(const char *languageIn, const char *scriptIn, const char *regionIn, + ULocale.Minimize fieldToFavor, UErrorCode &errorCode) const; +#endif + + // visible for LocaleDistance + const LocaleDistanceData &getDistanceData() const { return distanceData; } + +private: + XLikelySubtags(XLikelySubtagsData &data); + XLikelySubtags(const XLikelySubtags &other) = delete; + XLikelySubtags &operator=(const XLikelySubtags &other) = delete; + + static void initLikelySubtags(UErrorCode &errorCode); + + LSR makeMaximizedLsr(const char *language, const char *script, const char *region, + const char *variant, UErrorCode &errorCode) const; + + /** + * Raw access to addLikelySubtags. Input must be in canonical format, eg "en", not "eng" or "EN". + */ + LSR maximize(const char *language, const char *script, const char *region) const; + + static int32_t trieNext(BytesTrie &iter, const char *s, int32_t i); + + UResourceBundle *langInfoBundle; + // We could store the strings by value, except that if there were few enough strings, + // moving the contents could copy it to a different array, + // invalidating the pointers stored in the maps. + CharString *strings; + CharStringMap languageAliases; + CharStringMap regionAliases; + + // The trie maps each lang+script+region (encoded in ASCII) to an index into lsrs. + // There is also a trie value for each intermediate lang and lang+script. + // '*' is used instead of "und", "Zzzz"/"" and "ZZ"/"". + BytesTrie trie; + uint64_t trieUndState; + uint64_t trieUndZzzzState; + int32_t defaultLsrIndex; + uint64_t trieFirstLetterStates[26]; + const LSR *lsrs; +#if U_DEBUG + int32_t lsrsLength; +#endif + + // distance/matcher data: see comment in XLikelySubtagsData::load() + LocaleDistanceData distanceData; +}; + +U_NAMESPACE_END + +#endif // __LOCLIKELYSUBTAGS_H__ diff --git a/deps/icu-small/source/common/lsr.cpp b/deps/icu-small/source/common/lsr.cpp new file mode 100644 index 00000000000000..0c28eeda1bc7b6 --- /dev/null +++ b/deps/icu-small/source/common/lsr.cpp @@ -0,0 +1,101 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// lsr.cpp +// created: 2019may08 Markus W. Scherer + +#include "unicode/utypes.h" +#include "charstr.h" +#include "cmemory.h" +#include "cstring.h" +#include "lsr.h" +#include "uinvchar.h" +#include "ustr_imp.h" + +U_NAMESPACE_BEGIN + +LSR::LSR(char prefix, const char *lang, const char *scr, const char *r, UErrorCode &errorCode) : + language(nullptr), script(nullptr), region(r), + regionIndex(indexForRegion(region)) { + if (U_SUCCESS(errorCode)) { + CharString langScript; + langScript.append(prefix, errorCode).append(lang, errorCode).append('\0', errorCode); + int32_t scriptOffset = langScript.length(); + langScript.append(prefix, errorCode).append(scr, errorCode); + owned = langScript.cloneData(errorCode); + if (U_SUCCESS(errorCode)) { + language = owned; + script = owned + scriptOffset; + } + } +} + +LSR::LSR(LSR &&other) U_NOEXCEPT : + language(other.language), script(other.script), region(other.region), owned(other.owned), + regionIndex(other.regionIndex), hashCode(other.hashCode) { + if (owned != nullptr) { + other.language = other.script = ""; + other.owned = nullptr; + other.hashCode = 0; + } +} + +void LSR::deleteOwned() { + uprv_free(owned); +} + +LSR &LSR::operator=(LSR &&other) U_NOEXCEPT { + this->~LSR(); + language = other.language; + script = other.script; + region = other.region; + regionIndex = other.regionIndex; + owned = other.owned; + hashCode = other.hashCode; + if (owned != nullptr) { + other.language = other.script = ""; + other.owned = nullptr; + other.hashCode = 0; + } + return *this; +} + +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); +} + +int32_t LSR::indexForRegion(const char *region) { + int32_t c = region[0]; + int32_t a = c - '0'; + if (0 <= a && a <= 9) { // digits: "419" + int32_t b = region[1] - '0'; + if (b < 0 || 9 < b) { return 0; } + c = region[2] - '0'; + if (c < 0 || 9 < c || region[3] != 0) { return 0; } + return (10 * a + b) * 10 + c + 1; + } else { // letters: "DE" + a = uprv_upperOrdinal(c); + if (a < 0 || 25 < a) { return 0; } + int32_t b = uprv_upperOrdinal(region[1]); + if (b < 0 || 25 < b || region[2] != 0) { return 0; } + return 26 * a + b + 1001; + } + return 0; +} + +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; + } + return *this; +} + +U_NAMESPACE_END diff --git a/deps/icu-small/source/common/lsr.h b/deps/icu-small/source/common/lsr.h new file mode 100644 index 00000000000000..db6cf938f47d02 --- /dev/null +++ b/deps/icu-small/source/common/lsr.h @@ -0,0 +1,72 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// lsr.h +// created: 2019may08 Markus W. Scherer + +#ifndef __LSR_H__ +#define __LSR_H__ + +#include "unicode/utypes.h" +#include "unicode/uobject.h" +#include "cstring.h" + +U_NAMESPACE_BEGIN + +struct LSR final : public UMemory { + static constexpr int32_t REGION_INDEX_LIMIT = 1001 + 26 * 26; + + 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; + /** 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) : + language(lang), script(scr), region(r), + regionIndex(indexForRegion(region)) {} + /** + * 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(LSR &&other) U_NOEXCEPT; + LSR(const LSR &other) = delete; + inline ~LSR() { + // Pure inline code for almost all instances. + if (owned != nullptr) { + deleteOwned(); + } + } + + LSR &operator=(LSR &&other) U_NOEXCEPT; + LSR &operator=(const LSR &other) = delete; + + /** + * Returns a positive index (>0) for a well-formed region code. + * Do not rely on a particular region->index mapping; it may change. + * Returns 0 for ill-formed strings. + */ + static int32_t indexForRegion(const char *region); + + UBool operator==(const LSR &other) const; + + inline UBool operator!=(const LSR &other) const { + return !operator==(other); + } + + LSR &setHashCode(); + +private: + void deleteOwned(); +}; + +U_NAMESPACE_END + +#endif // __LSR_H__ diff --git a/deps/icu-small/source/common/mutex.h b/deps/icu-small/source/common/mutex.h index 5223397bbcc10a..44b1f90ba04dd2 100644 --- a/deps/icu-small/source/common/mutex.h +++ b/deps/icu-small/source/common/mutex.h @@ -28,50 +28,48 @@ U_NAMESPACE_BEGIN -//---------------------------------------------------------------------------- -// Code within that accesses shared static or global data should -// should instantiate a Mutex object while doing so. You should make your own -// private mutex where possible. - -// For example: -// -// UMutex myMutex = U_MUTEX_INITIALIZER; -// -// void Function(int arg1, int arg2) -// { -// static Object* foo; // Shared read-write object -// Mutex mutex(&myMutex); // or no args for the global lock -// foo->Method(); -// // When 'mutex' goes out of scope and gets destroyed here, the lock is released -// } -// -// Note: Do NOT use the form 'Mutex mutex();' as that merely forward-declares a function -// returning a Mutex. This is a common mistake which silently slips through the -// compiler!! -// +/** + * Mutex is a helper class for convenient locking and unlocking of a UMutex. + * + * Creating a local scope Mutex will lock a UMutex, holding the lock until the Mutex + * goes out of scope. + * + * If no UMutex is specified, the ICU global mutex is implied. + * + * For example: + * + * static UMutex myMutex; + * + * void Function(int arg1, int arg2) + * { + * static Object* foo; // Shared read-write object + * Mutex mutex(&myMutex); // or no args for the global lock + * foo->Method(); + * // When 'mutex' goes out of scope and gets destroyed here, the lock is released + * } + * + * Note: Do NOT use the form 'Mutex mutex();' as that merely forward-declares a function + * returning a Mutex. This is a common mistake which silently slips through the + * compiler!! + */ class U_COMMON_API Mutex : public UMemory { public: - inline Mutex(UMutex *mutex = NULL); - inline ~Mutex(); + Mutex(UMutex *mutex = nullptr) : fMutex(mutex) { + umtx_lock(fMutex); + } + ~Mutex() { + umtx_unlock(fMutex); + } -private: - UMutex *fMutex; + Mutex(const Mutex &other) = delete; // forbid assigning of this class + Mutex &operator=(const Mutex &other) = delete; // forbid copying of this class + void *operator new(size_t s) = delete; // forbid heap allocation. Locals only. - Mutex(const Mutex &other); // forbid copying of this class - Mutex &operator=(const Mutex &other); // forbid copying of this class +private: + UMutex *fMutex; }; -inline Mutex::Mutex(UMutex *mutex) - : fMutex(mutex) -{ - umtx_lock(fMutex); -} - -inline Mutex::~Mutex() -{ - umtx_unlock(fMutex); -} U_NAMESPACE_END diff --git a/deps/icu-small/source/common/normalizer2impl.h b/deps/icu-small/source/common/normalizer2impl.h index 7ecdef6d9c8032..cf3015ea881bfc 100644 --- a/deps/icu-small/source/common/normalizer2impl.h +++ b/deps/icu-small/source/common/normalizer2impl.h @@ -245,9 +245,7 @@ class U_COMMON_API ReorderingBuffer : public UMemory { */ class U_COMMON_API Normalizer2Impl : public UObject { public: - Normalizer2Impl() : normTrie(NULL), fCanonIterData(NULL) { - fCanonIterDataInitOnce.reset(); - } + Normalizer2Impl() : normTrie(NULL), fCanonIterData(NULL) { } virtual ~Normalizer2Impl(); void init(const int32_t *inIndexes, const UCPTrie *inTrie, @@ -723,7 +721,7 @@ class U_COMMON_API Normalizer2Impl : public UObject { const uint16_t *extraData; // mappings and/or compositions for yesYes, yesNo & noNo characters const uint8_t *smallFCD; // [0x100] one bit per 32 BMP code points, set if any FCD!=0 - UInitOnce fCanonIterDataInitOnce; + UInitOnce fCanonIterDataInitOnce = U_INITONCE_INITIALIZER; CanonIterData *fCanonIterData; }; diff --git a/deps/icu-small/source/common/putil.cpp b/deps/icu-small/source/common/putil.cpp index e105befc3fc740..207350f8f26120 100644 --- a/deps/icu-small/source/common/putil.cpp +++ b/deps/icu-small/source/common/putil.cpp @@ -249,7 +249,7 @@ static UDate getUTCtime_real() { } static UDate getUTCtime_fake() { - static UMutex fakeClockMutex = U_MUTEX_INTIALIZER; + static UMutex fakeClockMutex; umtx_lock(&fakeClockMutex); if(!fakeClock_set) { UDate real = getUTCtime_real(); @@ -1315,11 +1315,10 @@ uprv_pathIsAbsolute(const char *path) # endif #endif -#if U_PLATFORM_HAS_WINUWP_API != 0 +#if defined(ICU_DATA_DIR_WINDOWS) // Helper function to get the ICU Data Directory under the Windows directory location. static BOOL U_CALLCONV getIcuDataDirectoryUnderWindowsDirectory(char* directoryBuffer, UINT bufferLength) { -#if defined(ICU_DATA_DIR_WINDOWS) wchar_t windowsPath[MAX_PATH]; char windowsPathUtf8[MAX_PATH]; @@ -1346,7 +1345,6 @@ static BOOL U_CALLCONV getIcuDataDirectoryUnderWindowsDirectory(char* directoryB } } } -#endif return FALSE; } @@ -1380,9 +1378,9 @@ static void U_CALLCONV dataDirectoryInitFn() { */ # if !defined(ICU_NO_USER_DATA_OVERRIDE) && !UCONFIG_NO_FILE_IO /* First try to get the environment variable */ -# if U_PLATFORM_HAS_WINUWP_API == 0 // Windows UWP does not support getenv +# if U_PLATFORM_HAS_WINUWP_API == 0 // Windows UWP does not support getenv path=getenv("ICU_DATA"); -# endif +# endif # endif /* ICU_DATA_DIR may be set as a compile option. @@ -1411,7 +1409,7 @@ static void U_CALLCONV dataDirectoryInitFn() { } #endif -#if U_PLATFORM_HAS_WINUWP_API != 0 && defined(ICU_DATA_DIR_WINDOWS) +#if defined(ICU_DATA_DIR_WINDOWS) char datadir_path_buffer[MAX_PATH]; if (getIcuDataDirectoryUnderWindowsDirectory(datadir_path_buffer, UPRV_LENGTHOF(datadir_path_buffer))) { path = datadir_path_buffer; @@ -1461,12 +1459,17 @@ static void U_CALLCONV TimeZoneDataDirInitFn(UErrorCode &status) { const char *dir = ""; -#if U_PLATFORM_HAS_WINUWP_API != 0 - // The UWP version does not support the environment variable setting, but can possibly pick them up from the Windows directory. +#if U_PLATFORM_HAS_WINUWP_API == 1 +// The UWP version does not support the environment variable setting. + +# if defined(ICU_DATA_DIR_WINDOWS) + // When using the Windows system data, we can possibly pick up time zone data from the Windows directory. char datadir_path_buffer[MAX_PATH]; if (getIcuDataDirectoryUnderWindowsDirectory(datadir_path_buffer, UPRV_LENGTHOF(datadir_path_buffer))) { dir = datadir_path_buffer; } +# endif + #else dir = getenv("ICU_TIMEZONE_FILES_DIR"); #endif // U_PLATFORM_HAS_WINUWP_API @@ -1560,6 +1563,10 @@ static const char *uprv_getPOSIXIDForCategory(int category) { /* Nothing worked. Give it a nice POSIX default value. */ posixID = "en_US_POSIX"; + // Note: this test will not catch 'C.UTF-8', + // that will be handled in uprv_getDefaultLocaleID(). + // Leave this mapping here for the uprv_getPOSIXIDForDefaultCodepage() + // caller which expects to see "en_US_POSIX" in many branches. } return posixID; } @@ -1631,8 +1638,8 @@ The leftmost codepage (.xxx) wins. } // Copy the ID into owned memory. - // Over-allocate in case we replace "@" with "__". - char *correctedPOSIXLocale = static_cast(uprv_malloc(uprv_strlen(posixID) + 1 + 1)); + // Over-allocate in case we replace "C" with "en_US_POSIX" (+10), + null termination + char *correctedPOSIXLocale = static_cast(uprv_malloc(uprv_strlen(posixID) + 10 + 1)); if (correctedPOSIXLocale == nullptr) { return nullptr; } @@ -1641,9 +1648,16 @@ The leftmost codepage (.xxx) wins. char *limit; if ((limit = uprv_strchr(correctedPOSIXLocale, '.')) != nullptr) { *limit = 0; - if ((limit = uprv_strchr(correctedPOSIXLocale, '@')) != nullptr) { - *limit = 0; - } + } + if ((limit = uprv_strchr(correctedPOSIXLocale, '@')) != nullptr) { + *limit = 0; + } + + if ((uprv_strcmp("C", correctedPOSIXLocale) == 0) // no @ variant + || (uprv_strcmp("POSIX", correctedPOSIXLocale) == 0)) { + // Raw input was C.* or POSIX.*, Give it a nice POSIX default value. + // (The "C"/"POSIX" case is handled in uprv_getPOSIXIDForCategory()) + uprv_strcpy(correctedPOSIXLocale, "en_US_POSIX"); } /* Note that we scan the *uncorrected* ID. */ @@ -1668,7 +1682,7 @@ The leftmost codepage (.xxx) wins. if ((q = uprv_strchr(p, '.')) != nullptr) { /* How big will the resulting string be? */ int32_t len = (int32_t)(uprv_strlen(correctedPOSIXLocale) + (q-p)); - uprv_strncat(correctedPOSIXLocale, p, q-p); + uprv_strncat(correctedPOSIXLocale, p, q-p); // do not include charset correctedPOSIXLocale[len] = 0; } else { @@ -2053,7 +2067,7 @@ int_getDefaultCodepage() static char codepage[64]; DWORD codepageNumber = 0; -#if U_PLATFORM_HAS_WINUWP_API > 0 +#if U_PLATFORM_HAS_WINUWP_API == 1 // UWP doesn't have a direct API to get the default ACP as Microsoft would rather // have folks use Unicode than a "system" code page, however this is the same // codepage as the system default locale codepage. (FWIW, the system locale is diff --git a/deps/icu-small/source/common/putilimp.h b/deps/icu-small/source/common/putilimp.h index f9c13d8e1b27bf..2e9fbcc4837cd8 100644 --- a/deps/icu-small/source/common/putilimp.h +++ b/deps/icu-small/source/common/putilimp.h @@ -178,76 +178,6 @@ typedef size_t uintptr_t; /** @} */ -/*===========================================================================*/ -/** @{ GCC built in functions for atomic memory operations */ -/*===========================================================================*/ - -/** - * \def U_HAVE_GCC_ATOMICS - * @internal - */ -#ifdef U_HAVE_GCC_ATOMICS - /* Use the predefined value. */ -#elif U_PLATFORM == U_PF_MINGW - #define U_HAVE_GCC_ATOMICS 0 -#elif U_GCC_MAJOR_MINOR >= 404 || defined(__clang__) - /* TODO: Intel icc and IBM xlc on AIX also support gcc atomics. (Intel originated them.) - * Add them for these compilers. - * Note: Clang sets __GNUC__ defines for version 4.2, so misses the 4.4 test here. - */ -# define U_HAVE_GCC_ATOMICS 1 -#else -# define U_HAVE_GCC_ATOMICS 0 -#endif - -/** @} */ - -/** - * \def U_HAVE_STD_ATOMICS - * Defines whether to use the C++11 std::atomic functions. - * If false, ICU will fall back to compiler or platform specific alternatives. - * Note: support for these fall back options for atomics will be removed in a future version - * of ICU, and the use of C++ 11 atomics will be required. - * @internal - */ -#ifdef U_HAVE_STD_ATOMICS - /* Use the predefined value. */ -#else -# define U_HAVE_STD_ATOMICS 1 -#endif - -/** - * \def U_HAVE_CLANG_ATOMICS - * Defines whether Clang c11 style built-in atomics are available. - * These are used in preference to gcc atomics when both are available. - */ -#ifdef U_HAVE_CLANG_ATOMICS - /* Use the predefined value. */ -#elif __has_builtin(__c11_atomic_load) && \ - __has_builtin(__c11_atomic_store) && \ - __has_builtin(__c11_atomic_fetch_add) && \ - __has_builtin(__c11_atomic_fetch_sub) -# define U_HAVE_CLANG_ATOMICS 1 -#else -# define U_HAVE_CLANG_ATOMICS 0 -#endif - - -/** - * \def U_HAVE_STD_MUTEX - * Defines whether to use the C++11 std::mutex functions. - * If false, ICU will fall back to compiler or platform specific alternatives. - * std::mutex is preferred, and used by default unless this setting is overridden. - * Note: support for other options for mutexes will be removed in a future version - * of ICU, and the use of std::mutex will be required. - * @internal - */ -#ifdef U_HAVE_STD_MUTEX - /* Use the predefined value. */ -#else -# define U_HAVE_STD_MUTEX 1 -#endif - /*===========================================================================*/ /** @{ Programs used by ICU code */ /*===========================================================================*/ diff --git a/deps/icu-small/source/common/rbbi.cpp b/deps/icu-small/source/common/rbbi.cpp index 3b116ffaf6cba7..01dae48de44c1d 100644 --- a/deps/icu-small/source/common/rbbi.cpp +++ b/deps/icu-small/source/common/rbbi.cpp @@ -323,8 +323,8 @@ void RuleBasedBreakIterator::init(UErrorCode &status) { // Virtual function: does the right thing with subclasses. // //----------------------------------------------------------------------------- -BreakIterator* -RuleBasedBreakIterator::clone(void) const { +RuleBasedBreakIterator* +RuleBasedBreakIterator::clone() const { return new RuleBasedBreakIterator(*this); } @@ -352,7 +352,7 @@ RuleBasedBreakIterator::operator==(const BreakIterator& that) const { // or have a different iteration position. // Note that fText's position is always the same as the break iterator's position. return FALSE; - }; + } if (!(fPosition == that2.fPosition && fRuleStatusIndex == that2.fRuleStatusIndex && @@ -1079,10 +1079,8 @@ const uint8_t *RuleBasedBreakIterator::getBinaryRules(uint32_t &length) { } -BreakIterator * RuleBasedBreakIterator::createBufferClone(void * /*stackBuffer*/, - int32_t &bufferSize, - UErrorCode &status) -{ +RuleBasedBreakIterator *RuleBasedBreakIterator::createBufferClone( + void * /*stackBuffer*/, int32_t &bufferSize, UErrorCode &status) { if (U_FAILURE(status)){ return NULL; } diff --git a/deps/icu-small/source/common/rbbi_cache.cpp b/deps/icu-small/source/common/rbbi_cache.cpp index 17ee2320802f60..4f9e83360a2a32 100644 --- a/deps/icu-small/source/common/rbbi_cache.cpp +++ b/deps/icu-small/source/common/rbbi_cache.cpp @@ -519,7 +519,7 @@ UBool RuleBasedBreakIterator::BreakCache::populatePreceding(UErrorCode &status) // The initial handleNext() only advanced by a single code point. Go again. position = fBI->handleNext(); // Safe rules identify safe pairs. } - }; + } positionStatusIdx = fBI->fRuleStatusIndex; } } while (position >= fromPosition); diff --git a/deps/icu-small/source/common/resbund.cpp b/deps/icu-small/source/common/resbund.cpp index 00dbf6f8fe2e9c..5ec7541b4db636 100644 --- a/deps/icu-small/source/common/resbund.cpp +++ b/deps/icu-small/source/common/resbund.cpp @@ -51,6 +51,7 @@ #include "unicode/utypes.h" #include "unicode/resbund.h" +#include "cmemory.h" #include "mutex.h" #include "uassert.h" #include "umutex.h" @@ -377,7 +378,7 @@ void ResourceBundle::getVersion(UVersionInfo versionInfo) const { } const Locale &ResourceBundle::getLocale(void) const { - static UMutex gLocaleLock = U_MUTEX_INITIALIZER; + static UMutex gLocaleLock; Mutex lock(&gLocaleLock); if (fLocale != NULL) { return *fLocale; diff --git a/deps/icu-small/source/common/resource.h b/deps/icu-small/source/common/resource.h index 3dbff785ef12a8..5199b858880770 100644 --- a/deps/icu-small/source/common/resource.h +++ b/deps/icu-small/source/common/resource.h @@ -28,6 +28,7 @@ #include "unicode/utypes.h" #include "unicode/unistr.h" #include "unicode/ures.h" +#include "restrace.h" struct ResourceData; @@ -47,8 +48,10 @@ class U_COMMON_API ResourceArray { ResourceArray() : items16(NULL), items32(NULL), length(0) {} /** Only for implementation use. @internal */ - ResourceArray(const uint16_t *i16, const uint32_t *i32, int32_t len) : - items16(i16), items32(i32), length(len) {} + ResourceArray(const uint16_t *i16, const uint32_t *i32, int32_t len, + const ResourceTracer& traceInfo) : + items16(i16), items32(i32), length(len), + fTraceInfo(traceInfo) {} /** * @return The number of items in the array resource. @@ -68,6 +71,7 @@ class U_COMMON_API ResourceArray { const uint16_t *items16; const uint32_t *items32; int32_t length; + ResourceTracer fTraceInfo; }; /** @@ -80,27 +84,37 @@ class U_COMMON_API ResourceTable { /** Only for implementation use. @internal */ ResourceTable(const uint16_t *k16, const int32_t *k32, - const uint16_t *i16, const uint32_t *i32, int32_t len) : - keys16(k16), keys32(k32), items16(i16), items32(i32), length(len) {} + const uint16_t *i16, const uint32_t *i32, int32_t len, + const ResourceTracer& traceInfo) : + keys16(k16), keys32(k32), items16(i16), items32(i32), length(len), + fTraceInfo(traceInfo) {} /** * @return The number of items in the array resource. */ int32_t getSize() const { return length; } /** - * @param i Array item index. + * @param i Table item index. * @param key Output-only, receives the key of the i'th item. * @param value Output-only, receives the value of the i'th item. * @return TRUE if i is non-negative and less than getSize(). */ UBool getKeyAndValue(int32_t i, const char *&key, ResourceValue &value) const; + /** + * @param key Key string to find in the table. + * @param value Output-only, receives the value of the item with that key. + * @return TRUE if the table contains the key. + */ + UBool findValue(const char *key, ResourceValue &value) const; + private: const uint16_t *keys16; const int32_t *keys32; const uint16_t *items16; const uint32_t *items32; int32_t length; + ResourceTracer fTraceInfo; }; /** diff --git a/deps/icu-small/source/common/restrace.cpp b/deps/icu-small/source/common/restrace.cpp new file mode 100644 index 00000000000000..5c6498850e2f8f --- /dev/null +++ b/deps/icu-small/source/common/restrace.cpp @@ -0,0 +1,130 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if U_ENABLE_TRACING + +#include "restrace.h" +#include "charstr.h" +#include "cstring.h" +#include "utracimp.h" +#include "uresimp.h" +#include "uassert.h" +#include "util.h" + +U_NAMESPACE_BEGIN + +ResourceTracer::~ResourceTracer() = default; + +void ResourceTracer::trace(const char* resType) const { + U_ASSERT(fResB || fParent); + UTRACE_ENTRY(UTRACE_UDATA_RESOURCE); + UErrorCode status = U_ZERO_ERROR; + + CharString filePath; + getFilePath(filePath, status); + + CharString resPath; + getResPath(resPath, status); + + // The longest type ("intvector") is 9 chars + const char kSpaces[] = " "; + CharString format; + format.append(kSpaces, sizeof(kSpaces) - 1 - uprv_strlen(resType), status); + format.append("(%s) %s @ %s", status); + + UTRACE_DATA3(UTRACE_VERBOSE, + format.data(), + resType, + filePath.data(), + resPath.data()); + UTRACE_EXIT_STATUS(status); +} + +void ResourceTracer::traceOpen() const { + U_ASSERT(fResB); + UTRACE_ENTRY(UTRACE_UDATA_BUNDLE); + UErrorCode status = U_ZERO_ERROR; + + CharString filePath; + UTRACE_DATA1(UTRACE_VERBOSE, "%s", getFilePath(filePath, status).data()); + UTRACE_EXIT_STATUS(status); +} + +CharString& ResourceTracer::getFilePath(CharString& output, UErrorCode& status) const { + if (fResB) { + output.append(fResB->fData->fPath, status); + output.append('/', status); + output.append(fResB->fData->fName, status); + output.append(".res", status); + } else { + fParent->getFilePath(output, status); + } + return output; +} + +CharString& ResourceTracer::getResPath(CharString& output, UErrorCode& status) const { + if (fResB) { + output.append('/', status); + output.append(fResB->fResPath, status); + // removing the trailing / + U_ASSERT(output[output.length()-1] == '/'); + output.truncate(output.length()-1); + } else { + fParent->getResPath(output, status); + } + if (fKey) { + output.append('/', status); + output.append(fKey, status); + } + if (fIndex != -1) { + output.append('[', status); + UnicodeString indexString; + ICU_Utility::appendNumber(indexString, fIndex); + output.appendInvariantChars(indexString, status); + output.append(']', status); + } + return output; +} + +void FileTracer::traceOpen(const char* path, const char* type, const char* name) { + if (uprv_strcmp(type, "res") == 0) { + traceOpenResFile(path, name); + } else { + traceOpenDataFile(path, type, name); + } +} + +void FileTracer::traceOpenDataFile(const char* path, const char* type, const char* name) { + UTRACE_ENTRY(UTRACE_UDATA_DATA_FILE); + UErrorCode status = U_ZERO_ERROR; + + CharString filePath; + filePath.append(path, status); + filePath.append('/', status); + filePath.append(name, status); + filePath.append('.', status); + filePath.append(type, status); + + UTRACE_DATA1(UTRACE_VERBOSE, "%s", filePath.data()); + UTRACE_EXIT_STATUS(status); +} + +void FileTracer::traceOpenResFile(const char* path, const char* name) { + UTRACE_ENTRY(UTRACE_UDATA_RES_FILE); + UErrorCode status = U_ZERO_ERROR; + + CharString filePath; + filePath.append(path, status); + filePath.append('/', status); + filePath.append(name, status); + filePath.append(".res", status); + + UTRACE_DATA1(UTRACE_VERBOSE, "%s", filePath.data()); + UTRACE_EXIT_STATUS(status); +} + +U_NAMESPACE_END + +#endif // U_ENABLE_TRACING diff --git a/deps/icu-small/source/common/restrace.h b/deps/icu-small/source/common/restrace.h new file mode 100644 index 00000000000000..ef29eaed578107 --- /dev/null +++ b/deps/icu-small/source/common/restrace.h @@ -0,0 +1,147 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#ifndef __RESTRACE_H__ +#define __RESTRACE_H__ + +#include "unicode/utypes.h" + +#if U_ENABLE_TRACING + +struct UResourceBundle; + +U_NAMESPACE_BEGIN + +class CharString; + +/** + * Instances of this class store information used to trace reads from resource + * bundles when ICU is built with --enable-tracing. + * + * All arguments of type const UResourceBundle*, const char*, and + * const ResourceTracer& are stored as pointers. The caller must retain + * ownership for the lifetime of this ResourceTracer. + * + * Exported as U_COMMON_API for Windows because it is a value field + * in other exported types. + */ +class U_COMMON_API ResourceTracer { +public: + ResourceTracer() : + fResB(nullptr), + fParent(nullptr), + fKey(nullptr), + fIndex(-1) {} + + ResourceTracer(const UResourceBundle* resB) : + fResB(resB), + fParent(nullptr), + fKey(nullptr), + fIndex(-1) {} + + ResourceTracer(const UResourceBundle* resB, const char* key) : + fResB(resB), + fParent(nullptr), + fKey(key), + fIndex(-1) {} + + ResourceTracer(const UResourceBundle* resB, int32_t index) : + fResB(resB), + fParent(nullptr), + fKey(nullptr), + fIndex(index) {} + + ResourceTracer(const ResourceTracer& parent, const char* key) : + fResB(nullptr), + fParent(&parent), + fKey(key), + fIndex(-1) {} + + ResourceTracer(const ResourceTracer& parent, int32_t index) : + fResB(nullptr), + fParent(&parent), + fKey(nullptr), + fIndex(index) {} + + ~ResourceTracer(); + + void trace(const char* type) const; + void traceOpen() const; + + /** + * Calls trace() if the resB or parent provided to the constructor was + * non-null; otherwise, does nothing. + */ + void maybeTrace(const char* type) const { + if (fResB || fParent) { + trace(type); + } + } + +private: + const UResourceBundle* fResB; + const ResourceTracer* fParent; + const char* fKey; + int32_t fIndex; + + CharString& getFilePath(CharString& output, UErrorCode& status) const; + + CharString& getResPath(CharString& output, UErrorCode& status) const; +}; + +/** + * This class provides methods to trace data file reads when ICU is built + * with --enable-tracing. + */ +class FileTracer { +public: + static void traceOpen(const char* path, const char* type, const char* name); + +private: + static void traceOpenDataFile(const char* path, const char* type, const char* name); + static void traceOpenResFile(const char* path, const char* name); +}; + +U_NAMESPACE_END + +#else // U_ENABLE_TRACING + +U_NAMESPACE_BEGIN + +/** + * Default trivial implementation when --enable-tracing is not used. + */ +class U_COMMON_API ResourceTracer { +public: + ResourceTracer() {} + + ResourceTracer(const void*) {} + + ResourceTracer(const void*, const char*) {} + + ResourceTracer(const void*, int32_t) {} + + ResourceTracer(const ResourceTracer&, const char*) {} + + ResourceTracer(const ResourceTracer&, int32_t) {} + + void trace(const char*) const {} + + void traceOpen() const {} + + void maybeTrace(const char*) const {} +}; + +/** + * Default trivial implementation when --enable-tracing is not used. + */ +class FileTracer { +public: + static void traceOpen(const char*, const char*, const char*) {} +}; + +U_NAMESPACE_END + +#endif // U_ENABLE_TRACING + +#endif //__RESTRACE_H__ diff --git a/deps/icu-small/source/common/schriter.cpp b/deps/icu-small/source/common/schriter.cpp index f852800aaae6bd..17b68aee9d923a 100644 --- a/deps/icu-small/source/common/schriter.cpp +++ b/deps/icu-small/source/common/schriter.cpp @@ -101,7 +101,7 @@ StringCharacterIterator::operator==(const ForwardCharacterIterator& that) const && end == realThat.end; } -CharacterIterator* +StringCharacterIterator* StringCharacterIterator::clone() const { return new StringCharacterIterator(*this); } diff --git a/deps/icu-small/source/common/serv.cpp b/deps/icu-small/source/common/serv.cpp index 40940740d02b45..044864b859c7e8 100644 --- a/deps/icu-small/source/common/serv.cpp +++ b/deps/icu-small/source/common/serv.cpp @@ -333,10 +333,7 @@ U_CDECL_END ****************************************************************** */ -static UMutex *lock() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex lock; ICUService::ICUService() : name() @@ -361,7 +358,7 @@ ICUService::ICUService(const UnicodeString& newName) ICUService::~ICUService() { { - Mutex mutex(lock()); + Mutex mutex(&lock); clearCaches(); delete factories; factories = NULL; @@ -452,7 +449,7 @@ ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUSer // if factory is not null, we're calling from within the mutex, // and since some unix machines don't have reentrant mutexes we // need to make sure not to try to lock it again. - XMutex mutex(lock(), factory != NULL); + XMutex mutex(&lock, factory != NULL); if (serviceCache == NULL) { ncthis->serviceCache = new Hashtable(status); @@ -618,7 +615,7 @@ ICUService::getVisibleIDs(UVector& result, const UnicodeString* matchID, UErrorC } { - Mutex mutex(lock()); + Mutex mutex(&lock); const Hashtable* map = getVisibleIDMap(status); if (map != NULL) { ICUServiceKey* fallbackKey = createKey(matchID, status); @@ -695,7 +692,7 @@ ICUService::getDisplayName(const UnicodeString& id, UnicodeString& result, const { { UErrorCode status = U_ZERO_ERROR; - Mutex mutex(lock()); + Mutex mutex(&lock); const Hashtable* map = getVisibleIDMap(status); if (map != NULL) { ICUServiceFactory* f = (ICUServiceFactory*)map->get(id); @@ -747,7 +744,7 @@ ICUService::getDisplayNames(UVector& result, result.setDeleter(userv_deleteStringPair); if (U_SUCCESS(status)) { ICUService* ncthis = (ICUService*)this; // cast away semantic const - Mutex mutex(lock()); + Mutex mutex(&lock); if (dnCache != NULL && dnCache->locale != locale) { delete dnCache; @@ -852,7 +849,7 @@ URegistryKey ICUService::registerFactory(ICUServiceFactory* factoryToAdopt, UErrorCode& status) { if (U_SUCCESS(status) && factoryToAdopt != NULL) { - Mutex mutex(lock()); + Mutex mutex(&lock); if (factories == NULL) { factories = new UVector(deleteUObject, NULL, status); @@ -883,7 +880,7 @@ ICUService::unregister(URegistryKey rkey, UErrorCode& status) ICUServiceFactory *factory = (ICUServiceFactory*)rkey; UBool result = FALSE; if (factory != NULL && factories != NULL) { - Mutex mutex(lock()); + Mutex mutex(&lock); if (factories->removeElement(factory)) { clearCaches(); @@ -903,7 +900,7 @@ void ICUService::reset() { { - Mutex mutex(lock()); + Mutex mutex(&lock); reInitializeFactories(); clearCaches(); } diff --git a/deps/icu-small/source/common/servls.cpp b/deps/icu-small/source/common/servls.cpp index 0b1b1b947d514e..0c2a73d98e2275 100644 --- a/deps/icu-small/source/common/servls.cpp +++ b/deps/icu-small/source/common/servls.cpp @@ -263,7 +263,7 @@ ICULocaleService::validateFallbackLocale() const { const Locale& loc = Locale::getDefault(); ICULocaleService* ncThis = (ICULocaleService*)this; - static UMutex llock = U_MUTEX_INITIALIZER; + static UMutex llock; { Mutex mutex(&llock); if (loc != fallbackLocale) { diff --git a/deps/icu-small/source/common/servnotf.cpp b/deps/icu-small/source/common/servnotf.cpp index 9b5997bd17f509..435f36b0d00671 100644 --- a/deps/icu-small/source/common/servnotf.cpp +++ b/deps/icu-small/source/common/servnotf.cpp @@ -21,10 +21,7 @@ U_NAMESPACE_BEGIN EventListener::~EventListener() {} UOBJECT_DEFINE_RTTI_IMPLEMENTATION(EventListener) -static UMutex *notifyLock() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex notifyLock; ICUNotifier::ICUNotifier(void) : listeners(NULL) @@ -33,7 +30,7 @@ ICUNotifier::ICUNotifier(void) ICUNotifier::~ICUNotifier(void) { { - Mutex lmx(notifyLock()); + Mutex lmx(¬ifyLock); delete listeners; listeners = NULL; } @@ -50,7 +47,7 @@ ICUNotifier::addListener(const EventListener* l, UErrorCode& status) } if (acceptsListener(*l)) { - Mutex lmx(notifyLock()); + Mutex lmx(¬ifyLock); if (listeners == NULL) { listeners = new UVector(5, status); } else { @@ -83,7 +80,7 @@ ICUNotifier::removeListener(const EventListener *l, UErrorCode& status) } { - Mutex lmx(notifyLock()); + Mutex lmx(¬ifyLock); if (listeners != NULL) { // identity equality check for (int i = 0, e = listeners->size(); i < e; ++i) { @@ -106,7 +103,7 @@ void ICUNotifier::notifyChanged(void) { if (listeners != NULL) { - Mutex lmx(notifyLock()); + Mutex lmx(¬ifyLock); if (listeners != NULL) { for (int i = 0, e = listeners->size(); i < e; ++i) { EventListener* el = (EventListener*)listeners->elementAt(i); diff --git a/deps/icu-small/source/common/uarrsort.cpp b/deps/icu-small/source/common/uarrsort.cpp index 03c4d4e7fc44aa..60905821649db9 100644 --- a/deps/icu-small/source/common/uarrsort.cpp +++ b/deps/icu-small/source/common/uarrsort.cpp @@ -34,6 +34,10 @@ enum { STACK_ITEM_SIZE=200 }; +static constexpr int32_t sizeInMaxAlignTs(int32_t sizeInBytes) { + return (sizeInBytes + sizeof(max_align_t) - 1) / sizeof(max_align_t); +} + /* UComparator convenience implementations ---------------------------------- */ U_CAPI int32_t U_EXPORT2 @@ -134,25 +138,15 @@ doInsertionSort(char *array, int32_t length, int32_t itemSize, static void insertionSort(char *array, int32_t length, int32_t itemSize, UComparator *cmp, const void *context, UErrorCode *pErrorCode) { - UAlignedMemory v[STACK_ITEM_SIZE/sizeof(UAlignedMemory)+1]; - void *pv; - /* allocate an intermediate item variable (v) */ - if(itemSize<=STACK_ITEM_SIZE) { - pv=v; - } else { - pv=uprv_malloc(itemSize); - if(pv==NULL) { - *pErrorCode=U_MEMORY_ALLOCATION_ERROR; - return; - } + icu::MaybeStackArray v; + if (sizeInMaxAlignTs(itemSize) > v.getCapacity() && + v.resize(sizeInMaxAlignTs(itemSize)) == nullptr) { + *pErrorCode = U_MEMORY_ALLOCATION_ERROR; + return; } - doInsertionSort(array, length, itemSize, cmp, context, pv); - - if(pv!=v) { - uprv_free(pv); - } + doInsertionSort(array, length, itemSize, cmp, context, v.getAlias()); } /* QuickSort ---------------------------------------------------------------- */ @@ -238,26 +232,16 @@ subQuickSort(char *array, int32_t start, int32_t limit, int32_t itemSize, static void quickSort(char *array, int32_t length, int32_t itemSize, UComparator *cmp, const void *context, UErrorCode *pErrorCode) { - UAlignedMemory xw[(2*STACK_ITEM_SIZE)/sizeof(UAlignedMemory)+1]; - void *p; - /* allocate two intermediate item variables (x and w) */ - if(itemSize<=STACK_ITEM_SIZE) { - p=xw; - } else { - p=uprv_malloc(2*itemSize); - if(p==NULL) { - *pErrorCode=U_MEMORY_ALLOCATION_ERROR; - return; - } + icu::MaybeStackArray xw; + if(sizeInMaxAlignTs(itemSize)*2 > xw.getCapacity() && + xw.resize(sizeInMaxAlignTs(itemSize) * 2) == nullptr) { + *pErrorCode=U_MEMORY_ALLOCATION_ERROR; + return; } - subQuickSort(array, 0, length, itemSize, - cmp, context, p, (char *)p+itemSize); - - if(p!=xw) { - uprv_free(p); - } + subQuickSort(array, 0, length, itemSize, cmp, context, + xw.getAlias(), xw.getAlias() + sizeInMaxAlignTs(itemSize)); } /* uprv_sortArray() API ----------------------------------------------------- */ diff --git a/deps/icu-small/source/common/ubidiimp.h b/deps/icu-small/source/common/ubidiimp.h index a5d0727495d767..9746b2bc103102 100644 --- a/deps/icu-small/source/common/ubidiimp.h +++ b/deps/icu-small/source/common/ubidiimp.h @@ -198,8 +198,8 @@ typedef struct Run { /* in a Run, logicalStart will get this bit set if the run level is odd */ #define INDEX_ODD_BIT (1UL<<31) -#define MAKE_INDEX_ODD_PAIR(index, level) ((index)|((int32_t)(level)<<31)) -#define ADD_ODD_BIT_FROM_LEVEL(x, level) ((x)|=((int32_t)(level)<<31)) +#define MAKE_INDEX_ODD_PAIR(index, level) ((index)|((int32_t)((level)&1)<<31)) +#define ADD_ODD_BIT_FROM_LEVEL(x, level) ((x)|=((int32_t)((level)&1)<<31)) #define REMOVE_ODD_BIT(x) ((x)&=~INDEX_ODD_BIT) #define GET_INDEX(x) ((x)&~INDEX_ODD_BIT) @@ -387,41 +387,49 @@ typedef union { } BidiMemoryForAllocation; /* Macros for initial checks at function entry */ -#define RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrcode, retvalue) \ - if((pErrcode)==NULL || U_FAILURE(*pErrcode)) return retvalue -#define RETURN_IF_NOT_VALID_PARA(bidi, errcode, retvalue) \ - if(!IS_VALID_PARA(bidi)) { \ - errcode=U_INVALID_STATE_ERROR; \ - return retvalue; \ - } -#define RETURN_IF_NOT_VALID_PARA_OR_LINE(bidi, errcode, retvalue) \ - if(!IS_VALID_PARA_OR_LINE(bidi)) { \ - errcode=U_INVALID_STATE_ERROR; \ - return retvalue; \ - } -#define RETURN_IF_BAD_RANGE(arg, start, limit, errcode, retvalue) \ - if((arg)<(start) || (arg)>=(limit)) { \ - (errcode)=U_ILLEGAL_ARGUMENT_ERROR; \ - return retvalue; \ - } - -#define RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrcode) \ - if((pErrcode)==NULL || U_FAILURE(*pErrcode)) return -#define RETURN_VOID_IF_NOT_VALID_PARA(bidi, errcode) \ - if(!IS_VALID_PARA(bidi)) { \ - errcode=U_INVALID_STATE_ERROR; \ - return; \ - } -#define RETURN_VOID_IF_NOT_VALID_PARA_OR_LINE(bidi, errcode) \ - if(!IS_VALID_PARA_OR_LINE(bidi)) { \ - errcode=U_INVALID_STATE_ERROR; \ - return; \ - } -#define RETURN_VOID_IF_BAD_RANGE(arg, start, limit, errcode) \ - if((arg)<(start) || (arg)>=(limit)) { \ - (errcode)=U_ILLEGAL_ARGUMENT_ERROR; \ - return; \ - } +#define RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrcode, retvalue) UPRV_BLOCK_MACRO_BEGIN { \ + if((pErrcode)==NULL || U_FAILURE(*pErrcode)) return retvalue; \ +} UPRV_BLOCK_MACRO_END +#define RETURN_IF_NOT_VALID_PARA(bidi, errcode, retvalue) UPRV_BLOCK_MACRO_BEGIN { \ + if(!IS_VALID_PARA(bidi)) { \ + errcode=U_INVALID_STATE_ERROR; \ + return retvalue; \ + } \ +} UPRV_BLOCK_MACRO_END +#define RETURN_IF_NOT_VALID_PARA_OR_LINE(bidi, errcode, retvalue) UPRV_BLOCK_MACRO_BEGIN { \ + if(!IS_VALID_PARA_OR_LINE(bidi)) { \ + errcode=U_INVALID_STATE_ERROR; \ + return retvalue; \ + } \ +} UPRV_BLOCK_MACRO_END +#define RETURN_IF_BAD_RANGE(arg, start, limit, errcode, retvalue) UPRV_BLOCK_MACRO_BEGIN { \ + if((arg)<(start) || (arg)>=(limit)) { \ + (errcode)=U_ILLEGAL_ARGUMENT_ERROR; \ + return retvalue; \ + } \ +} UPRV_BLOCK_MACRO_END + +#define RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrcode) UPRV_BLOCK_MACRO_BEGIN { \ + if((pErrcode)==NULL || U_FAILURE(*pErrcode)) return; \ +} UPRV_BLOCK_MACRO_END +#define RETURN_VOID_IF_NOT_VALID_PARA(bidi, errcode) UPRV_BLOCK_MACRO_BEGIN { \ + if(!IS_VALID_PARA(bidi)) { \ + errcode=U_INVALID_STATE_ERROR; \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END +#define RETURN_VOID_IF_NOT_VALID_PARA_OR_LINE(bidi, errcode) UPRV_BLOCK_MACRO_BEGIN { \ + if(!IS_VALID_PARA_OR_LINE(bidi)) { \ + errcode=U_INVALID_STATE_ERROR; \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END +#define RETURN_VOID_IF_BAD_RANGE(arg, start, limit, errcode) UPRV_BLOCK_MACRO_BEGIN { \ + if((arg)<(start) || (arg)>=(limit)) { \ + (errcode)=U_ILLEGAL_ARGUMENT_ERROR; \ + return; \ + } \ +} UPRV_BLOCK_MACRO_END /* helper function to (re)allocate memory if allowed */ U_CFUNC UBool diff --git a/deps/icu-small/source/common/ubiditransform.cpp b/deps/icu-small/source/common/ubiditransform.cpp index 394df6092d21b1..bb3ce8cb934d43 100644 --- a/deps/icu-small/source/common/ubiditransform.cpp +++ b/deps/icu-small/source/common/ubiditransform.cpp @@ -31,11 +31,11 @@ #define SHAPE_LOGICAL U_SHAPE_TEXT_DIRECTION_LOGICAL #define SHAPE_VISUAL U_SHAPE_TEXT_DIRECTION_VISUAL_LTR -#define CHECK_LEN(STR, LEN, ERROR) { \ - if (LEN == 0) return 0; \ - if (LEN < -1) { *(ERROR) = U_ILLEGAL_ARGUMENT_ERROR; return 0; } \ - if (LEN == -1) LEN = u_strlen(STR); \ - } +#define CHECK_LEN(STR, LEN, ERROR) UPRV_BLOCK_MACRO_BEGIN { \ + if (LEN == 0) return 0; \ + if (LEN < -1) { *(ERROR) = U_ILLEGAL_ARGUMENT_ERROR; return 0; } \ + if (LEN == -1) LEN = u_strlen(STR); \ +} UPRV_BLOCK_MACRO_END #define MAX_ACTIONS 7 diff --git a/deps/icu-small/source/common/ucase.cpp b/deps/icu-small/source/common/ucase.cpp index 50c8d20c1fce73..57a40327905c00 100644 --- a/deps/icu-small/source/common/ucase.cpp +++ b/deps/icu-small/source/common/ucase.cpp @@ -116,7 +116,7 @@ static const uint8_t flagsOffset[256]={ * moved to the last uint16_t of the value, use +1 for beginning of next slot * @param value (out) int32_t or uint32_t output if hasSlot, otherwise not modified */ -#define GET_SLOT_VALUE(excWord, idx, pExc16, value) \ +#define GET_SLOT_VALUE(excWord, idx, pExc16, value) UPRV_BLOCK_MACRO_BEGIN { \ if(((excWord)&UCASE_EXC_DOUBLE_SLOTS)==0) { \ (pExc16)+=SLOT_OFFSET(excWord, idx); \ (value)=*pExc16; \ @@ -124,7 +124,8 @@ static const uint8_t flagsOffset[256]={ (pExc16)+=2*SLOT_OFFSET(excWord, idx); \ (value)=*pExc16++; \ (value)=((value)<<16)|*pExc16; \ - } + } \ +} UPRV_BLOCK_MACRO_END /* simple case mappings ----------------------------------------------------- */ diff --git a/deps/icu-small/source/common/uchar.cpp b/deps/icu-small/source/common/uchar.cpp index 60fe75c78dec03..12365fd6976e5b 100644 --- a/deps/icu-small/source/common/uchar.cpp +++ b/deps/icu-small/source/common/uchar.cpp @@ -40,7 +40,7 @@ /* constants and macros for access to the data ------------------------------ */ /* getting a uint32_t properties word from the data */ -#define GET_PROPS(c, result) ((result)=UTRIE2_GET16(&propsTrie, c)); +#define GET_PROPS(c, result) ((result)=UTRIE2_GET16(&propsTrie, c)) /* API functions ------------------------------------------------------------ */ diff --git a/deps/icu-small/source/common/uchriter.cpp b/deps/icu-small/source/common/uchriter.cpp index 822168f5c8e600..bedbabc74c2351 100644 --- a/deps/icu-small/source/common/uchriter.cpp +++ b/deps/icu-small/source/common/uchriter.cpp @@ -89,7 +89,7 @@ UCharCharacterIterator::hashCode() const { return ustr_hashUCharsN(text, textLength) ^ pos ^ begin ^ end; } -CharacterIterator* +UCharCharacterIterator* UCharCharacterIterator::clone() const { return new UCharCharacterIterator(*this); } diff --git a/deps/icu-small/source/common/ucln_cmn.cpp b/deps/icu-small/source/common/ucln_cmn.cpp index d78491df419fb0..ab9d3adbd25958 100644 --- a/deps/icu-small/source/common/ucln_cmn.cpp +++ b/deps/icu-small/source/common/ucln_cmn.cpp @@ -65,9 +65,20 @@ U_CFUNC void ucln_common_registerCleanup(ECleanupCommonType type, cleanupFunc *func) { + // Thread safety messiness: From ticket 10295, calls to registerCleanup() may occur + // concurrently. Although such cases should be storing the same value, they raise errors + // from the thread sanity checker. Doing the store within a mutex avoids those. + // BUT that can trigger a recursive entry into std::call_once() in umutex.cpp when this code, + // running from the call_once function, tries to grab the ICU global mutex, which + // re-enters the mutex init path. So, work-around by special casing UCLN_COMMON_MUTEX, not + // using the ICU global mutex for it. + // + // No other point in ICU uses std::call_once(). + U_ASSERT(UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT); - if (UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT) - { + if (type == UCLN_COMMON_MUTEX) { + gCommonCleanupFunctions[type] = func; + } else if (UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT) { icu::Mutex m; // See ticket 10295 for discussion. gCommonCleanupFunctions[type] = func; } diff --git a/deps/icu-small/source/common/ucln_cmn.h b/deps/icu-small/source/common/ucln_cmn.h index 0ca911b47d9875..b837fb946296a1 100644 --- a/deps/icu-small/source/common/ucln_cmn.h +++ b/deps/icu-small/source/common/ucln_cmn.h @@ -22,8 +22,6 @@ /* These are the cleanup functions for various APIs. */ /* @return true if cleanup complete successfully.*/ -U_CFUNC UBool umtx_cleanup(void); - U_CFUNC UBool utrace_cleanup(void); U_CFUNC UBool ucln_lib_cleanup(void); @@ -41,6 +39,8 @@ typedef enum ECleanupCommonType { UCLN_COMMON_LOCALE_KEY_TYPE, UCLN_COMMON_LOCALE, UCLN_COMMON_LOCALE_AVAILABLE, + UCLN_COMMON_LIKELY_SUBTAGS, + UCLN_COMMON_LOCALE_DISTANCE, UCLN_COMMON_ULOC, UCLN_COMMON_CURRENCY, UCLN_COMMON_LOADED_NORMALIZER2, @@ -62,6 +62,7 @@ typedef enum ECleanupCommonType { */ UCLN_COMMON_UNIFIED_CACHE, UCLN_COMMON_URES, + UCLN_COMMON_MUTEX, // Mutexes should be the last to be cleaned up. UCLN_COMMON_COUNT /* This must be last */ } ECleanupCommonType; diff --git a/deps/icu-small/source/common/ucnv.cpp b/deps/icu-small/source/common/ucnv.cpp index abf302eaddb7a8..e2e0c5b9f7f42f 100644 --- a/deps/icu-small/source/common/ucnv.cpp +++ b/deps/icu-small/source/common/ucnv.cpp @@ -25,6 +25,8 @@ #if !UCONFIG_NO_CONVERSION +#include + #include "unicode/ustring.h" #include "unicode/ucnv.h" #include "unicode/ucnv_err.h" @@ -158,7 +160,6 @@ ucnv_safeClone(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, U UConverter *localConverter, *allocatedConverter; int32_t stackBufferSize; int32_t bufferSizeNeeded; - char *stackBufferChars = (char *)stackBuffer; UErrorCode cbErr; UConverterToUnicodeArgs toUArgs = { sizeof(UConverterToUnicodeArgs), @@ -224,23 +225,22 @@ ucnv_safeClone(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, U } } - - /* Pointers on 64-bit platforms need to be aligned - * on a 64-bit boundary in memory. + /* Adjust (if necessary) the stackBuffer pointer to be aligned correctly for a UConverter. + * TODO(Jira ICU-20736) Redo this using std::align() once g++4.9 compatibility is no longer needed. */ - if (U_ALIGNMENT_OFFSET(stackBuffer) != 0) { - int32_t offsetUp = (int32_t)U_ALIGNMENT_OFFSET_UP(stackBufferChars); - if(stackBufferSize > offsetUp) { - stackBufferSize -= offsetUp; - stackBufferChars += offsetUp; + if (stackBuffer) { + uintptr_t p = reinterpret_cast(stackBuffer); + uintptr_t aligned_p = (p + alignof(UConverter) - 1) & ~(alignof(UConverter) - 1); + ptrdiff_t pointerAdjustment = aligned_p - p; + if (bufferSizeNeeded + pointerAdjustment <= stackBufferSize) { + stackBuffer = reinterpret_cast(aligned_p); + stackBufferSize -= pointerAdjustment; } else { /* prevent using the stack buffer but keep the size > 0 so that we do not just preflight */ stackBufferSize = 1; } } - stackBuffer = (void *)stackBufferChars; - /* Now, see if we must allocate any memory */ if (stackBufferSize < bufferSizeNeeded || stackBuffer == NULL) { @@ -475,7 +475,7 @@ ucnv_setSubstString(UConverter *cnv, const UChar *s, int32_t length, UErrorCode *err) { - UAlignedMemory cloneBuffer[U_CNV_SAFECLONE_BUFFERSIZE / sizeof(UAlignedMemory) + 1]; + alignas(UConverter) char cloneBuffer[U_CNV_SAFECLONE_BUFFERSIZE]; char chars[UCNV_ERROR_BUFFER_LENGTH]; UConverter *clone; diff --git a/deps/icu-small/source/common/ucnv2022.cpp b/deps/icu-small/source/common/ucnv2022.cpp index 4a35ff85e10fa0..6cd9a3d12e40fc 100644 --- a/deps/icu-small/source/common/ucnv2022.cpp +++ b/deps/icu-small/source/common/ucnv2022.cpp @@ -3571,20 +3571,11 @@ _ISO_2022_WriteSub(UConverterFromUnicodeArgs *args, int32_t offsetIndex, UErrorC /* * Structure for cloning an ISO 2022 converter into a single memory block. - * ucnv_safeClone() of the converter will align the entire cloneStruct, - * and then ucnv_safeClone() of the sub-converter may additionally align - * currentConverter inside the cloneStruct, for which we need the deadSpace - * after currentConverter. - * This is because UAlignedMemory may be larger than the actually - * necessary alignment size for the platform. - * The other cloneStruct fields will not be moved around, - * and are aligned properly with cloneStruct's alignment. */ struct cloneStruct { UConverter cnv; UConverter currentConverter; - UAlignedMemory deadSpace; UConverterDataISO2022 mydata; }; @@ -3602,6 +3593,10 @@ _ISO_2022_SafeClone( UConverterDataISO2022 *cnvData; int32_t i, size; + if (U_FAILURE(*status)){ + return nullptr; + } + if (*pBufferSize == 0) { /* 'preflighting' request - set needed size into *pBufferSize */ *pBufferSize = (int32_t)sizeof(struct cloneStruct); return NULL; @@ -3619,7 +3614,7 @@ _ISO_2022_SafeClone( /* share the subconverters */ if(cnvData->currentConverter != NULL) { - size = (int32_t)(sizeof(UConverter) + sizeof(UAlignedMemory)); /* include size of padding */ + size = (int32_t)sizeof(UConverter); localClone->mydata.currentConverter = ucnv_safeClone(cnvData->currentConverter, &localClone->currentConverter, diff --git a/deps/icu-small/source/common/ucnv_bld.cpp b/deps/icu-small/source/common/ucnv_bld.cpp index e6ef833f4e4317..1c2363ea89981f 100644 --- a/deps/icu-small/source/common/ucnv_bld.cpp +++ b/deps/icu-small/source/common/ucnv_bld.cpp @@ -194,10 +194,7 @@ static struct { /*initializes some global variables */ static UHashtable *SHARED_DATA_HASHTABLE = NULL; -static icu::UMutex *cnvCacheMutex() { /* Mutex for synchronizing cnv cache access. */ - static icu::UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static icu::UMutex cnvCacheMutex; /* Note: the global mutex is used for */ /* reference count updates. */ @@ -602,9 +599,9 @@ U_CFUNC void ucnv_unloadSharedDataIfReady(UConverterSharedData *sharedData) { if(sharedData != NULL && sharedData->isReferenceCounted) { - umtx_lock(cnvCacheMutex()); + umtx_lock(&cnvCacheMutex); ucnv_unload(sharedData); - umtx_unlock(cnvCacheMutex()); + umtx_unlock(&cnvCacheMutex); } } @@ -612,9 +609,9 @@ U_CFUNC void ucnv_incrementRefCount(UConverterSharedData *sharedData) { if(sharedData != NULL && sharedData->isReferenceCounted) { - umtx_lock(cnvCacheMutex()); + umtx_lock(&cnvCacheMutex); sharedData->referenceCounter++; - umtx_unlock(cnvCacheMutex()); + umtx_unlock(&cnvCacheMutex); } } @@ -815,9 +812,9 @@ ucnv_loadSharedData(const char *converterName, pArgs->nestedLoads=1; pArgs->pkg=NULL; - umtx_lock(cnvCacheMutex()); + umtx_lock(&cnvCacheMutex); mySharedConverterData = ucnv_load(pArgs, err); - umtx_unlock(cnvCacheMutex()); + umtx_unlock(&cnvCacheMutex); if (U_FAILURE (*err) || (mySharedConverterData == NULL)) { return NULL; @@ -1064,7 +1061,7 @@ ucnv_flushCache () * because the sequence of looking up in the cache + incrementing * is protected by cnvCacheMutex. */ - umtx_lock(cnvCacheMutex()); + umtx_lock(&cnvCacheMutex); /* * double loop: A delta/extension-only converter has a pointer to its base table's * shared data; the first iteration of the outer loop may see the delta converter @@ -1093,7 +1090,7 @@ ucnv_flushCache () } } } while(++i == 1 && remaining > 0); - umtx_unlock(cnvCacheMutex()); + umtx_unlock(&cnvCacheMutex); UTRACE_DATA1(UTRACE_INFO, "ucnv_flushCache() exits with %d converters remaining", remaining); @@ -1199,7 +1196,7 @@ internalSetName(const char *name, UErrorCode *status) { } algorithmicSharedData = getAlgorithmicTypeFromName(stackArgs.name); - umtx_lock(cnvCacheMutex()); + umtx_lock(&cnvCacheMutex); gDefaultAlgorithmicSharedData = algorithmicSharedData; gDefaultConverterContainsOption = containsOption; @@ -1215,7 +1212,7 @@ internalSetName(const char *name, UErrorCode *status) { ucnv_enableCleanup(); - umtx_unlock(cnvCacheMutex()); + umtx_unlock(&cnvCacheMutex); } #endif @@ -1240,7 +1237,7 @@ ucnv_getDefaultName() { but ucnv_setDefaultName is not thread safe. */ { - icu::Mutex lock(cnvCacheMutex()); + icu::Mutex lock(&cnvCacheMutex); name = gDefaultConverterName; } if(name==NULL) { diff --git a/deps/icu-small/source/common/ucnv_lmb.cpp b/deps/icu-small/source/common/ucnv_lmb.cpp index 6dd8e83428a0af..5e7cfde353d7e3 100644 --- a/deps/icu-small/source/common/ucnv_lmb.cpp +++ b/deps/icu-small/source/common/ucnv_lmb.cpp @@ -1107,11 +1107,13 @@ GetUniFromLMBCSUni(char const ** ppLMBCSin) /* Called with LMBCS-style Unicode all input as required by ICU converter semantics. */ -#define CHECK_SOURCE_LIMIT(index) \ - if (args->source+index > args->sourceLimit){\ - *err = U_TRUNCATED_CHAR_FOUND;\ - args->source = args->sourceLimit;\ - return 0xffff;} +#define CHECK_SOURCE_LIMIT(index) UPRV_BLOCK_MACRO_BEGIN { \ + if (args->source+index > args->sourceLimit) { \ + *err = U_TRUNCATED_CHAR_FOUND; \ + args->source = args->sourceLimit; \ + return 0xffff; \ + } \ +} UPRV_BLOCK_MACRO_END /* Return the Unicode representation for the current LMBCS character */ diff --git a/deps/icu-small/source/common/ucnvbocu.cpp b/deps/icu-small/source/common/ucnvbocu.cpp index 5b66c5059a55ba..7c2aab56558c8c 100644 --- a/deps/icu-small/source/common/ucnvbocu.cpp +++ b/deps/icu-small/source/common/ucnvbocu.cpp @@ -202,14 +202,14 @@ bocu1TrailToByte[BOCU1_TRAIL_CONTROLS_COUNT]={ * @param d Divisor. * @param m Output variable for the rest (modulo result). */ -#define NEGDIVMOD(n, d, m) { \ +#define NEGDIVMOD(n, d, m) UPRV_BLOCK_MACRO_BEGIN { \ (m)=(n)%(d); \ (n)/=(d); \ if((m)<0) { \ --(n); \ (m)+=(d); \ } \ -} +} UPRV_BLOCK_MACRO_END /* Faster versions of packDiff() for single-byte-encoded diff values. */ diff --git a/deps/icu-small/source/common/ucnvhz.cpp b/deps/icu-small/source/common/ucnvhz.cpp index 31595374696d8c..b26cf78289dcab 100644 --- a/deps/icu-small/source/common/ucnvhz.cpp +++ b/deps/icu-small/source/common/ucnvhz.cpp @@ -38,7 +38,7 @@ #define ESC_LEN 2 -#define CONCAT_ESCAPE_MACRO( args, targetIndex,targetLength,strToAppend, err, len,sourceIndex){ \ +#define CONCAT_ESCAPE_MACRO(args, targetIndex,targetLength,strToAppend, err, len,sourceIndex) UPRV_BLOCK_MACRO_BEGIN { \ while(len-->0){ \ if(targetIndex < targetLength){ \ args->target[targetIndex] = (unsigned char) *strToAppend; \ @@ -53,7 +53,7 @@ } \ strToAppend++; \ } \ -} +} UPRV_BLOCK_MACRO_END typedef struct{ @@ -518,19 +518,11 @@ _HZ_WriteSub(UConverterFromUnicodeArgs *args, int32_t offsetIndex, UErrorCode *e /* * Structure for cloning an HZ converter into a single memory block. - * ucnv_safeClone() of the HZ converter will align the entire cloneHZStruct, - * and then ucnv_safeClone() of the sub-converter may additionally align - * subCnv inside the cloneHZStruct, for which we need the deadSpace after - * subCnv. This is because UAlignedMemory may be larger than the actually - * necessary alignment size for the platform. - * The other cloneHZStruct fields will not be moved around, - * and are aligned properly with cloneHZStruct's alignment. */ struct cloneHZStruct { UConverter cnv; UConverter subCnv; - UAlignedMemory deadSpace; UConverterDataHZ mydata; }; @@ -545,12 +537,12 @@ _HZ_SafeClone(const UConverter *cnv, int32_t size, bufferSizeNeeded = sizeof(struct cloneHZStruct); if (U_FAILURE(*status)){ - return 0; + return nullptr; } if (*pBufferSize == 0){ /* 'preflighting' request - set needed size into *pBufferSize */ *pBufferSize = bufferSizeNeeded; - return 0; + return nullptr; } localClone = (struct cloneHZStruct *)stackBuffer; @@ -561,7 +553,7 @@ _HZ_SafeClone(const UConverter *cnv, localClone->cnv.isExtraLocal = TRUE; /* deep-clone the sub-converter */ - size = (int32_t)(sizeof(UConverter) + sizeof(UAlignedMemory)); /* include size of padding */ + size = (int32_t)sizeof(UConverter); ((UConverterDataHZ*)localClone->cnv.extraInfo)->gbConverter = ucnv_safeClone(((UConverterDataHZ*)cnv->extraInfo)->gbConverter, &localClone->subCnv, &size, status); diff --git a/deps/icu-small/source/common/ucnvisci.cpp b/deps/icu-small/source/common/ucnvisci.cpp index d0c07f2b27fae9..c1ab06e137ee22 100644 --- a/deps/icu-small/source/common/ucnvisci.cpp +++ b/deps/icu-small/source/common/ucnvisci.cpp @@ -831,7 +831,7 @@ static const uint16_t nuktaSpecialCases[][2]={ }; -#define WRITE_TO_TARGET_FROM_U(args,offsets,source,target,targetLimit,targetByteUnit,err){ \ +#define WRITE_TO_TARGET_FROM_U(args,offsets,source,target,targetLimit,targetByteUnit,err) UPRV_BLOCK_MACRO_BEGIN { \ int32_t offset = (int32_t)(source - args->source-1); \ /* write the targetUniChar to target */ \ if(target < targetLimit){ \ @@ -884,7 +884,7 @@ static const uint16_t nuktaSpecialCases[][2]={ (uint8_t) (targetByteUnit); \ *err = U_BUFFER_OVERFLOW_ERROR; \ } \ -} +} UPRV_BLOCK_MACRO_END /* Rules: * Explicit Halant : @@ -1119,7 +1119,7 @@ static const uint16_t lookupTable[][2]={ { GURMUKHI, PNJ_MASK } }; -#define WRITE_TO_TARGET_TO_U(args,source,target,offsets,offset,targetUniChar,delta, err){\ +#define WRITE_TO_TARGET_TO_U(args,source,target,offsets,offset,targetUniChar,delta, err) UPRV_BLOCK_MACRO_BEGIN { \ /* add offset to current Indic Block */ \ if(targetUniChar>ASCII_END && \ targetUniChar != ZWJ && \ @@ -1140,9 +1140,9 @@ static const uint16_t lookupTable[][2]={ (UChar)targetUniChar; \ *err = U_BUFFER_OVERFLOW_ERROR; \ } \ -} +} UPRV_BLOCK_MACRO_END -#define GET_MAPPING(sourceChar,targetUniChar,data){ \ +#define GET_MAPPING(sourceChar,targetUniChar,data) UPRV_BLOCK_MACRO_BEGIN { \ targetUniChar = toUnicodeTable[(sourceChar)] ; \ /* is the code point valid in current script? */ \ if(sourceChar> ASCII_END && \ @@ -1153,7 +1153,7 @@ static const uint16_t lookupTable[][2]={ targetUniChar=missingCharMarker; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /*********** * Rules for ISCII to Unicode converter diff --git a/deps/icu-small/source/common/ucnvsel.cpp b/deps/icu-small/source/common/ucnvsel.cpp index 6ccee1ae61fd70..07b55022c346e8 100644 --- a/deps/icu-small/source/common/ucnvsel.cpp +++ b/deps/icu-small/source/common/ucnvsel.cpp @@ -691,36 +691,36 @@ static int16_t countOnes(uint32_t* mask, int32_t len) { /* internal function! */ static UEnumeration *selectForMask(const UConverterSelector* sel, - uint32_t *mask, UErrorCode *status) { + uint32_t *theMask, UErrorCode *status) { + LocalMemory mask(theMask); // this is the context we will use. Store a table of indices to which // encodings are legit. - struct Enumerator* result = (Enumerator*)uprv_malloc(sizeof(Enumerator)); - if (result == NULL) { - uprv_free(mask); + LocalMemory result(static_cast(uprv_malloc(sizeof(Enumerator)))); + if (result.isNull()) { *status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } - result->index = NULL; // this will be allocated later! + result->index = nullptr; // this will be allocated later! result->length = result->cur = 0; result->sel = sel; - UEnumeration *en = (UEnumeration *)uprv_malloc(sizeof(UEnumeration)); - if (en == NULL) { + LocalMemory en(static_cast(uprv_malloc(sizeof(UEnumeration)))); + if (en.isNull()) { // TODO(markus): Combine Enumerator and UEnumeration into one struct. - uprv_free(mask); - uprv_free(result); *status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } - memcpy(en, &defaultEncodings, sizeof(UEnumeration)); - en->context = result; + memcpy(en.getAlias(), &defaultEncodings, sizeof(UEnumeration)); int32_t columns = (sel->encodingsCount+31)/32; - int16_t numOnes = countOnes(mask, columns); + int16_t numOnes = countOnes(mask.getAlias(), columns); // now, we know the exact space we need for index if (numOnes > 0) { - result->index = (int16_t*) uprv_malloc(numOnes * sizeof(int16_t)); - + result->index = static_cast(uprv_malloc(numOnes * sizeof(int16_t))); + if (result->index == nullptr) { + *status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } int32_t i, j; int16_t k = 0; for (j = 0 ; j < columns; j++) { @@ -734,8 +734,8 @@ static UEnumeration *selectForMask(const UConverterSelector* sel, } } //otherwise, index will remain NULL (and will never be touched by //the enumerator code anyway) - uprv_free(mask); - return en; + en->context = result.orphan(); + return en.orphan(); } /* check a string against the selector - UTF16 version */ diff --git a/deps/icu-small/source/common/ucptrie.cpp b/deps/icu-small/source/common/ucptrie.cpp index b72e318387a186..0004160a238b0e 100644 --- a/deps/icu-small/source/common/ucptrie.cpp +++ b/deps/icu-small/source/common/ucptrie.cpp @@ -280,7 +280,7 @@ UChar32 getRange(const void *t, UChar32 start, int32_t prevI3Block = -1; int32_t prevBlock = -1; UChar32 c = start; - uint32_t trieValue, value; + uint32_t trieValue, value = nullValue; bool haveValue = false; do { int32_t i3Block; diff --git a/deps/icu-small/source/common/ucurr.cpp b/deps/icu-small/source/common/ucurr.cpp index dba3247fef2c98..d42c2f10b1d4c6 100644 --- a/deps/icu-small/source/common/ucurr.cpp +++ b/deps/icu-small/source/common/ucurr.cpp @@ -365,10 +365,7 @@ U_CDECL_END #if !UCONFIG_NO_SERVICE struct CReg; -static UMutex *gCRegLock() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex gCRegLock; static CReg* gCRegHead = 0; struct CReg : public icu::UMemory { @@ -394,14 +391,14 @@ struct CReg : public icu::UMemory { if (status && U_SUCCESS(*status) && _iso && _id) { CReg* n = new CReg(_iso, _id); if (n) { - umtx_lock(gCRegLock()); + umtx_lock(&gCRegLock); if (!gCRegHead) { /* register for the first time */ ucln_common_registerCleanup(UCLN_COMMON_CURRENCY, currency_cleanup); } n->next = gCRegHead; gCRegHead = n; - umtx_unlock(gCRegLock()); + umtx_unlock(&gCRegLock); return n; } *status = U_MEMORY_ALLOCATION_ERROR; @@ -411,7 +408,7 @@ struct CReg : public icu::UMemory { static UBool unreg(UCurrRegistryKey key) { UBool found = FALSE; - umtx_lock(gCRegLock()); + umtx_lock(&gCRegLock); CReg** p = &gCRegHead; while (*p) { @@ -424,13 +421,13 @@ struct CReg : public icu::UMemory { p = &((*p)->next); } - umtx_unlock(gCRegLock()); + umtx_unlock(&gCRegLock); return found; } static const UChar* get(const char* id) { const UChar* result = NULL; - umtx_lock(gCRegLock()); + umtx_lock(&gCRegLock); CReg* p = gCRegHead; /* register cleanup of the mutex */ @@ -442,7 +439,7 @@ struct CReg : public icu::UMemory { } p = p->next; } - umtx_unlock(gCRegLock()); + umtx_unlock(&gCRegLock); return result; } @@ -716,7 +713,9 @@ ucurr_getName(const UChar* currency, // We no longer support choice format data in names. Data should not contain // choice patterns. - *isChoiceFormat = FALSE; + if (isChoiceFormat != NULL) { + *isChoiceFormat = FALSE; + } if (U_SUCCESS(ec2)) { U_ASSERT(s != NULL); return s; @@ -1356,10 +1355,7 @@ static CurrencyNameCacheEntry* currCache[CURRENCY_NAME_CACHE_NUM] = {NULL}; // It is a simple round-robin replacement strategy. static int8_t currentCacheEntryIndex = 0; -static UMutex *gCurrencyCacheMutex() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex gCurrencyCacheMutex; // Cache deletion static void @@ -1408,7 +1404,7 @@ getCacheEntry(const char* locale, UErrorCode& ec) { CurrencyNameStruct* currencySymbols = NULL; CurrencyNameCacheEntry* cacheEntry = NULL; - umtx_lock(gCurrencyCacheMutex()); + umtx_lock(&gCurrencyCacheMutex); // in order to handle racing correctly, // not putting 'search' in a separate function. int8_t found = -1; @@ -1423,13 +1419,13 @@ getCacheEntry(const char* locale, UErrorCode& ec) { cacheEntry = currCache[found]; ++(cacheEntry->refCount); } - umtx_unlock(gCurrencyCacheMutex()); + umtx_unlock(&gCurrencyCacheMutex); if (found == -1) { collectCurrencyNames(locale, ¤cyNames, &total_currency_name_count, ¤cySymbols, &total_currency_symbol_count, ec); if (U_FAILURE(ec)) { return NULL; } - umtx_lock(gCurrencyCacheMutex()); + umtx_lock(&gCurrencyCacheMutex); // check again. for (int8_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) { if (currCache[i]!= NULL && @@ -1468,19 +1464,19 @@ getCacheEntry(const char* locale, UErrorCode& ec) { cacheEntry = currCache[found]; ++(cacheEntry->refCount); } - umtx_unlock(gCurrencyCacheMutex()); + umtx_unlock(&gCurrencyCacheMutex); } return cacheEntry; } static void releaseCacheEntry(CurrencyNameCacheEntry* cacheEntry) { - umtx_lock(gCurrencyCacheMutex()); + umtx_lock(&gCurrencyCacheMutex); --(cacheEntry->refCount); if (cacheEntry->refCount == 0) { // remove deleteCacheEntry(cacheEntry); } - umtx_unlock(gCurrencyCacheMutex()); + umtx_unlock(&gCurrencyCacheMutex); } U_CAPI void @@ -1601,10 +1597,9 @@ uprv_getStaticCurrencyName(const UChar* iso, const char* loc, { U_NAMESPACE_USE - UBool isChoiceFormat; int32_t len; const UChar* currname = ucurr_getName(iso, loc, UCURR_SYMBOL_NAME, - &isChoiceFormat, &len, &ec); + nullptr /* isChoiceFormat */, &len, &ec); if (U_SUCCESS(ec)) { result.setTo(currname, len); } diff --git a/deps/icu-small/source/common/udata.cpp b/deps/icu-small/source/common/udata.cpp index 99efbc97eed737..f2faa82777a233 100644 --- a/deps/icu-small/source/common/udata.cpp +++ b/deps/icu-small/source/common/udata.cpp @@ -33,6 +33,7 @@ might have to #include some other header #include "cstring.h" #include "mutex.h" #include "putilimp.h" +#include "restrace.h" #include "uassert.h" #include "ucln_cmn.h" #include "ucmndata.h" @@ -110,11 +111,12 @@ static u_atomic_int32_t gHaveTriedToLoadCommonData = ATOMIC_INT32_T_INITIALIZER( static UHashtable *gCommonDataCache = NULL; /* Global hash table of opened ICU data files. */ static icu::UInitOnce gCommonDataCacheInitOnce = U_INITONCE_INITIALIZER; -#if U_PLATFORM_HAS_WINUWP_API == 0 +#if !defined(ICU_DATA_DIR_WINDOWS) static UDataFileAccess gDataFileAccess = UDATA_DEFAULT_ACCESS; // Access not synchronized. // Modifying is documented as thread-unsafe. #else -static UDataFileAccess gDataFileAccess = UDATA_NO_FILES; // Windows UWP looks in one spot explicitly +// If we are using the Windows data directory, then look in one spot only. +static UDataFileAccess gDataFileAccess = UDATA_NO_FILES; #endif static UBool U_CALLCONV @@ -206,7 +208,7 @@ setCommonICUData(UDataMemory *pData, /* The new common data. Belongs to ca return didUpdate; } -#if U_PLATFORM_HAS_WINUWP_API == 0 +#if !defined(ICU_DATA_DIR_WINDOWS) static UBool setCommonICUDataPointer(const void *pData, UBool /*warn*/, UErrorCode *pErrorCode) { @@ -320,7 +322,7 @@ static UDataMemory *udata_findCachedData(const char *path, UErrorCode &err) retVal = el->item; } #ifdef UDATA_DEBUG - fprintf(stderr, "Cache: [%s] -> %p\n", baseName, retVal); + fprintf(stderr, "Cache: [%s] -> %p\n", baseName, (void*) retVal); #endif return retVal; } @@ -383,7 +385,7 @@ static UDataMemory *udata_cacheDataItem(const char *path, UDataMemory *item, UEr #ifdef UDATA_DEBUG fprintf(stderr, "Cache: [%s] <<< %p : %s. vFunc=%p\n", newElement->name, - newElement->item, u_errorName(subErr), newElement->item->vFuncs); + (void*) newElement->item, u_errorName(subErr), (void*) newElement->item->vFuncs); #endif if (subErr == U_USING_DEFAULT_WARNING || U_FAILURE(subErr)) { @@ -477,7 +479,7 @@ UDataPathIterator::UDataPathIterator(const char *inPath, const char *pkg, nextPath = itemPath.data(); } #ifdef UDATA_DEBUG - fprintf(stderr, "SUFFIX=%s [%p]\n", inSuffix, inSuffix); + fprintf(stderr, "SUFFIX=%s [%p]\n", inSuffix, (void*) inSuffix); #endif /** Suffix **/ @@ -492,12 +494,11 @@ UDataPathIterator::UDataPathIterator(const char *inPath, const char *pkg, /* pathBuffer will hold the output path strings returned by this iterator */ #ifdef UDATA_DEBUG - fprintf(stderr, "%p: init %s -> [path=%s], [base=%s], [suff=%s], [itempath=%s], [nextpath=%s], [checklast4=%s]\n", - iter, + fprintf(stderr, "0: init %s -> [path=%s], [base=%s], [suff=%s], [itempath=%s], [nextpath=%s], [checklast4=%s]\n", item, path, basename, - suffix, + suffix.data(), itemPath.data(), nextPath, checkLastFour?"TRUE":"false"); @@ -553,7 +554,7 @@ const char *UDataPathIterator::next(UErrorCode *pErrorCode) fprintf(stderr, "rest of path (IDD) = %s\n", currentPath); fprintf(stderr, " "); { - uint32_t qqq; + int32_t qqq; for(qqq=0;qqqpHeader == &U_ICUDATA_ENTRY_POINT) { @@ -714,7 +717,8 @@ openCommonData(const char *path, /* Path from OpenChoice? */ setCommonICUDataPointer(uprv_getICUData_conversion(), FALSE, pErrorCode); } */ -#if U_PLATFORM_HAS_WINUWP_API == 0 // Windows UWP Platform does not support dll icu data at this time +#if !defined(ICU_DATA_DIR_WINDOWS) +// When using the Windows system data, we expect only a single data file. setCommonICUDataPointer(&U_ICUDATA_ENTRY_POINT, FALSE, pErrorCode); { Mutex lock; @@ -831,7 +835,7 @@ static UBool extendICUData(UErrorCode *pErr) * Use a specific mutex to avoid nested locks of the global mutex. */ #if MAP_IMPLEMENTATION==MAP_STDIO - static UMutex extendICUDataMutex = U_MUTEX_INITIALIZER; + static UMutex extendICUDataMutex; umtx_lock(&extendICUDataMutex); #endif if(!umtx_loadAcquire(gHaveTriedToLoadCommonData)) { @@ -1070,13 +1074,13 @@ static UDataMemory *doLoadFromCommonData(UBool isICUData, const char * /*pkgName /* look up the data piece in the common data */ pHeader=pCommonData->vFuncs->Lookup(pCommonData, tocEntryName, &length, subErrorCode); #ifdef UDATA_DEBUG - fprintf(stderr, "%s: pHeader=%p - %s\n", tocEntryName, pHeader, u_errorName(*subErrorCode)); + fprintf(stderr, "%s: pHeader=%p - %s\n", tocEntryName, (void*) pHeader, u_errorName(*subErrorCode)); #endif if(pHeader!=NULL) { pEntryData = checkDataItem(pHeader, isAcceptable, context, type, name, subErrorCode, pErrorCode); #ifdef UDATA_DEBUG - fprintf(stderr, "pEntryData=%p\n", pEntryData); + fprintf(stderr, "pEntryData=%p\n", (void*) pEntryData); #endif if (U_FAILURE(*pErrorCode)) { return NULL; @@ -1168,6 +1172,9 @@ doOpenChoice(const char *path, const char *type, const char *name, UBool isICUData = FALSE; + FileTracer::traceOpen(path, type, name); + + /* Is this path ICU data? */ if(path == NULL || !strcmp(path, U_ICUDATA_ALIAS) || /* "ICUDATA" */ @@ -1276,12 +1283,12 @@ doOpenChoice(const char *path, const char *type, const char *name, fprintf(stderr, " tocEntryPath = %s\n", tocEntryName.data()); #endif -#if U_PLATFORM_HAS_WINUWP_API == 0 // Windows UWP Platform does not support dll icu data at this time +#if !defined(ICU_DATA_DIR_WINDOWS) if(path == NULL) { path = COMMON_DATA_NAME; /* "icudt26e" */ } #else - // Windows UWP expects only a single data file. + // When using the Windows system data, we expects only a single data file. path = COMMON_DATA_NAME; /* "icudt26e" */ #endif diff --git a/deps/icu-small/source/common/uhash.cpp b/deps/icu-small/source/common/uhash.cpp index 79241a282913ed..86311ceb0b25d1 100644 --- a/deps/icu-small/source/common/uhash.cpp +++ b/deps/icu-small/source/common/uhash.cpp @@ -119,13 +119,14 @@ static const float RESIZE_POLICY_RATIO_TABLE[6] = { /* This macro expects a UHashTok.pointer as its keypointer and valuepointer parameters */ -#define HASH_DELETE_KEY_VALUE(hash, keypointer, valuepointer) \ - if (hash->keyDeleter != NULL && keypointer != NULL) { \ - (*hash->keyDeleter)(keypointer); \ - } \ - if (hash->valueDeleter != NULL && valuepointer != NULL) { \ - (*hash->valueDeleter)(valuepointer); \ - } +#define HASH_DELETE_KEY_VALUE(hash, keypointer, valuepointer) UPRV_BLOCK_MACRO_BEGIN { \ + if (hash->keyDeleter != NULL && keypointer != NULL) { \ + (*hash->keyDeleter)(keypointer); \ + } \ + if (hash->valueDeleter != NULL && valuepointer != NULL) { \ + (*hash->valueDeleter)(valuepointer); \ + } \ +} UPRV_BLOCK_MACRO_END /* * Constants for hinting whether a key or value is an integer diff --git a/deps/icu-small/source/common/uidna.cpp b/deps/icu-small/source/common/uidna.cpp index 6d56fcb8f517af..09347efd6d3c39 100644 --- a/deps/icu-small/source/common/uidna.cpp +++ b/deps/icu-small/source/common/uidna.cpp @@ -57,18 +57,16 @@ toASCIILower(UChar ch){ inline static UBool startsWithPrefix(const UChar* src , int32_t srcLength){ - UBool startsWithPrefix = TRUE; - if(srcLength < ACE_PREFIX_LENGTH){ return FALSE; } for(int8_t i=0; i< ACE_PREFIX_LENGTH; i++){ if(toASCIILower(src[i]) != ACE_PREFIX[i]){ - startsWithPrefix = FALSE; + return FALSE; } } - return startsWithPrefix; + return TRUE; } @@ -441,6 +439,7 @@ _internal_toUnicode(const UChar* src, int32_t srcLength, for(int32_t j=0; j 0x7f){ srcIsASCII = FALSE; + break; }/*else if(isLDHChar(src[j])==FALSE){ // here we do not assemble surrogates // since we know that LDH code points diff --git a/deps/icu-small/source/common/uinvchar.cpp b/deps/icu-small/source/common/uinvchar.cpp index 2e0f42d9274d2a..ac9716066f22b7 100644 --- a/deps/icu-small/source/common/uinvchar.cpp +++ b/deps/icu-small/source/common/uinvchar.cpp @@ -207,7 +207,8 @@ u_UCharsToChars(const UChar *us, char *cs, int32_t length) { while(length>0) { u=*us++; if(!UCHAR_IS_INVARIANT(u)) { - UPRV_UNREACHABLE; /* Variant characters were used. These are not portable in ICU. */ + U_ASSERT(FALSE); /* Variant characters were used. These are not portable in ICU. */ + u=0; } *cs++=(char)UCHAR_TO_CHAR(u); --length; @@ -445,6 +446,13 @@ uprv_copyEbcdic(const UDataSwapper *ds, return length; } +U_CFUNC UBool +uprv_isEbcdicAtSign(char c) { + static const uint8_t ebcdicAtSigns[] = { + 0x7C, 0x44, 0x66, 0x80, 0xAC, 0xAE, 0xAF, 0xB5, 0xEC, 0xEF, 0x00 }; + return c != 0 && uprv_strchr((const char *)ebcdicAtSigns, c) != nullptr; +} + /* compare invariant strings; variant characters compare less than others and unlike each other */ U_CFUNC int32_t uprv_compareInvAscii(const UDataSwapper *ds, @@ -561,6 +569,11 @@ uprv_compareInvEbcdicAsAscii(const char *s1, const char *s2) { } } +U_CAPI char U_EXPORT2 +uprv_ebcdicToAscii(char c) { + return (char)asciiFromEbcdic[(uint8_t)c]; +} + U_CAPI char U_EXPORT2 uprv_ebcdicToLowercaseAscii(char c) { return (char)lowercaseAsciiFromEbcdic[(uint8_t)c]; diff --git a/deps/icu-small/source/common/uinvchar.h b/deps/icu-small/source/common/uinvchar.h index 56dddfa8fde9bb..a43cfcd98286fe 100644 --- a/deps/icu-small/source/common/uinvchar.h +++ b/deps/icu-small/source/common/uinvchar.h @@ -68,6 +68,75 @@ uprv_isInvariantUString(const UChar *s, int32_t length); # error Unknown charset family! #endif +#ifdef __cplusplus + +U_NAMESPACE_BEGIN + +/** + * Like U_UPPER_ORDINAL(x) but with validation. + * Returns 0..25 for A..Z else a value outside 0..25. + */ +inline int32_t uprv_upperOrdinal(int32_t c) { +#if U_CHARSET_FAMILY==U_ASCII_FAMILY + return c - 'A'; +#elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY + // EBCDIC: A-Z (26 letters) is split into three ranges A-I (9 letters), J-R (9), S-Z (8). + // https://en.wikipedia.org/wiki/EBCDIC_037#Codepage_layout + if (c <= 'I') { return c - 'A'; } // A-I --> 0-8 + if (c < 'J') { return -1; } + if (c <= 'R') { return c - 'J' + 9; } // J-R --> 9..17 + if (c < 'S') { return -1; } + return c - 'S' + 18; // S-Z --> 18..25 +#else +# error Unknown charset family! +#endif +} + +// Like U_UPPER_ORDINAL(x) but for lowercase and with validation. +// Returns 0..25 for a..z else a value outside 0..25. +inline int32_t uprv_lowerOrdinal(int32_t c) { +#if U_CHARSET_FAMILY==U_ASCII_FAMILY + return c - 'a'; +#elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY + // EBCDIC: a-z (26 letters) is split into three ranges a-i (9 letters), j-r (9), s-z (8). + // https://en.wikipedia.org/wiki/EBCDIC_037#Codepage_layout + if (c <= 'i') { return c - 'a'; } // a-i --> 0-8 + if (c < 'j') { return -1; } + if (c <= 'r') { return c - 'j' + 9; } // j-r --> 9..17 + if (c < 's') { return -1; } + return c - 's' + 18; // s-z --> 18..25 +#else +# error Unknown charset family! +#endif +} + +U_NAMESPACE_END + +#endif + +/** + * Returns true if c == '@' is possible. + * The @ sign is variant, and the @ sign used on one + * EBCDIC machine won't be compiled the same way on other EBCDIC based machines. + * @internal + */ +U_CFUNC UBool +uprv_isEbcdicAtSign(char c); + +/** + * \def uprv_isAtSign + * Returns true if c == '@' is possible. + * For ASCII, checks for exactly '@'. For EBCDIC, calls uprv_isEbcdicAtSign(). + * @internal + */ +#if U_CHARSET_FAMILY==U_ASCII_FAMILY +# define uprv_isAtSign(c) ((c)=='@') +#elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY +# define uprv_isAtSign(c) uprv_isEbcdicAtSign(c) +#else +# error Unknown charset family! +#endif + /** * Compare two EBCDIC invariant-character strings in ASCII order. * @internal @@ -88,6 +157,26 @@ uprv_compareInvEbcdicAsAscii(const char *s1, const char *s2); # error Unknown charset family! #endif +/** + * Converts an EBCDIC invariant character to ASCII. + * @internal + */ +U_INTERNAL char U_EXPORT2 +uprv_ebcdicToAscii(char c); + +/** + * \def uprv_invCharToAscii + * Converts an invariant character to ASCII. + * @internal + */ +#if U_CHARSET_FAMILY==U_ASCII_FAMILY +# define uprv_invCharToAscii(c) (c) +#elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY +# define uprv_invCharToAscii(c) uprv_ebcdicToAscii(c) +#else +# error Unknown charset family! +#endif + /** * Converts an EBCDIC invariant character to lowercase ASCII. * @internal diff --git a/deps/icu-small/source/common/uloc.cpp b/deps/icu-small/source/common/uloc.cpp index 73b43204b814b9..6a9bfcfbff5999 100644 --- a/deps/icu-small/source/common/uloc.cpp +++ b/deps/icu-small/source/common/uloc.cpp @@ -148,7 +148,8 @@ static const char * const LANGUAGES[] = { "mad", "maf", "mag", "mai", "mak", "man", "mas", "mde", "mdf", "mdh", "mdr", "men", "mer", "mfe", "mg", "mga", "mgh", "mgo", "mh", "mi", "mic", "min", "mis", "mk", - "ml", "mn", "mnc", "mni", "moh", "mos", "mr", "mrj", + "ml", "mn", "mnc", "mni", "mo", + "moh", "mos", "mr", "mrj", "ms", "mt", "mua", "mul", "mus", "mwl", "mwr", "mwv", "my", "mye", "myv", "mzn", "na", "nan", "nap", "naq", "nb", "nd", "nds", "ne", @@ -264,7 +265,8 @@ static const char * const LANGUAGES_3[] = { "mad", "maf", "mag", "mai", "mak", "man", "mas", "mde", "mdf", "mdh", "mdr", "men", "mer", "mfe", "mlg", "mga", "mgh", "mgo", "mah", "mri", "mic", "min", "mis", "mkd", - "mal", "mon", "mnc", "mni", "moh", "mos", "mar", "mrj", + "mal", "mon", "mnc", "mni", "mol", + "moh", "mos", "mar", "mrj", "msa", "mlt", "mua", "mul", "mus", "mwl", "mwr", "mwv", "mya", "mye", "myv", "mzn", "nau", "nan", "nap", "naq", "nob", "nde", "nds", "nep", @@ -480,14 +482,15 @@ static const CanonicalizationMap CANONICALIZE_MAP[] = { /* Test if the locale id has BCP47 u extension and does not have '@' */ #define _hasBCP47Extension(id) (id && uprv_strstr(id, "@") == NULL && getShortestSubtagLength(localeID) == 1) /* Converts the BCP47 id to Unicode id. Does nothing to id if conversion fails */ -#define _ConvertBCP47(finalID, id, buffer, length,err) \ - if (uloc_forLanguageTag(id, buffer, length, NULL, err) <= 0 || \ - U_FAILURE(*err) || *err == U_STRING_NOT_TERMINATED_WARNING) { \ - finalID=id; \ - if (*err == U_STRING_NOT_TERMINATED_WARNING) { *err = U_BUFFER_OVERFLOW_ERROR; } \ - } else { \ - finalID=buffer; \ - } +#define _ConvertBCP47(finalID, id, buffer, length,err) UPRV_BLOCK_MACRO_BEGIN { \ + if (uloc_forLanguageTag(id, buffer, length, NULL, err) <= 0 || \ + U_FAILURE(*err) || *err == U_STRING_NOT_TERMINATED_WARNING) { \ + finalID=id; \ + if (*err == U_STRING_NOT_TERMINATED_WARNING) { *err = U_BUFFER_OVERFLOW_ERROR; } \ + } else { \ + finalID=buffer; \ + } \ +} UPRV_BLOCK_MACRO_END /* Gets the size of the shortest subtag in the given localeID. */ static int32_t getShortestSubtagLength(const char *localeID) { int32_t localeIDLength = static_cast(uprv_strlen(localeID)); @@ -1454,31 +1457,29 @@ static const UEnumeration gKeywordsEnum = { U_CAPI UEnumeration* U_EXPORT2 uloc_openKeywordList(const char *keywordList, int32_t keywordListSize, UErrorCode* status) { - UKeywordsContext *myContext = NULL; - UEnumeration *result = NULL; + LocalMemory myContext; + LocalMemory result; - if(U_FAILURE(*status)) { - return NULL; + if (U_FAILURE(*status)) { + return nullptr; } - result = (UEnumeration *)uprv_malloc(sizeof(UEnumeration)); - /* Null pointer test */ - if (result == NULL) { + myContext.adoptInstead(static_cast(uprv_malloc(sizeof(UKeywordsContext)))); + result.adoptInstead(static_cast(uprv_malloc(sizeof(UEnumeration)))); + if (myContext.isNull() || result.isNull()) { *status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } - uprv_memcpy(result, &gKeywordsEnum, sizeof(UEnumeration)); - myContext = static_cast(uprv_malloc(sizeof(UKeywordsContext))); - if (myContext == NULL) { + uprv_memcpy(result.getAlias(), &gKeywordsEnum, sizeof(UEnumeration)); + myContext->keywords = static_cast(uprv_malloc(keywordListSize+1)); + if (myContext->keywords == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; - uprv_free(result); - return NULL; + return nullptr; } - myContext->keywords = (char *)uprv_malloc(keywordListSize+1); uprv_memcpy(myContext->keywords, keywordList, keywordListSize); myContext->keywords[keywordListSize] = 0; myContext->current = myContext->keywords; - result->context = myContext; - return result; + result->context = myContext.orphan(); + return result.orphan(); } U_CAPI UEnumeration* U_EXPORT2 diff --git a/deps/icu-small/source/common/uloc_tag.cpp b/deps/icu-small/source/common/uloc_tag.cpp index c732170cb62b9c..8f673541a76504 100644 --- a/deps/icu-small/source/common/uloc_tag.cpp +++ b/deps/icu-small/source/common/uloc_tag.cpp @@ -1558,10 +1558,8 @@ _appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendT return; } - if (!_addAttributeToList(&attrFirst, attr)) { - *status = U_ILLEGAL_ARGUMENT_ERROR; - return; - } + // duplicate attribute is ignored, causes no error. + _addAttributeToList(&attrFirst, attr); /* next tag */ pTag += len; diff --git a/deps/icu-small/source/common/umutex.cpp b/deps/icu-small/source/common/umutex.cpp index 20b03d6cd3e416..ccbee9960a39e7 100644 --- a/deps/icu-small/source/common/umutex.cpp +++ b/deps/icu-small/source/common/umutex.cpp @@ -24,6 +24,7 @@ #include "unicode/utypes.h" #include "uassert.h" +#include "ucln_cmn.h" #include "cmemory.h" U_NAMESPACE_BEGIN @@ -35,60 +36,94 @@ U_NAMESPACE_BEGIN #error U_USER_MUTEX_CPP not supported #endif + /************************************************************************************************* * * ICU Mutex wrappers. * *************************************************************************************************/ -// The ICU global mutex. Used when ICU implementation code passes NULL for the mutex pointer. -static UMutex *globalMutex() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +namespace { +std::mutex *initMutex; +std::condition_variable *initCondition; -U_CAPI void U_EXPORT2 -umtx_lock(UMutex *mutex) { - if (mutex == nullptr) { - mutex = globalMutex(); - } - mutex->fMutex.lock(); -} +// The ICU global mutex. +// Used when ICU implementation code passes nullptr for the mutex pointer. +UMutex globalMutex; +std::once_flag initFlag; +std::once_flag *pInitFlag = &initFlag; -U_CAPI void U_EXPORT2 -umtx_unlock(UMutex* mutex) -{ - if (mutex == nullptr) { - mutex = globalMutex(); - } - mutex->fMutex.unlock(); -} +} // Anonymous namespace -UConditionVar::UConditionVar() : fCV() { +U_CDECL_BEGIN +static UBool U_CALLCONV umtx_cleanup() { + initMutex->~mutex(); + initCondition->~condition_variable(); + UMutex::cleanup(); + + // Reset the once_flag, by destructing it and creating a fresh one in its place. + // Do not use this trick anywhere else in ICU; use umtx_initOnce, not std::call_once(). + pInitFlag->~once_flag(); + pInitFlag = new(&initFlag) std::once_flag(); + return true; } -UConditionVar::~UConditionVar() { +static void U_CALLCONV umtx_init() { + initMutex = STATIC_NEW(std::mutex); + initCondition = STATIC_NEW(std::condition_variable); + ucln_common_registerCleanup(UCLN_COMMON_MUTEX, umtx_cleanup); +} +U_CDECL_END + + +std::mutex *UMutex::getMutex() { + std::mutex *retPtr = fMutex.load(std::memory_order_acquire); + if (retPtr == nullptr) { + std::call_once(*pInitFlag, umtx_init); + std::lock_guard guard(*initMutex); + retPtr = fMutex.load(std::memory_order_acquire); + if (retPtr == nullptr) { + fMutex = new(fStorage) std::mutex(); + retPtr = fMutex; + fListLink = gListHead; + gListHead = this; + } + } + U_ASSERT(retPtr != nullptr); + return retPtr; } -U_CAPI void U_EXPORT2 -umtx_condWait(UConditionVar *cond, UMutex *mutex) { - if (mutex == nullptr) { - mutex = globalMutex(); +UMutex *UMutex::gListHead = nullptr; + +void UMutex::cleanup() { + UMutex *next = nullptr; + for (UMutex *m = gListHead; m != nullptr; m = next) { + (*m->fMutex).~mutex(); + m->fMutex = nullptr; + next = m->fListLink; + m->fListLink = nullptr; } - cond->fCV.wait(mutex->fMutex); + gListHead = nullptr; } -U_CAPI void U_EXPORT2 -umtx_condBroadcast(UConditionVar *cond) { - cond->fCV.notify_all(); +U_CAPI void U_EXPORT2 +umtx_lock(UMutex *mutex) { + if (mutex == nullptr) { + mutex = &globalMutex; + } + mutex->lock(); } -U_CAPI void U_EXPORT2 -umtx_condSignal(UConditionVar *cond) { - cond->fCV.notify_one(); +U_CAPI void U_EXPORT2 +umtx_unlock(UMutex* mutex) +{ + if (mutex == nullptr) { + mutex = &globalMutex; + } + mutex->unlock(); } @@ -98,17 +133,6 @@ umtx_condSignal(UConditionVar *cond) { * *************************************************************************************************/ -static std::mutex &initMutex() { - static std::mutex m; - return m; -} - -static std::condition_variable &initCondition() { - static std::condition_variable cv; - return cv; -} - - // This function is called when a test of a UInitOnce::fState reveals that // initialization has not completed, that we either need to call the init // function on this thread, or wait for some other thread to complete. @@ -119,8 +143,8 @@ static std::condition_variable &initCondition() { // U_COMMON_API UBool U_EXPORT2 umtx_initImplPreInit(UInitOnce &uio) { - std::unique_lock lock(initMutex()); - + std::call_once(*pInitFlag, umtx_init); + std::unique_lock lock(*initMutex); if (umtx_loadAcquire(uio.fState) == 0) { umtx_storeRelease(uio.fState, 1); return true; // Caller will next call the init function. @@ -128,7 +152,7 @@ umtx_initImplPreInit(UInitOnce &uio) { while (umtx_loadAcquire(uio.fState) == 1) { // Another thread is currently running the initialization. // Wait until it completes. - initCondition().wait(lock); + initCondition->wait(lock); } U_ASSERT(uio.fState == 2); return false; @@ -145,10 +169,10 @@ umtx_initImplPreInit(UInitOnce &uio) { U_COMMON_API void U_EXPORT2 umtx_initImplPostInit(UInitOnce &uio) { { - std::unique_lock lock(initMutex()); + std::unique_lock lock(*initMutex); umtx_storeRelease(uio.fState, 2); } - initCondition().notify_all(); + initCondition->notify_all(); } U_NAMESPACE_END diff --git a/deps/icu-small/source/common/umutex.h b/deps/icu-small/source/common/umutex.h index 1674d00bb2d59b..7588bcc5d9aed6 100755 --- a/deps/icu-small/source/common/umutex.h +++ b/deps/icu-small/source/common/umutex.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "unicode/utypes.h" #include "unicode/uclean.h" @@ -36,10 +37,11 @@ #error U_USER_ATOMICS and U_USER_MUTEX_H are not supported #endif - // Export an explicit template instantiation of std::atomic. // When building DLLs for Windows this is required as it is used as a data member of the exported SharedObject class. // See digitlst.h, pluralaffix.h, datefmt.h, and others for similar examples. +// +// Similar story for std::atomic, and the exported UMutex class. #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN && !defined(U_IN_DOXYGEN) #if defined(__clang__) || defined(_MSC_VER) #if defined(__clang__) @@ -48,12 +50,14 @@ #pragma clang diagnostic ignored "-Winstantiation-after-specialization" #endif template struct U_COMMON_API std::atomic; +template struct U_COMMON_API std::atomic; #if defined(__clang__) #pragma clang diagnostic pop #endif #elif defined(__GNUC__) // For GCC this class is already exported/visible, so no need for U_COMMON_API. template struct std::atomic; +template struct std::atomic; #endif #endif @@ -180,49 +184,78 @@ template void umtx_initOnce(UInitOnce &uio, void (U_CALLCONV *fp)(T, UE } } +// UMutex should be constexpr-constructible, so that no initialization code +// is run during startup. +// This works on all C++ libraries except MS VS before VS2019. +#if (defined(_CPPLIB_VER) && !defined(_MSVC_STL_VERSION)) || \ + (defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION < 142) + // (VS std lib older than VS2017) || (VS std lib version < VS2019) +# define UMUTEX_CONSTEXPR +#else +# define UMUTEX_CONSTEXPR constexpr +#endif -/************************************************************************************************* +/** + * UMutex - ICU Mutex class. * - * ICU Mutex wrappers. Originally wrapped operating system mutexes, giving the rest of ICU a - * platform independent set of mutex operations. Now vestigial, wrapping std::mutex only. - * For internal ICU use only. + * This is the preferred Mutex class for use within ICU implementation code. + * It is a thin wrapper over C++ std::mutex, with these additions: + * - Static instances are safe, not triggering static construction or destruction, + * and the associated order of construction or destruction issues. + * - Plumbed into u_cleanup() for destructing the underlying std::mutex, + * which frees any OS level resources they may be holding. * - *************************************************************************************************/ + * Limitations: + * - Static or global instances only. Cannot be heap allocated. Cannot appear as a + * member of another class. + * - No condition variables or other advanced features. If needed, you will need to use + * std::mutex and std::condition_variable directly. For an example, see unifiedcache.cpp + * + * Typical Usage: + * static UMutex myMutex; + * + * { + * Mutex lock(myMutex); + * ... // Do stuff that is protected by myMutex; + * } // myMutex is released when lock goes out of scope. + */ -struct UMutex : public icu::UMemory { - UMutex() = default; +class U_COMMON_API UMutex { +public: + UMUTEX_CONSTEXPR UMutex() {} ~UMutex() = default; + UMutex(const UMutex &other) = delete; UMutex &operator =(const UMutex &other) = delete; + void *operator new(size_t) = delete; - std::mutex fMutex = {}; // Note: struct - pubic members - because most access is from - // // plain C style functions (umtx_lock(), etc.) -}; + // requirements for C++ BasicLockable, allows UMutex to work with std::lock_guard + void lock() { + std::mutex *m = fMutex.load(std::memory_order_acquire); + if (m == nullptr) { m = getMutex(); } + m->lock(); + } + void unlock() { fMutex.load(std::memory_order_relaxed)->unlock(); } + static void cleanup(); -struct UConditionVar : public icu::UMemory { - U_COMMON_API UConditionVar(); - U_COMMON_API ~UConditionVar(); - UConditionVar(const UConditionVar &other) = delete; - UConditionVar &operator =(const UConditionVar &other) = delete; +private: + alignas(std::mutex) char fStorage[sizeof(std::mutex)] {}; + std::atomic fMutex { nullptr }; - std::condition_variable_any fCV; -}; + /** All initialized UMutexes are kept in a linked list, so that they can be found, + * and the underlying std::mutex destructed, by u_cleanup(). + */ + UMutex *fListLink { nullptr }; + static UMutex *gListHead; -#define U_MUTEX_INITIALIZER {} -#define U_CONDITION_INITIALIZER {} + /** Out-of-line function to lazily initialize a UMutex on first use. + * Initial fast check is inline, in lock(). The returned value may never + * be nullptr. + */ + std::mutex *getMutex(); +}; -// Implementation notes for UConditionVar: -// -// Use an out-of-line constructor to reduce problems with the ICU dependency checker. -// On Linux, the default constructor of std::condition_variable_any -// produces an in-line reference to global operator new(), which the -// dependency checker flags for any file that declares a UConditionVar. With -// an out-of-line constructor, the dependency is constrained to umutex.o -// -// Do not export (U_COMMON_API) the entire class, but only the constructor -// and destructor, to avoid Windows build problems with attempting to export the -// std::condition_variable_any. /* Lock a mutex. * @param mutex The given mutex to be locked. Pass NULL to specify @@ -237,30 +270,6 @@ U_INTERNAL void U_EXPORT2 umtx_lock(UMutex* mutex); */ U_INTERNAL void U_EXPORT2 umtx_unlock (UMutex* mutex); -/* - * Wait on a condition variable. - * The calling thread will unlock the mutex and wait on the condition variable. - * The mutex must be locked by the calling thread when invoking this function. - * - * @param cond the condition variable to wait on. - * @param mutex the associated mutex. - */ - -U_INTERNAL void U_EXPORT2 umtx_condWait(UConditionVar *cond, UMutex *mutex); - - -/* - * Broadcast wakeup of all threads waiting on a Condition. - * - * @param cond the condition variable. - */ -U_INTERNAL void U_EXPORT2 umtx_condBroadcast(UConditionVar *cond); - -/* - * Signal a condition variable, waking up one waiting thread. - */ -U_INTERNAL void U_EXPORT2 umtx_condSignal(UConditionVar *cond); - U_NAMESPACE_END diff --git a/deps/icu-small/source/common/unames.cpp b/deps/icu-small/source/common/unames.cpp index 038743004ea589..a28b6ee6036b96 100644 --- a/deps/icu-small/source/common/unames.cpp +++ b/deps/icu-small/source/common/unames.cpp @@ -212,13 +212,13 @@ isDataLoaded(UErrorCode *pErrorCode) { return U_SUCCESS(*pErrorCode); } -#define WRITE_CHAR(buffer, bufferLength, bufferPos, c) { \ +#define WRITE_CHAR(buffer, bufferLength, bufferPos, c) UPRV_BLOCK_MACRO_BEGIN { \ if((bufferLength)>0) { \ *(buffer)++=c; \ --(bufferLength); \ } \ ++(bufferPos); \ -} +} UPRV_BLOCK_MACRO_END #define U_ISO_COMMENT U_CHAR_NAME_CHOICE_COUNT diff --git a/deps/icu-small/source/common/unicode/appendable.h b/deps/icu-small/source/common/unicode/appendable.h index 8512c2f30311b8..4beacaf6583620 100644 --- a/deps/icu-small/source/common/unicode/appendable.h +++ b/deps/icu-small/source/common/unicode/appendable.h @@ -23,6 +23,9 @@ */ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" U_NAMESPACE_BEGIN @@ -231,4 +234,6 @@ class U_COMMON_API UnicodeStringAppendable : public Appendable { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __APPENDABLE_H__ diff --git a/deps/icu-small/source/common/unicode/brkiter.h b/deps/icu-small/source/common/unicode/brkiter.h index ac1bf1df29f214..b944497345479b 100644 --- a/deps/icu-small/source/common/unicode/brkiter.h +++ b/deps/icu-small/source/common/unicode/brkiter.h @@ -29,6 +29,10 @@ * \brief C++ API: Break Iterator. */ +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #if UCONFIG_NO_BREAK_ITERATION U_NAMESPACE_BEGIN @@ -135,7 +139,7 @@ class U_COMMON_API BreakIterator : public UObject { * method which subclasses implement. * @stable ICU 2.0 */ - virtual BreakIterator* clone(void) const = 0; + virtual BreakIterator* clone() const = 0; /** * Return a polymorphic class ID for this object. Different subclasses @@ -493,6 +497,7 @@ class U_COMMON_API BreakIterator : public UObject { static UnicodeString& U_EXPORT2 getDisplayName(const Locale& objectLocale, UnicodeString& name); +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Deprecated functionality. Use clone() instead. * @@ -515,6 +520,7 @@ class U_COMMON_API BreakIterator : public UObject { virtual BreakIterator * createBufferClone(void *stackBuffer, int32_t &BufferSize, UErrorCode &status) = 0; +#endif // U_FORCE_HIDE_DEPRECATED_API #ifndef U_HIDE_DEPRECATED_API @@ -658,5 +664,7 @@ U_NAMESPACE_END #endif /* #if !UCONFIG_NO_BREAK_ITERATION */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // BRKITER_H //eof diff --git a/deps/icu-small/source/common/unicode/bytestream.h b/deps/icu-small/source/common/unicode/bytestream.h index 61d1e8aca651d7..2c71c248e3dfa0 100644 --- a/deps/icu-small/source/common/unicode/bytestream.h +++ b/deps/icu-small/source/common/unicode/bytestream.h @@ -38,6 +38,9 @@ */ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" #include "unicode/std_string.h" @@ -267,4 +270,6 @@ class StringByteSink : public ByteSink { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __BYTESTREAM_H__ diff --git a/deps/icu-small/source/common/unicode/bytestrie.h b/deps/icu-small/source/common/unicode/bytestrie.h index c57b8ccfeb5960..51405f64a10e64 100644 --- a/deps/icu-small/source/common/unicode/bytestrie.h +++ b/deps/icu-small/source/common/unicode/bytestrie.h @@ -23,6 +23,9 @@ */ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/stringpiece.h" #include "unicode/uobject.h" #include "unicode/ustringtrie.h" @@ -94,6 +97,41 @@ class U_COMMON_API BytesTrie : public UMemory { return *this; } +#ifndef U_HIDE_DRAFT_API + /** + * Returns the state of this trie as a 64-bit integer. + * The state value is never 0. + * + * @return opaque state value + * @see resetToState64 + * @draft ICU 65 + */ + uint64_t getState64() const { + return (static_cast(remainingMatchLength_ + 2) << kState64RemainingShift) | + (uint64_t)(pos_ - bytes_); + } + + /** + * Resets this trie to the saved state. + * Unlike resetToState(State), the 64-bit state value + * must be from getState64() from the same trie object or + * from one initialized the exact same way. + * Because of no validation, this method is faster. + * + * @param state The opaque trie state value from getState64(). + * @return *this + * @see getState64 + * @see resetToState + * @see reset + * @draft ICU 65 + */ + BytesTrie &resetToState64(uint64_t state) { + remainingMatchLength_ = static_cast(state >> kState64RemainingShift) - 2; + pos_ = bytes_ + (state & kState64PosMask); + return *this; + } +#endif /* U_HIDE_DRAFT_API */ + /** * BytesTrie state object, for saving a trie's current state * and resetting the trie back to this state later. @@ -502,6 +540,13 @@ class U_COMMON_API BytesTrie : public UMemory { static const int32_t kMaxTwoByteDelta=((kMinThreeByteDeltaLead-kMinTwoByteDeltaLead)<<8)-1; // 0x2fff static const int32_t kMaxThreeByteDelta=((kFourByteDeltaLead-kMinThreeByteDeltaLead)<<16)-1; // 0xdffff + // For getState64(): + // The remainingMatchLength_ is -1..14=(kMaxLinearMatchLength=0x10)-2 + // so we need at least 5 bits for that. + // We add 2 to store it as a positive value 1..16=kMaxLinearMatchLength. + static constexpr int32_t kState64RemainingShift = 59; + static constexpr uint64_t kState64PosMask = (UINT64_C(1) << kState64RemainingShift) - 1; + uint8_t *ownedArray_; // Fixed value referencing the BytesTrie bytes. @@ -517,4 +562,6 @@ class U_COMMON_API BytesTrie : public UMemory { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __BYTESTRIE_H__ diff --git a/deps/icu-small/source/common/unicode/bytestriebuilder.h b/deps/icu-small/source/common/unicode/bytestriebuilder.h index b164e3bbd685f7..e58f18755ef959 100644 --- a/deps/icu-small/source/common/unicode/bytestriebuilder.h +++ b/deps/icu-small/source/common/unicode/bytestriebuilder.h @@ -23,6 +23,9 @@ #define __BYTESTRIEBUILDER_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/bytestrie.h" #include "unicode/stringpiece.h" #include "unicode/stringtriebuilder.h" @@ -179,4 +182,6 @@ class U_COMMON_API BytesTrieBuilder : public StringTrieBuilder { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __BYTESTRIEBUILDER_H__ diff --git a/deps/icu-small/source/common/unicode/caniter.h b/deps/icu-small/source/common/unicode/caniter.h index b47e35da07bb7f..87c946c2b4db56 100644 --- a/deps/icu-small/source/common/unicode/caniter.h +++ b/deps/icu-small/source/common/unicode/caniter.h @@ -12,6 +12,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_NORMALIZATION #include "unicode/uobject.h" @@ -207,4 +209,6 @@ U_NAMESPACE_END #endif /* #if !UCONFIG_NO_NORMALIZATION */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/casemap.h b/deps/icu-small/source/common/unicode/casemap.h index 477eb484d136b6..53af84fa74d65f 100644 --- a/deps/icu-small/source/common/unicode/casemap.h +++ b/deps/icu-small/source/common/unicode/casemap.h @@ -8,6 +8,9 @@ #define __CASEMAP_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/stringpiece.h" #include "unicode/uobject.h" @@ -489,4 +492,6 @@ class U_COMMON_API CaseMap U_FINAL : public UMemory { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __CASEMAP_H__ diff --git a/deps/icu-small/source/common/unicode/char16ptr.h b/deps/icu-small/source/common/unicode/char16ptr.h index a7c5f1a0c5ed56..c8a9ae6c35d646 100644 --- a/deps/icu-small/source/common/unicode/char16ptr.h +++ b/deps/icu-small/source/common/unicode/char16ptr.h @@ -7,9 +7,12 @@ #ifndef __CHAR16PTR_H__ #define __CHAR16PTR_H__ -#include #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + +#include + /** * \file * \brief C++ API: char16_t pointer wrappers with @@ -305,4 +308,6 @@ inline OldUChar *toOldUCharPtr(char16_t *p) { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __CHAR16PTR_H__ diff --git a/deps/icu-small/source/common/unicode/chariter.h b/deps/icu-small/source/common/unicode/chariter.h index 292794f6d65832..7e4f446bb0f8a8 100644 --- a/deps/icu-small/source/common/unicode/chariter.h +++ b/deps/icu-small/source/common/unicode/chariter.h @@ -13,6 +13,9 @@ #define CHARITER_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" #include "unicode/unistr.h" /** @@ -377,7 +380,7 @@ class U_COMMON_API CharacterIterator : public ForwardCharacterIterator { * @return a pointer to a new CharacterIterator * @stable ICU 2.0 */ - virtual CharacterIterator* clone(void) const = 0; + virtual CharacterIterator* clone() const = 0; /** * Sets the iterator to refer to the first code unit in its @@ -725,4 +728,7 @@ CharacterIterator::getLength(void) const { } U_NAMESPACE_END + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/dbbi.h b/deps/icu-small/source/common/unicode/dbbi.h index 62509c5227b9da..9031c0b96b1b40 100644 --- a/deps/icu-small/source/common/unicode/dbbi.h +++ b/deps/icu-small/source/common/unicode/dbbi.h @@ -13,6 +13,10 @@ #ifndef DBBI_H #define DBBI_H +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/rbbi.h" #if !UCONFIG_NO_BREAK_ITERATION @@ -39,4 +43,6 @@ U_NAMESPACE_END #endif /* #if !UCONFIG_NO_BREAK_ITERATION */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/docmain.h b/deps/icu-small/source/common/unicode/docmain.h index 89906799877622..2b38692997dd9a 100644 --- a/deps/icu-small/source/common/unicode/docmain.h +++ b/deps/icu-small/source/common/unicode/docmain.h @@ -99,7 +99,7 @@ * * * Codepage Conversion - * ucnv.h, ucnvsel.hb + * ucnv.h, ucnvsel.h * C API * * @@ -115,7 +115,7 @@ * * Locales * uloc.h - * icu::Locale, icu::LocaleBuilder + * icu::Locale, icu::LocaleBuilder, icu::LocaleMatcher * * * Resource Bundles diff --git a/deps/icu-small/source/common/unicode/dtintrv.h b/deps/icu-small/source/common/unicode/dtintrv.h index 625456f0c868e9..325faa3ccb92cb 100644 --- a/deps/icu-small/source/common/unicode/dtintrv.h +++ b/deps/icu-small/source/common/unicode/dtintrv.h @@ -15,6 +15,9 @@ #define __DTINTRV_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" /** @@ -22,7 +25,6 @@ * \brief C++ API: Date Interval data type */ - U_NAMESPACE_BEGIN @@ -157,4 +159,6 @@ DateInterval::operator!=(const DateInterval& other) const { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/edits.h b/deps/icu-small/source/common/unicode/edits.h index 79e98b0cc27ac6..c3ceaccb3b3802 100644 --- a/deps/icu-small/source/common/unicode/edits.h +++ b/deps/icu-small/source/common/unicode/edits.h @@ -8,6 +8,9 @@ #define __EDITS_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" /** @@ -159,7 +162,7 @@ class U_COMMON_API Edits U_FINAL : public UMemory { * @return TRUE if U_FAILURE(outErrorCode) * @stable ICU 59 */ - UBool copyErrorTo(UErrorCode &outErrorCode); + UBool copyErrorTo(UErrorCode &outErrorCode) const; /** * How much longer is the new text compared with the old text? @@ -523,4 +526,6 @@ class U_COMMON_API Edits U_FINAL : public UMemory { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __EDITS_H__ diff --git a/deps/icu-small/source/common/unicode/errorcode.h b/deps/icu-small/source/common/unicode/errorcode.h index 1e5df8f03e88fe..75cdbb6a98f194 100644 --- a/deps/icu-small/source/common/unicode/errorcode.h +++ b/deps/icu-small/source/common/unicode/errorcode.h @@ -26,6 +26,9 @@ */ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" U_NAMESPACE_BEGIN @@ -136,4 +139,6 @@ class U_COMMON_API ErrorCode: public UMemory { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __ERRORCODE_H__ diff --git a/deps/icu-small/source/common/unicode/filteredbrk.h b/deps/icu-small/source/common/unicode/filteredbrk.h index 2444114e9a14bf..42936763259e2d 100644 --- a/deps/icu-small/source/common/unicode/filteredbrk.h +++ b/deps/icu-small/source/common/unicode/filteredbrk.h @@ -11,6 +11,9 @@ #define FILTEREDBRK_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/brkiter.h" #if !UCONFIG_NO_BREAK_ITERATION && !UCONFIG_NO_FILTERED_BREAK_ITERATION @@ -101,6 +104,7 @@ class U_COMMON_API FilteredBreakIteratorBuilder : public UObject { */ virtual UBool unsuppressBreakAfter(const UnicodeString& string, UErrorCode& status) = 0; +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * This function has been deprecated in favor of wrapIteratorWithFilter() * The behavior is identical. @@ -111,6 +115,7 @@ class U_COMMON_API FilteredBreakIteratorBuilder : public UObject { * @see wrapBreakIteratorWithFilter() */ virtual BreakIterator *build(BreakIterator* adoptBreakIterator, UErrorCode& status) = 0; +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Wrap (adopt) an existing break iterator in a new filtered instance. @@ -142,4 +147,6 @@ U_NAMESPACE_END #endif // #if !UCONFIG_NO_BREAK_ITERATION && !UCONFIG_NO_FILTERED_BREAK_ITERATION +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // #ifndef FILTEREDBRK_H diff --git a/deps/icu-small/source/common/unicode/idna.h b/deps/icu-small/source/common/unicode/idna.h index f08658e502e200..6dfcfe48db28f1 100644 --- a/deps/icu-small/source/common/unicode/idna.h +++ b/deps/icu-small/source/common/unicode/idna.h @@ -24,6 +24,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_IDNA #include "unicode/bytestream.h" @@ -322,4 +324,7 @@ class U_COMMON_API IDNAInfo : public UMemory { U_NAMESPACE_END #endif // UCONFIG_NO_IDNA + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __IDNA_H__ diff --git a/deps/icu-small/source/common/unicode/localebuilder.h b/deps/icu-small/source/common/unicode/localebuilder.h index 960e5980c03c2e..19e10f1c070924 100644 --- a/deps/icu-small/source/common/unicode/localebuilder.h +++ b/deps/icu-small/source/common/unicode/localebuilder.h @@ -3,11 +3,14 @@ #ifndef __LOCALEBUILDER_H__ #define __LOCALEBUILDER_H__ +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/locid.h" +#include "unicode/localematcher.h" #include "unicode/stringpiece.h" #include "unicode/uobject.h" -#include "unicode/utypes.h" - #ifndef U_HIDE_DRAFT_API /** @@ -276,7 +279,24 @@ class U_COMMON_API LocaleBuilder : public UObject { */ Locale build(UErrorCode& status); +#ifndef U_HIDE_DRAFT_API + /** + * Sets the UErrorCode if an error occurred while recording sets. + * Preserves older error codes in the outErrorCode. + * @param outErrorCode Set to an error code that occurred while setting subtags. + * Unchanged if there is no such error or if outErrorCode + * already contained an error. + * @return TRUE if U_FAILURE(outErrorCode) + * @draft ICU 65 + */ + UBool copyErrorTo(UErrorCode &outErrorCode) const; +#endif /* U_HIDE_DRAFT_API */ + private: + friend class LocaleMatcher::Result; + + void copyExtensionsFrom(const Locale& src, UErrorCode& errorCode); + UErrorCode status_; char language_[9]; char script_[5]; @@ -289,4 +309,7 @@ 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 new file mode 100644 index 00000000000000..701123f750b222 --- /dev/null +++ b/deps/icu-small/source/common/unicode/localematcher.h @@ -0,0 +1,605 @@ +// © 2019 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html#License + +// localematcher.h +// created: 2019may08 Markus W. Scherer + +#ifndef __LOCALEMATCHER_H__ +#define __LOCALEMATCHER_H__ + +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + +#include "unicode/locid.h" +#include "unicode/stringpiece.h" +#include "unicode/uobject.h" + +/** + * \file + * \brief C++ API: Locale matcher: User's desired locales vs. application's supported locales. + */ + +#ifndef U_HIDE_DRAFT_API + +/** + * Builder option for whether the language subtag or the script subtag is most important. + * + * @see Builder#setFavorSubtag(FavorSubtag) + * @draft ICU 65 + */ +enum ULocMatchFavorSubtag { + /** + * Language differences are most important, then script differences, then region differences. + * (This is the default behavior.) + * + * @draft ICU 65 + */ + ULOCMATCH_FAVOR_LANGUAGE, + /** + * Makes script differences matter relatively more than language differences. + * + * @draft ICU 65 + */ + ULOCMATCH_FAVOR_SCRIPT +}; +#ifndef U_IN_DOXYGEN +typedef enum ULocMatchFavorSubtag ULocMatchFavorSubtag; +#endif + +/** + * Builder option for whether all desired locales are treated equally or + * earlier ones are preferred. + * + * @see Builder#setDemotionPerDesiredLocale(Demotion) + * @draft ICU 65 + */ +enum ULocMatchDemotion { + /** + * All desired locales are treated equally. + * + * @draft ICU 65 + */ + ULOCMATCH_DEMOTION_NONE, + /** + * Earlier desired locales are preferred. + * + *

From each desired locale to the next, + * the distance to any supported locale is increased by an additional amount + * which is at least as large as most region mismatches. + * A later desired locale has to have a better match with some supported locale + * due to more than merely having the same region subtag. + * + *

For example: Supported={en, sv} desired=[en-GB, sv] + * yields Result(en-GB, en) because + * with the demotion of sv its perfect match is no better than + * the region distance between the earlier desired locale en-GB and en=en-US. + * + *

Notes: + *

    + *
  • In some cases, language and/or script differences can be as small as + * the typical region difference. (Example: sr-Latn vs. sr-Cyrl) + *
  • It is possible for certain region differences to be larger than usual, + * and larger than the demotion. + * (As of CLDR 35 there is no such case, but + * this is possible in future versions of the data.) + *
+ * + * @draft ICU 65 + */ + ULOCMATCH_DEMOTION_REGION +}; +#ifndef U_IN_DOXYGEN +typedef enum ULocMatchDemotion ULocMatchDemotion; +#endif + +struct UHashtable; + +U_NAMESPACE_BEGIN + +struct LSR; + +class LocaleDistance; +class LocaleLsrIterator; +class UVector; +class XLikelySubtags; + +/** + * Immutable class that picks the best match between a user's desired locales and + * an application's supported locales. + * Movable but not copyable. + * + *

Example: + *

+ * UErrorCode errorCode = U_ZERO_ERROR;
+ * LocaleMatcher matcher = LocaleMatcher::Builder().setSupportedLocales("fr, en-GB, en").build(errorCode);
+ * Locale *bestSupported = matcher.getBestLocale(Locale.US, errorCode);  // "en"
+ * 
+ * + *

A matcher takes into account when languages are close to one another, + * such as Danish and Norwegian, + * and when regional variants are close, like en-GB and en-AU as opposed to en-US. + * + *

If there are multiple supported locales with the same (language, script, region) + * likely subtags, then the current implementation returns the first of those locales. + * It ignores variant subtags (except for pseudolocale variants) and extensions. + * This may change in future versions. + * + *

For example, the current implementation does not distinguish between + * de, de-DE, de-Latn, de-1901, de-u-co-phonebk. + * + *

If you prefer one equivalent locale over another, then provide only the preferred one, + * or place it earlier in the list of supported locales. + * + *

Otherwise, the order of supported locales may have no effect on the best-match results. + * The current implementation compares each desired locale with supported locales + * in the following order: + * 1. Default locale, if supported; + * 2. CLDR "paradigm locales" like en-GB and es-419; + * 3. other supported locales. + * This may change in future versions. + * + *

Often a product will just need one matcher instance, built with the languages + * that it supports. However, it may want multiple instances with different + * default languages based on additional information, such as the domain. + * + *

This class is not intended for public subclassing. + * + * @draft ICU 65 + */ +class U_COMMON_API LocaleMatcher : public UMemory { +public: + /** + * Data for the best-matching pair of a desired and a supported locale. + * Movable but not copyable. + * + * @draft ICU 65 + */ + class U_COMMON_API Result : public UMemory { + public: + /** + * Move constructor; might modify the source. + * This object will have the same contents that the source object had. + * + * @param src Result to move contents from. + * @draft ICU 65 + */ + Result(Result &&src) U_NOEXCEPT; + + /** + * Destructor. + * + * @draft ICU 65 + */ + ~Result(); + + /** + * Move assignment; might modify the source. + * This object will have the same contents that the source object had. + * + * @param src Result to move contents from. + * @draft ICU 65 + */ + Result &operator=(Result &&src) U_NOEXCEPT; + + /** + * Returns the best-matching desired locale. + * nullptr if the list of desired locales is empty or if none matched well enough. + * + * @return the best-matching desired locale, or nullptr. + * @draft ICU 65 + */ + inline const Locale *getDesiredLocale() const { return desiredLocale; } + + /** + * Returns the best-matching supported locale. + * If none matched well enough, this is the default locale. + * The default locale is nullptr if the list of supported locales is empty and + * no explicit default locale is set. + * + * @return the best-matching supported locale, or nullptr. + * @draft ICU 65 + */ + inline const Locale *getSupportedLocale() const { return supportedLocale; } + + /** + * Returns the index of the best-matching desired locale in the input Iterable order. + * -1 if the list of desired locales is empty or if none matched well enough. + * + * @return the index of the best-matching desired locale, or -1. + * @draft ICU 65 + */ + inline int32_t getDesiredIndex() const { return desiredIndex; } + + /** + * Returns the index of the best-matching supported locale in the + * constructor’s or builder’s input order (“set” Collection plus “added” locales). + * If the matcher was built from a locale list string, then the iteration order is that + * of a LocalePriorityList built from the same string. + * -1 if the list of supported locales is empty or if none matched well enough. + * + * @return the index of the best-matching supported locale, or -1. + * @draft ICU 65 + */ + inline int32_t getSupportedIndex() const { return supportedIndex; } + + /** + * Takes the best-matching supported locale and adds relevant fields of the + * best-matching desired locale, such as the -t- and -u- extensions. + * May replace some fields of the supported locale. + * The result is the locale that should be used for date and number formatting, collation, etc. + * Returns the root locale if getSupportedLocale() returns nullptr. + * + *

Example: desired=ar-SA-u-nu-latn, supported=ar-EG, resolved locale=ar-SA-u-nu-latn + * + * @return a locale combining the best-matching desired and supported locales. + * @draft ICU 65 + */ + Locale makeResolvedLocale(UErrorCode &errorCode) const; + + private: + Result(const Locale *desired, const Locale *supported, + int32_t desIndex, int32_t suppIndex, UBool owned) : + desiredLocale(desired), supportedLocale(supported), + desiredIndex(desIndex), supportedIndex(suppIndex), + desiredIsOwned(owned) {} + + Result(const Result &other) = delete; + Result &operator=(const Result &other) = delete; + + const Locale *desiredLocale; + const Locale *supportedLocale; + int32_t desiredIndex; + int32_t supportedIndex; + UBool desiredIsOwned; + + friend class LocaleMatcher; + }; + + /** + * LocaleMatcher builder. + * Movable but not copyable. + * + * @see LocaleMatcher#builder() + * @draft ICU 65 + */ + class U_COMMON_API Builder : public UMemory { + public: + /** + * Constructs a builder used in chaining parameters for building a LocaleMatcher. + * + * @return a new Builder object + * @draft ICU 65 + */ + Builder() {} + + /** + * Move constructor; might modify the source. + * This builder will have the same contents that the source builder had. + * + * @param src Builder to move contents from. + * @draft ICU 65 + */ + Builder(Builder &&src) U_NOEXCEPT; + + /** + * Destructor. + * + * @draft ICU 65 + */ + ~Builder(); + + /** + * Move assignment; might modify the source. + * This builder will have the same contents that the source builder had. + * + * @param src Builder to move contents from. + * @draft ICU 65 + */ + Builder &operator=(Builder &&src) U_NOEXCEPT; + + /** + * Parses an Accept-Language string + * (RFC 2616 Section 14.4), + * such as "af, en, fr;q=0.9", and sets the supported locales accordingly. + * Allows whitespace in more places but does not allow "*". + * Clears any previously set/added supported locales first. + * + * @param locales the Accept-Language string of locales to set + * @return this Builder object + * @draft ICU 65 + */ + Builder &setSupportedLocalesFromListString(StringPiece locales); + + /** + * Copies the supported locales, preserving iteration order. + * Clears any previously set/added supported locales first. + * Duplicates are allowed, and are not removed. + * + * @param locales the list of locale + * @return this Builder object + * @draft ICU 65 + */ + Builder &setSupportedLocales(Locale::Iterator &locales); + + /** + * Copies the supported locales from the begin/end range, preserving iteration order. + * Clears any previously set/added supported locales first. + * Duplicates are allowed, and are not removed. + * + * Each of the iterator parameter values must be an + * input iterator whose value is convertible to const Locale &. + * + * @param begin Start of range. + * @param end Exclusive end of range. + * @return this Builder object + * @draft ICU 65 + */ + template + Builder &setSupportedLocales(Iter begin, Iter end) { + if (U_FAILURE(errorCode_)) { return *this; } + clearSupportedLocales(); + while (begin != end) { + addSupportedLocale(*begin++); + } + return *this; + } + + /** + * Copies the supported locales from the begin/end range, preserving iteration order. + * Calls the converter to convert each *begin to a Locale or const Locale &. + * Clears any previously set/added supported locales first. + * Duplicates are allowed, and are not removed. + * + * Each of the iterator parameter values must be an + * input iterator whose value is convertible to const Locale &. + * + * @param begin Start of range. + * @param end Exclusive end of range. + * @param converter Converter from *begin to const Locale & or compatible. + * @return this Builder object + * @draft ICU 65 + */ + template + Builder &setSupportedLocalesViaConverter(Iter begin, Iter end, Conv converter) { + if (U_FAILURE(errorCode_)) { return *this; } + clearSupportedLocales(); + while (begin != end) { + addSupportedLocale(converter(*begin++)); + } + return *this; + } + + /** + * Adds another supported locale. + * Duplicates are allowed, and are not removed. + * + * @param locale another locale + * @return this Builder object + * @draft ICU 65 + */ + Builder &addSupportedLocale(const Locale &locale); + + /** + * Sets the default locale; if nullptr, or if it is not set explicitly, + * then the first supported locale is used as the default locale. + * + * @param defaultLocale the default locale (will be copied) + * @return this Builder object + * @draft ICU 65 + */ + Builder &setDefaultLocale(const Locale *defaultLocale); + + /** + * If ULOCMATCH_FAVOR_SCRIPT, then the language differences are smaller than script + * differences. + * This is used in situations (such as maps) where + * it is better to fall back to the same script than a similar language. + * + * @param subtag the subtag to favor + * @return this Builder object + * @draft ICU 65 + */ + Builder &setFavorSubtag(ULocMatchFavorSubtag subtag); + + /** + * Option for whether all desired locales are treated equally or + * earlier ones are preferred (this is the default). + * + * @param demotion the demotion per desired locale to set. + * @return this Builder object + * @draft ICU 65 + */ + Builder &setDemotionPerDesiredLocale(ULocMatchDemotion demotion); + + /** + * Sets the UErrorCode if an error occurred while setting parameters. + * Preserves older error codes in the outErrorCode. + * + * @param outErrorCode Set to an error code if it does not contain one already + * and an error occurred while setting parameters. + * Otherwise unchanged. + * @return TRUE if U_FAILURE(outErrorCode) + * @draft ICU 65 + */ + UBool copyErrorTo(UErrorCode &outErrorCode) const; + + /** + * Builds and returns a new locale matcher. + * This builder can continue to be used. + * + * @param errorCode 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 new LocaleMatcher. + * @draft ICU 65 + */ + LocaleMatcher build(UErrorCode &errorCode) const; + + private: + friend class LocaleMatcher; + + Builder(const Builder &other) = delete; + Builder &operator=(const Builder &other) = delete; + + void clearSupportedLocales(); + bool ensureSupportedLocaleVector(); + + UErrorCode errorCode_ = U_ZERO_ERROR; + UVector *supportedLocales_ = nullptr; + int32_t thresholdDistance_ = -1; + ULocMatchDemotion demotion_ = ULOCMATCH_DEMOTION_REGION; + Locale *defaultLocale_ = nullptr; + ULocMatchFavorSubtag favor_ = ULOCMATCH_FAVOR_LANGUAGE; + }; + + // FYI No public LocaleMatcher constructors in C++; use the Builder. + + /** + * Move copy constructor; might modify the source. + * This matcher will have the same settings that the source matcher had. + * @param src source matcher + * @draft ICU 65 + */ + LocaleMatcher(LocaleMatcher &&src) U_NOEXCEPT; + + /** + * Destructor. + * @draft ICU 65 + */ + ~LocaleMatcher(); + + /** + * Move assignment operator; might modify the source. + * This matcher will have the same settings that the source matcher had. + * The behavior is undefined if *this and src are the same object. + * @param src source matcher + * @return *this + * @draft ICU 65 + */ + LocaleMatcher &operator=(LocaleMatcher &&src) U_NOEXCEPT; + + /** + * Returns the supported locale which best matches the desired locale. + * + * @param desiredLocale Typically a user's language. + * @param errorCode 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 the best-matching supported locale. + * @draft ICU 65 + */ + const Locale *getBestMatch(const Locale &desiredLocale, UErrorCode &errorCode) const; + + /** + * Returns the supported locale which best matches one of the desired locales. + * + * @param desiredLocales Typically a user's languages, in order of preference (descending). + * @param errorCode 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 the best-matching supported locale. + * @draft ICU 65 + */ + const Locale *getBestMatch(Locale::Iterator &desiredLocales, UErrorCode &errorCode) const; + + /** + * Parses an Accept-Language string + * (RFC 2616 Section 14.4), + * such as "af, en, fr;q=0.9", + * and returns the supported locale which best matches one of the desired locales. + * Allows whitespace in more places but does not allow "*". + * + * @param desiredLocaleList Typically a user's languages, as an Accept-Language string. + * @param errorCode 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 the best-matching supported locale. + * @draft ICU 65 + */ + const Locale *getBestMatchForListString(StringPiece desiredLocaleList, UErrorCode &errorCode) const; + + /** + * Returns the best match between the desired locale and the supported locales. + * If the result's desired locale is not nullptr, then it is the address of the input locale. + * It has not been cloned. + * + * @param desiredLocale Typically a user's language. + * @param errorCode 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 the best-matching pair of the desired and a supported locale. + * @draft ICU 65 + */ + Result getBestMatchResult(const Locale &desiredLocale, UErrorCode &errorCode) const; + + /** + * Returns the best match between the desired and supported locales. + * If the result's desired locale is not nullptr, then it is a clone of + * the best-matching desired locale. The Result object owns the clone. + * + * @param desiredLocales Typically a user's languages, in order of preference (descending). + * @param errorCode 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 the best-matching pair of a desired and a supported locale. + * @draft ICU 65 + */ + Result getBestMatchResult(Locale::Iterator &desiredLocales, UErrorCode &errorCode) const; + +#ifndef U_HIDE_INTERNAL_API + /** + * Returns a fraction between 0 and 1, where 1 means that the languages are a + * perfect match, and 0 means that they are completely different. + * + *

This is mostly an implementation detail, and the precise values may change over time. + * The implementation may use either the maximized forms or the others ones, or both. + * The implementation may or may not rely on the forms to be consistent with each other. + * + *

Callers should construct and use a matcher rather than match pairs of locales directly. + * + * @param desired Desired locale. + * @param supported Supported locale. + * @param errorCode 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 value between 0 and 1, inclusive. + * @internal (has a known user) + */ + double internalMatch(const Locale &desired, const Locale &supported, UErrorCode &errorCode) const; +#endif // U_HIDE_INTERNAL_API + +private: + LocaleMatcher(const Builder &builder, UErrorCode &errorCode); + LocaleMatcher(const LocaleMatcher &other) = delete; + LocaleMatcher &operator=(const LocaleMatcher &other) = delete; + + int32_t getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, UErrorCode &errorCode) const; + + const XLikelySubtags &likelySubtags; + const LocaleDistance &localeDistance; + int32_t thresholdDistance; + int32_t demotionPerDesiredLocale; + ULocMatchFavorSubtag favorSubtag; + + // These are in input order. + const Locale ** supportedLocales; + LSR *lsrs; + int32_t supportedLocalesLength; + // These are in preference order: 1. Default locale 2. paradigm locales 3. others. + UHashtable *supportedLsrToIndex; // Map stores index+1 because 0 is "not found" + // Array versions of the supportedLsrToIndex keys and values. + // The distance lookup loops over the supportedLSRs and returns the index of the best match. + const LSR **supportedLSRs; + int32_t *supportedIndexes; + int32_t supportedLSRsLength; + Locale *ownedDefaultLocale; + const Locale *defaultLocale; + int32_t defaultLocaleIndex; +}; + +U_NAMESPACE_END + +#endif // U_HIDE_DRAFT_API +#endif // U_SHOW_CPLUSPLUS_API +#endif // __LOCALEMATCHER_H__ diff --git a/deps/icu-small/source/common/unicode/locdspnm.h b/deps/icu-small/source/common/unicode/locdspnm.h index f6e778356feced..4f06f857044c6e 100644 --- a/deps/icu-small/source/common/unicode/locdspnm.h +++ b/deps/icu-small/source/common/unicode/locdspnm.h @@ -12,6 +12,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Provides display names of Locale and its components. @@ -204,4 +206,6 @@ U_NAMESPACE_END #endif +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/locid.h b/deps/icu-small/source/common/unicode/locid.h index 7350e381ffa540..6fb0897fc05d95 100644 --- a/deps/icu-small/source/common/unicode/locid.h +++ b/deps/icu-small/source/common/unicode/locid.h @@ -31,11 +31,14 @@ #ifndef LOCID_H #define LOCID_H +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/bytestream.h" #include "unicode/localpointer.h" #include "unicode/strenum.h" #include "unicode/stringpiece.h" -#include "unicode/utypes.h" #include "unicode/uobject.h" #include "unicode/putil.h" #include "unicode/uloc.h" @@ -284,16 +287,14 @@ class U_COMMON_API Locale : public UObject { */ Locale(const Locale& other); -#ifndef U_HIDE_DRAFT_API /** * Move constructor; might leave source in bogus state. * This locale will have the same contents that the source locale had. * * @param other The Locale object being moved in. - * @draft ICU 63 + * @stable ICU 63 */ Locale(Locale&& other) U_NOEXCEPT; -#endif // U_HIDE_DRAFT_API /** * Destructor @@ -310,7 +311,6 @@ class U_COMMON_API Locale : public UObject { */ Locale& operator=(const Locale& other); -#ifndef U_HIDE_DRAFT_API /** * Move assignment operator; might leave source in bogus state. * This locale will have the same contents that the source locale had. @@ -318,10 +318,9 @@ class U_COMMON_API Locale : public UObject { * * @param other The Locale object being moved in. * @return *this - * @draft ICU 63 + * @stable ICU 63 */ Locale& operator=(Locale&& other) U_NOEXCEPT; -#endif // U_HIDE_DRAFT_API /** * Checks if two locale keys are the same. @@ -389,7 +388,6 @@ class U_COMMON_API Locale : public UObject { UErrorCode& success); #endif /* U_HIDE_SYSTEM_API */ -#ifndef U_HIDE_DRAFT_API /** * Returns a Locale for the specified BCP47 language tag string. * If the specified language tag contains any ill-formed subtags, @@ -405,7 +403,7 @@ class U_COMMON_API Locale : public UObject { * @param tag the input BCP47 language tag. * @param status error information if creating the Locale failed. * @return the Locale for the specified BCP47 language tag. - * @draft ICU 63 + * @stable ICU 63 */ static Locale U_EXPORT2 forLanguageTag(StringPiece tag, UErrorCode& status); @@ -420,7 +418,7 @@ class U_COMMON_API Locale : public UObject { * @param sink the output sink receiving the BCP47 language * tag for this Locale. * @param status error information if creating the language tag failed. - * @draft ICU 63 + * @stable ICU 63 */ void toLanguageTag(ByteSink& sink, UErrorCode& status) const; @@ -432,11 +430,10 @@ class U_COMMON_API Locale : public UObject { * * @param status error information if creating the language tag failed. * @return the BCP47 language tag for this Locale. - * @draft ICU 63 + * @stable ICU 63 */ template inline StringClass toLanguageTag(UErrorCode& status) const; -#endif // U_HIDE_DRAFT_API /** * Creates a locale which has had minimal canonicalization @@ -508,7 +505,6 @@ class U_COMMON_API Locale : public UObject { */ const char * getBaseName() const; -#ifndef U_HIDE_DRAFT_API /** * Add the likely subtags for this Locale, per the algorithm described * in the following CLDR technical report: @@ -536,7 +532,7 @@ class U_COMMON_API Locale : public UObject { * @param status error information if maximizing this Locale failed. * If this Locale is not well-formed, the error code is * U_ILLEGAL_ARGUMENT_ERROR. - * @draft ICU 63 + * @stable ICU 63 */ void addLikelySubtags(UErrorCode& status); @@ -567,10 +563,9 @@ class U_COMMON_API Locale : public UObject { * @param status error information if maximizing this Locale failed. * If this Locale is not well-formed, the error code is * U_ILLEGAL_ARGUMENT_ERROR. - * @draft ICU 63 + * @stable ICU 63 */ void minimizeSubtags(UErrorCode& status); -#endif // U_HIDE_DRAFT_API /** * Gets the list of keywords for the specified locale. @@ -583,8 +578,6 @@ class U_COMMON_API Locale : public UObject { */ StringEnumeration * createKeywords(UErrorCode &status) const; -#ifndef U_HIDE_DRAFT_API - /** * Gets the list of Unicode keywords for the specified locale. * @@ -592,7 +585,7 @@ class U_COMMON_API Locale : public UObject { * @return pointer to StringEnumeration class, or NULL if there are no keywords. * Client must dispose of it by calling delete. * @see getUnicodeKeywords - * @draft ICU 63 + * @stable ICU 63 */ StringEnumeration * createUnicodeKeywords(UErrorCode &status) const; @@ -605,7 +598,7 @@ class U_COMMON_API Locale : public UObject { * * @param iterator an STL style output iterator to write the keywords to. * @param status error information if creating set of keywords failed. - * @draft ICU 63 + * @stable ICU 63 */ template inline void getKeywords(OutputIterator iterator, UErrorCode& status) const; @@ -619,13 +612,11 @@ class U_COMMON_API Locale : public UObject { * * @param iterator an STL style output iterator to write the keywords to. * @param status error information if creating set of keywords failed. - * @draft ICU 63 + * @stable ICU 63 */ template inline void getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const; -#endif // U_HIDE_DRAFT_API - /** * Gets the value for a keyword. * @@ -644,7 +635,6 @@ class U_COMMON_API Locale : public UObject { */ int32_t getKeywordValue(const char* keywordName, char *buffer, int32_t bufferCapacity, UErrorCode &status) const; -#ifndef U_HIDE_DRAFT_API /** * Gets the value for a keyword. * @@ -656,7 +646,7 @@ class U_COMMON_API Locale : public UObject { * @param keywordName name of the keyword for which we want the value. * @param sink the sink to receive the keyword value. * @param status error information if getting the value failed. - * @draft ICU 63 + * @stable ICU 63 */ void getKeywordValue(StringPiece keywordName, ByteSink& sink, UErrorCode& status) const; @@ -671,7 +661,7 @@ class U_COMMON_API Locale : public UObject { * @param keywordName name of the keyword for which we want the value. * @param status error information if getting the value failed. * @return the keyword value. - * @draft ICU 63 + * @stable ICU 63 */ template inline StringClass getKeywordValue(StringPiece keywordName, UErrorCode& status) const; @@ -687,7 +677,7 @@ class U_COMMON_API Locale : public UObject { * @param keywordName name of the keyword for which we want the value. * @param sink the sink to receive the keyword value. * @param status error information if getting the value failed. - * @draft ICU 63 + * @stable ICU 63 */ void getUnicodeKeywordValue(StringPiece keywordName, ByteSink& sink, UErrorCode& status) const; @@ -702,11 +692,10 @@ class U_COMMON_API Locale : public UObject { * @param keywordName name of the keyword for which we want the value. * @param status error information if getting the value failed. * @return the keyword value. - * @draft ICU 63 + * @stable ICU 63 */ template inline StringClass getUnicodeKeywordValue(StringPiece keywordName, UErrorCode& status) const; -#endif // U_HIDE_DRAFT_API /** * Sets or removes the value for a keyword. @@ -729,7 +718,6 @@ class U_COMMON_API Locale : public UObject { */ void setKeywordValue(const char* keywordName, const char* keywordValue, UErrorCode &status); -#ifndef U_HIDE_DRAFT_API /** * Sets or removes the value for a keyword. * @@ -746,7 +734,7 @@ class U_COMMON_API Locale : public UObject { * NULL, will result in the keyword being removed. No error is given if * that keyword does not exist. * @param status Returns any error information while performing this operation. - * @draft ICU 63 + * @stable ICU 63 */ void setKeywordValue(StringPiece keywordName, StringPiece keywordValue, UErrorCode& status); @@ -766,10 +754,9 @@ class U_COMMON_API Locale : public UObject { * NULL, will result in the keyword being removed. No error is given if * that keyword does not exist. * @param status Returns any error information while performing this operation. - * @draft ICU 63 + * @stable ICU 63 */ void setUnicodeKeywordValue(StringPiece keywordName, StringPiece keywordValue, UErrorCode& status); -#endif // U_HIDE_DRAFT_API /** * returns the locale's three-letter language code, as specified @@ -1008,6 +995,104 @@ class U_COMMON_API Locale : public UObject { */ virtual UClassID getDynamicClassID() const; +#ifndef U_HIDE_DRAFT_API + /** + * A Locale iterator interface similar to a Java Iterator. + * @draft ICU 65 + */ + class U_COMMON_API Iterator /* not : public UObject because this is an interface/mixin class */ { + public: + /** @draft ICU 65 */ + virtual ~Iterator(); + + /** + * @return TRUE if next() can be called again. + * @draft ICU 65 + */ + virtual UBool hasNext() const = 0; + + /** + * @return the next locale. + * @draft ICU 65 + */ + virtual const Locale &next() = 0; + }; + + /** + * A generic Locale iterator implementation over Locale input iterators. + * @draft ICU 65 + */ + template + class RangeIterator : public Iterator, public UMemory { + public: + /** + * Constructs an iterator from a begin/end range. + * Each of the iterator parameter values must be an + * input iterator whose value is convertible to const Locale &. + * + * @param begin Start of range. + * @param end Exclusive end of range. + * @draft ICU 65 + */ + RangeIterator(Iter begin, Iter end) : it_(begin), end_(end) {} + + /** + * @return TRUE if next() can be called again. + * @draft ICU 65 + */ + UBool hasNext() const override { return it_ != end_; } + + /** + * @return the next locale. + * @draft ICU 65 + */ + const Locale &next() override { return *it_++; } + + private: + Iter it_; + const Iter end_; + }; + + /** + * A generic Locale iterator implementation over Locale input iterators. + * Calls the converter to convert each *begin to a const Locale &. + * @draft ICU 65 + */ + template + class ConvertingIterator : public Iterator, public UMemory { + public: + /** + * Constructs an iterator from a begin/end range. + * Each of the iterator parameter values must be an + * input iterator whose value the converter converts to const Locale &. + * + * @param begin Start of range. + * @param end Exclusive end of range. + * @param converter Converter from *begin to const Locale & or compatible. + * @draft ICU 65 + */ + ConvertingIterator(Iter begin, Iter end, Conv converter) : + it_(begin), end_(end), converter_(converter) {} + + /** + * @return TRUE if next() can be called again. + * @draft ICU 65 + */ + UBool hasNext() const override { return it_ != end_; } + + /** + * @return the next locale. + * @draft ICU 65 + */ + const Locale &next() override { return converter_(*it_++); } + + private: + Iter it_; + const Iter end_; + Conv converter_; + }; +#endif // U_HIDE_DRAFT_API + protected: /* only protected for testing purposes. DO NOT USE. */ #ifndef U_HIDE_INTERNAL_API /** @@ -1074,7 +1159,6 @@ Locale::operator!=(const Locale& other) const return !operator==(other); } -#ifndef U_HIDE_DRAFT_API template inline StringClass Locale::toLanguageTag(UErrorCode& status) const { @@ -1083,7 +1167,6 @@ Locale::toLanguageTag(UErrorCode& status) const toLanguageTag(sink, status); return result; } -#endif // U_HIDE_DRAFT_API inline const char * Locale::getCountry() const @@ -1115,13 +1198,11 @@ Locale::getName() const return fullName; } -#ifndef U_HIDE_DRAFT_API - template inline void Locale::getKeywords(OutputIterator iterator, UErrorCode& status) const { LocalPointer keys(createKeywords(status)); - if (U_FAILURE(status)) { + if (U_FAILURE(status) || keys.isNull()) { return; } for (;;) { @@ -1138,7 +1219,7 @@ template inline void Locale::getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const { LocalPointer keys(createUnicodeKeywords(status)); - if (U_FAILURE(status)) { + if (U_FAILURE(status) || keys.isNull()) { return; } for (;;) { @@ -1169,8 +1250,6 @@ Locale::getUnicodeKeywordValue(StringPiece keywordName, UErrorCode& status) cons return result; } -#endif // U_HIDE_DRAFT_API - inline UBool Locale::isBogus(void) const { return fIsBogus; @@ -1178,4 +1257,6 @@ Locale::isBogus(void) const { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/messagepattern.h b/deps/icu-small/source/common/unicode/messagepattern.h index 9f2a86551ca417..04f00a8757d783 100644 --- a/deps/icu-small/source/common/unicode/messagepattern.h +++ b/deps/icu-small/source/common/unicode/messagepattern.h @@ -24,6 +24,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_FORMATTING #include "unicode/parseerr.h" @@ -942,4 +944,6 @@ U_NAMESPACE_END #endif // !UCONFIG_NO_FORMATTING +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __MESSAGEPATTERN_H__ diff --git a/deps/icu-small/source/common/unicode/normalizer2.h b/deps/icu-small/source/common/unicode/normalizer2.h index 4caa0e31034b2d..4aeb3bb3d82921 100644 --- a/deps/icu-small/source/common/unicode/normalizer2.h +++ b/deps/icu-small/source/common/unicode/normalizer2.h @@ -26,6 +26,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + #if !UCONFIG_NO_NORMALIZATION #include "unicode/stringpiece.h" @@ -771,4 +773,7 @@ class U_COMMON_API FilteredNormalizer2 : public Normalizer2 { U_NAMESPACE_END #endif // !UCONFIG_NO_NORMALIZATION + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __NORMALIZER2_H__ diff --git a/deps/icu-small/source/common/unicode/normlzr.h b/deps/icu-small/source/common/unicode/normlzr.h index 82335ae6d7d19b..00dd820474f734 100644 --- a/deps/icu-small/source/common/unicode/normlzr.h +++ b/deps/icu-small/source/common/unicode/normlzr.h @@ -13,6 +13,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Unicode Normalization @@ -183,6 +185,7 @@ class U_COMMON_API Normalizer : public UObject { Normalizer(const CharacterIterator& iter, UNormalizationMode mode); #endif /* U_HIDE_DEPRECATED_API */ +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Copy constructor. * @param copy The object to be copied. @@ -195,7 +198,7 @@ class U_COMMON_API Normalizer : public UObject { * @deprecated ICU 56 Use Normalizer2 instead. */ virtual ~Normalizer(); - +#endif // U_FORCE_HIDE_DEPRECATED_API //------------------------------------------------------------------------- // Static utility methods @@ -599,7 +602,7 @@ class U_COMMON_API Normalizer : public UObject { * @return a pointer to a new Normalizer * @deprecated ICU 56 Use Normalizer2 instead. */ - Normalizer* clone(void) const; + Normalizer* clone() const; /** * Generates a hash code for this iterator. @@ -723,12 +726,14 @@ class U_COMMON_API Normalizer : public UObject { static UClassID U_EXPORT2 getStaticClassID(); #endif /* U_HIDE_DEPRECATED_API */ +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * ICU "poor man's RTTI", returns a UClassID for the actual class. * @return a UClassID for the actual class. * @deprecated ICU 56 Use Normalizer2 instead. */ virtual UClassID getDynamicClassID() const; +#endif // U_FORCE_HIDE_DEPRECATED_API private: //------------------------------------------------------------------------- @@ -807,3 +812,5 @@ U_NAMESPACE_END #endif /* #if !UCONFIG_NO_NORMALIZATION */ #endif // NORMLZR_H + +#endif /* U_SHOW_CPLUSPLUS_API */ diff --git a/deps/icu-small/source/common/unicode/parsepos.h b/deps/icu-small/source/common/unicode/parsepos.h index c02c8169565738..ae5754b8d75132 100644 --- a/deps/icu-small/source/common/unicode/parsepos.h +++ b/deps/icu-small/source/common/unicode/parsepos.h @@ -19,6 +19,9 @@ #define PARSEPOS_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" @@ -229,4 +232,6 @@ ParsePosition::setErrorIndex(int32_t ei) } U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/platform.h b/deps/icu-small/source/common/unicode/platform.h index ee0d8b7a000303..74689d790cf79a 100644 --- a/deps/icu-small/source/common/unicode/platform.h +++ b/deps/icu-small/source/common/unicode/platform.h @@ -135,6 +135,14 @@ /** Fuchsia is a POSIX-ish platform. @internal */ #define U_PF_FUCHSIA 4100 /* Maximum value for Linux-based platform is 4499 */ +/** + * Emscripten is a C++ transpiler for the Web that can target asm.js or + * WebAssembly. It provides some POSIX-compatible wrappers and stubs and + * some Linux-like functionality, but is not fully compatible with + * either. + * @internal + */ +#define U_PF_EMSCRIPTEN 5010 /** z/OS is the successor to OS/390 which was the successor to MVS. @internal */ #define U_PF_OS390 9000 /** "IBM i" is the current name of what used to be i5/OS and earlier OS/400. @internal */ @@ -192,6 +200,8 @@ # define U_PLATFORM U_PF_OS390 #elif defined(__OS400__) || defined(__TOS_OS400__) # define U_PLATFORM U_PF_OS400 +#elif defined(__EMSCRIPTEN__) +# define U_PLATFORM U_PF_EMSCRIPTEN #else # define U_PLATFORM U_PF_UNKNOWN #endif @@ -414,26 +424,40 @@ #endif /* Compatibility with compilers other than clang: http://clang.llvm.org/docs/LanguageExtensions.html */ -#ifndef __has_attribute -# define __has_attribute(x) 0 +#ifdef __has_attribute +# define UPRV_HAS_ATTRIBUTE(x) __has_attribute(x) +#else +# define UPRV_HAS_ATTRIBUTE(x) 0 #endif -#ifndef __has_cpp_attribute -# define __has_cpp_attribute(x) 0 +#ifdef __has_cpp_attribute +# define UPRV_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +# define UPRV_HAS_CPP_ATTRIBUTE(x) 0 #endif -#ifndef __has_declspec_attribute -# define __has_declspec_attribute(x) 0 +#ifdef __has_declspec_attribute +# define UPRV_HAS_DECLSPEC_ATTRIBUTE(x) __has_declspec_attribute(x) +#else +# define UPRV_HAS_DECLSPEC_ATTRIBUTE(x) 0 #endif -#ifndef __has_builtin -# define __has_builtin(x) 0 +#ifdef __has_builtin +# define UPRV_HAS_BUILTIN(x) __has_builtin(x) +#else +# define UPRV_HAS_BUILTIN(x) 0 #endif -#ifndef __has_feature -# define __has_feature(x) 0 +#ifdef __has_feature +# define UPRV_HAS_FEATURE(x) __has_feature(x) +#else +# define UPRV_HAS_FEATURE(x) 0 #endif -#ifndef __has_extension -# define __has_extension(x) 0 +#ifdef __has_extension +# define UPRV_HAS_EXTENSION(x) __has_extension(x) +#else +# define UPRV_HAS_EXTENSION(x) 0 #endif -#ifndef __has_warning -# define __has_warning(x) 0 +#ifdef __has_warning +# define UPRV_HAS_WARNING(x) __has_warning(x) +#else +# define UPRV_HAS_WARNING(x) 0 #endif /** @@ -452,7 +476,9 @@ * Attribute to specify the size of the allocated buffer for malloc-like functions * @internal */ -#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || __has_attribute(alloc_size) +#if (defined(__GNUC__) && \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || \ + UPRV_HAS_ATTRIBUTE(alloc_size) # define U_ALLOC_SIZE_ATTR(X) __attribute__ ((alloc_size(X))) # define U_ALLOC_SIZE_ATTR2(X,Y) __attribute__ ((alloc_size(X,Y))) #else @@ -516,8 +542,9 @@ namespace std { #elif defined(__clang__) // Test for compiler vs. feature separately. // Other compilers might choke on the feature test. -# if __has_cpp_attribute(clang::fallthrough) || \ - (__has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")) +# if UPRV_HAS_CPP_ATTRIBUTE(clang::fallthrough) || \ + (UPRV_HAS_FEATURE(cxx_attributes) && \ + UPRV_HAS_WARNING("-Wimplicit-fallthrough")) # define U_FALLTHROUGH [[clang::fallthrough]] # endif #elif defined(__GNUC__) && (__GNUC__ >= 7) @@ -620,7 +647,8 @@ namespace std { */ #ifdef U_CHARSET_IS_UTF8 /* Use the predefined value. */ -#elif U_PLATFORM_IS_LINUX_BASED || U_PLATFORM_IS_DARWIN_BASED +#elif U_PLATFORM_IS_LINUX_BASED || U_PLATFORM_IS_DARWIN_BASED || \ + U_PLATFORM == U_PF_EMSCRIPTEN # define U_CHARSET_IS_UTF8 1 #else # define U_CHARSET_IS_UTF8 0 @@ -707,7 +735,7 @@ namespace std { * narrow-character strings are in EBCDIC. */ # define U_SIZEOF_WCHAR_T 2 -#else +# else /* * LOCALETYPE(*CLD) or LOCALETYPE(*LOCALE) is specified. * Wide-character strings are in 16-bit EBCDIC, @@ -786,7 +814,8 @@ namespace std { /* Use the predefined value. */ #elif defined(U_STATIC_IMPLEMENTATION) # define U_EXPORT -#elif defined(_MSC_VER) || (__has_declspec_attribute(dllexport) && __has_declspec_attribute(dllimport)) +#elif defined(_MSC_VER) || (UPRV_HAS_DECLSPEC_ATTRIBUTE(dllexport) && \ + UPRV_HAS_DECLSPEC_ATTRIBUTE(dllimport)) # define U_EXPORT __declspec(dllexport) #elif defined(__GNUC__) # define U_EXPORT __attribute__((visibility("default"))) @@ -810,7 +839,8 @@ namespace std { #ifdef U_IMPORT /* Use the predefined value. */ -#elif defined(_MSC_VER) || (__has_declspec_attribute(dllexport) && __has_declspec_attribute(dllimport)) +#elif defined(_MSC_VER) || (UPRV_HAS_DECLSPEC_ATTRIBUTE(dllexport) && \ + UPRV_HAS_DECLSPEC_ATTRIBUTE(dllimport)) /* Windows needs to export/import data. */ # define U_IMPORT __declspec(dllimport) #else @@ -852,4 +882,4 @@ namespace std { #endif /* @} */ -#endif +#endif // _PLATFORM_H diff --git a/deps/icu-small/source/common/unicode/rbbi.h b/deps/icu-small/source/common/unicode/rbbi.h index 365ae2d3d2ac75..7825f603a51c1b 100644 --- a/deps/icu-small/source/common/unicode/rbbi.h +++ b/deps/icu-small/source/common/unicode/rbbi.h @@ -18,6 +18,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + /** * \file * \brief C++ API: Rule Based Break Iterator @@ -272,7 +274,7 @@ class U_COMMON_API RuleBasedBreakIterator /*U_FINAL*/ : public BreakIterator { * @return a newly-constructed RuleBasedBreakIterator * @stable ICU 2.0 */ - virtual BreakIterator* clone() const; + virtual RuleBasedBreakIterator* clone() const; /** * Compute a hash code for this BreakIterator @@ -536,6 +538,7 @@ class U_COMMON_API RuleBasedBreakIterator /*U_FINAL*/ : public BreakIterator { */ static UClassID U_EXPORT2 getStaticClassID(void); +#ifndef U_FORCE_HIDE_DEPRECATED_API /** * Deprecated functionality. Use clone() instead. * @@ -562,10 +565,10 @@ class U_COMMON_API RuleBasedBreakIterator /*U_FINAL*/ : public BreakIterator { * or if the stackBuffer was too small to hold the clone. * @deprecated ICU 52. Use clone() instead. */ - virtual BreakIterator * createBufferClone(void *stackBuffer, - int32_t &BufferSize, - UErrorCode &status); - + virtual RuleBasedBreakIterator *createBufferClone(void *stackBuffer, + int32_t &BufferSize, + UErrorCode &status); +#endif // U_FORCE_HIDE_DEPRECATED_API /** * Return the binary form of compiled break rules, @@ -696,4 +699,6 @@ U_NAMESPACE_END #endif /* #if !UCONFIG_NO_BREAK_ITERATION */ +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/rep.h b/deps/icu-small/source/common/unicode/rep.h index b1023a37a2daf1..f66c2ac060e4a8 100644 --- a/deps/icu-small/source/common/unicode/rep.h +++ b/deps/icu-small/source/common/unicode/rep.h @@ -16,6 +16,10 @@ #ifndef REP_H #define REP_H +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" /** @@ -189,9 +193,6 @@ class U_COMMON_API Replaceable : public UObject { * Clones can be used concurrently in multiple threads. * If a subclass does not implement clone(), or if an error occurs, * then NULL is returned. - * The clone functions in all subclasses return a pointer to a Replaceable - * because some compilers do not support covariant (same-as-this) - * return types; cast to the appropriate subclass if necessary. * The caller must delete the clone. * * @return a clone of this object @@ -260,4 +261,6 @@ Replaceable::char32At(int32_t offset) const { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/resbund.h b/deps/icu-small/source/common/unicode/resbund.h index ab0b60bbb28fcc..708a3423d2ae2b 100644 --- a/deps/icu-small/source/common/unicode/resbund.h +++ b/deps/icu-small/source/common/unicode/resbund.h @@ -49,6 +49,9 @@ #define RESBUND_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" #include "unicode/ures.h" #include "unicode/unistr.h" @@ -489,4 +492,7 @@ class U_COMMON_API ResourceBundle : public UObject { }; U_NAMESPACE_END + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/schriter.h b/deps/icu-small/source/common/unicode/schriter.h index 1a12769e8df106..4925ecfe444280 100644 --- a/deps/icu-small/source/common/unicode/schriter.h +++ b/deps/icu-small/source/common/unicode/schriter.h @@ -21,6 +21,9 @@ #define SCHRITER_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/chariter.h" #include "unicode/uchriter.h" @@ -130,7 +133,7 @@ class U_COMMON_API StringCharacterIterator : public UCharCharacterIterator { * @return the newly cloned object. * @stable ICU 2.0 */ - virtual CharacterIterator* clone(void) const; + virtual StringCharacterIterator* clone() const; /** * Sets the iterator to iterate over the provided string. @@ -186,4 +189,7 @@ class U_COMMON_API StringCharacterIterator : public UCharCharacterIterator { }; U_NAMESPACE_END + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/simpleformatter.h b/deps/icu-small/source/common/unicode/simpleformatter.h index 3f7d93dc094a18..9414bca3085ad4 100644 --- a/deps/icu-small/source/common/unicode/simpleformatter.h +++ b/deps/icu-small/source/common/unicode/simpleformatter.h @@ -17,6 +17,9 @@ */ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/unistr.h" U_NAMESPACE_BEGIN @@ -333,4 +336,6 @@ class U_COMMON_API SimpleFormatter U_FINAL : public UMemory { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __SIMPLEFORMATTER_H__ diff --git a/deps/icu-small/source/common/unicode/std_string.h b/deps/icu-small/source/common/unicode/std_string.h index 729c56399506eb..bf87230167ecf2 100644 --- a/deps/icu-small/source/common/unicode/std_string.h +++ b/deps/icu-small/source/common/unicode/std_string.h @@ -27,6 +27,8 @@ #include "unicode/utypes.h" +#if U_SHOW_CPLUSPLUS_API + // Workaround for a libstdc++ bug before libstdc++4.6 (2011). // https://bugs.llvm.org/show_bug.cgi?id=13364 #if defined(__GLIBCXX__) @@ -34,4 +36,6 @@ namespace std { class type_info; } #endif #include +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __STD_STRING_H__ diff --git a/deps/icu-small/source/common/unicode/strenum.h b/deps/icu-small/source/common/unicode/strenum.h index fa525d4f5227da..e813cd84b3413a 100644 --- a/deps/icu-small/source/common/unicode/strenum.h +++ b/deps/icu-small/source/common/unicode/strenum.h @@ -12,6 +12,10 @@ #ifndef STRENUM_H #define STRENUM_H +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" #include "unicode/unistr.h" @@ -67,9 +71,6 @@ class U_COMMON_API StringEnumeration : public UObject { * Clones can be used concurrently in multiple threads. * If a subclass does not implement clone(), or if an error occurs, * then NULL is returned. - * The clone functions in all subclasses return a base class pointer - * because some compilers do not support covariant (same-as-this) - * return types; cast to the appropriate subclass if necessary. * The caller must delete the clone. * * @return a clone of this object @@ -274,5 +275,7 @@ class U_COMMON_API StringEnumeration : public UObject { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + /* STRENUM_H */ #endif diff --git a/deps/icu-small/source/common/unicode/stringpiece.h b/deps/icu-small/source/common/unicode/stringpiece.h index 640fbac5a827d0..15cebb0f202fe7 100644 --- a/deps/icu-small/source/common/unicode/stringpiece.h +++ b/deps/icu-small/source/common/unicode/stringpiece.h @@ -28,6 +28,12 @@ */ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + +#include +#include + #include "unicode/uobject.h" #include "unicode/std_string.h" @@ -74,6 +80,33 @@ class U_COMMON_API StringPiece : public UMemory { */ StringPiece(const std::string& str) : ptr_(str.data()), length_(static_cast(str.size())) { } +#ifndef U_HIDE_DRAFT_API + /** + * Constructs from some other implementation of a string piece class, from any + * C++ record type that has these two methods: + * + * \code{.cpp} + * + * struct OtherStringPieceClass { + * const char* data(); + * size_t size(); + * }; + * + * \endcode + * + * The other string piece class will typically be std::string_view from C++17 + * or absl::string_view from Abseil. + * + * @param str the other string piece + * @draft ICU 65 + */ + template ::value && + std::is_same::value>::type> + StringPiece(T str) + : ptr_(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) @@ -221,4 +254,6 @@ inline UBool operator!=(const StringPiece& x, const StringPiece& y) { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __STRINGPIECE_H__ diff --git a/deps/icu-small/source/common/unicode/stringtriebuilder.h b/deps/icu-small/source/common/unicode/stringtriebuilder.h index c27fbd67960d70..2860cbf5513b8e 100644 --- a/deps/icu-small/source/common/unicode/stringtriebuilder.h +++ b/deps/icu-small/source/common/unicode/stringtriebuilder.h @@ -18,6 +18,9 @@ #define __STRINGTRIEBUILDER_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" /** @@ -418,4 +421,6 @@ class U_COMMON_API StringTrieBuilder : public UObject { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __STRINGTRIEBUILDER_H__ diff --git a/deps/icu-small/source/common/unicode/symtable.h b/deps/icu-small/source/common/unicode/symtable.h index c2dc95a61bc020..f5a77b01eced80 100644 --- a/deps/icu-small/source/common/unicode/symtable.h +++ b/deps/icu-small/source/common/unicode/symtable.h @@ -13,6 +13,9 @@ #define SYMTABLE_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" /** @@ -111,4 +114,6 @@ class U_COMMON_API SymbolTable /* not : public UObject because this is an interf }; U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/uchar.h b/deps/icu-small/source/common/unicode/uchar.h index d70c964e38e5b8..1b7ee099be7ca2 100644 --- a/deps/icu-small/source/common/unicode/uchar.h +++ b/deps/icu-small/source/common/unicode/uchar.h @@ -2578,8 +2578,6 @@ typedef enum UVerticalOrientation { U_STABLE UBool U_EXPORT2 u_hasBinaryProperty(UChar32 c, UProperty which); -#ifndef U_HIDE_DRAFT_API - /** * Returns a frozen USet for a binary property. * The library retains ownership over the returned object. @@ -2593,13 +2591,11 @@ u_hasBinaryProperty(UChar32 c, UProperty which); * @see UProperty * @see u_hasBinaryProperty * @see Unicode::fromUSet - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI const USet * U_EXPORT2 u_getBinaryPropertySet(UProperty property, UErrorCode *pErrorCode); -#endif // U_HIDE_DRAFT_API - /** * Check if a code point has the Alphabetic Unicode property. * Same as u_hasBinaryProperty(c, UCHAR_ALPHABETIC). @@ -2757,8 +2753,6 @@ u_getIntPropertyMinValue(UProperty which); U_STABLE int32_t U_EXPORT2 u_getIntPropertyMaxValue(UProperty which); -#ifndef U_HIDE_DRAFT_API - /** * Returns an immutable UCPMap for an enumerated/catalog/int-valued property. * The library retains ownership over the returned object. @@ -2772,13 +2766,11 @@ u_getIntPropertyMaxValue(UProperty which); * @return the property as a map * @see UProperty * @see u_getIntPropertyValue - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI const UCPMap * U_EXPORT2 u_getIntPropertyMap(UProperty property, UErrorCode *pErrorCode); -#endif // U_HIDE_DRAFT_API - /** * Get the numeric value for a Unicode code point as defined in the * Unicode Character Database. @@ -3197,15 +3189,14 @@ U_STABLE UBool U_EXPORT2 u_isprint(UChar32 c); /** - * Determines whether the specified code point is a base character. + * Non-standard: Determines whether the specified code point is a base character. * True for general categories "L" (letters), "N" (numbers), * "Mc" (spacing combining marks), and "Me" (enclosing marks). * - * Note that this is different from the Unicode definition in - * chapter 3.5, conformance clause D13, - * which defines base characters to be all characters (not Cn) - * that do not graphically combine with preceding characters (M) - * and that are neither control (Cc) or format (Cf) characters. + * Note that this is different from the Unicode Standard definition in + * chapter 3.6, conformance clause D51 “Base character”, + * which defines base characters as the code points with general categories + * Letter (L), Number (N), Punctuation (P), Symbol (S), or Space Separator (Zs). * * @param c the code point to be tested * @return TRUE if the code point is a base character according to this function diff --git a/deps/icu-small/source/common/unicode/ucharstrie.h b/deps/icu-small/source/common/unicode/ucharstrie.h index dfc93f6d0bae8a..d5729d944ee3a2 100644 --- a/deps/icu-small/source/common/unicode/ucharstrie.h +++ b/deps/icu-small/source/common/unicode/ucharstrie.h @@ -24,6 +24,9 @@ */ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/unistr.h" #include "unicode/uobject.h" #include "unicode/ustringtrie.h" @@ -94,6 +97,41 @@ class U_COMMON_API UCharsTrie : public UMemory { return *this; } +#ifndef U_HIDE_DRAFT_API + /** + * Returns the state of this trie as a 64-bit integer. + * The state value is never 0. + * + * @return opaque state value + * @see resetToState64 + * @draft ICU 65 + */ + uint64_t getState64() const { + return (static_cast(remainingMatchLength_ + 2) << kState64RemainingShift) | + (uint64_t)(pos_ - uchars_); + } + + /** + * Resets this trie to the saved state. + * Unlike resetToState(State), the 64-bit state value + * must be from getState64() from the same trie object or + * from one initialized the exact same way. + * Because of no validation, this method is faster. + * + * @param state The opaque trie state value from getState64(). + * @return *this + * @see getState64 + * @see resetToState + * @see reset + * @draft ICU 65 + */ + UCharsTrie &resetToState64(uint64_t state) { + remainingMatchLength_ = static_cast(state >> kState64RemainingShift) - 2; + pos_ = uchars_ + (state & kState64PosMask); + return *this; + } +#endif /* U_HIDE_DRAFT_API */ + /** * UCharsTrie state object, for saving a trie's current state * and resetting the trie back to this state later. @@ -560,6 +598,13 @@ class U_COMMON_API UCharsTrie : public UMemory { static const int32_t kMaxTwoUnitDelta=((kThreeUnitDeltaLead-kMinTwoUnitDeltaLead)<<16)-1; // 0x03feffff + // For getState64(): + // The remainingMatchLength_ is -1..14=(kMaxLinearMatchLength=0x10)-2 + // so we need at least 5 bits for that. + // We add 2 to store it as a positive value 1..16=kMaxLinearMatchLength. + static constexpr int32_t kState64RemainingShift = 59; + static constexpr uint64_t kState64PosMask = (UINT64_C(1) << kState64RemainingShift) - 1; + char16_t *ownedArray_; // Fixed value referencing the UCharsTrie words. @@ -575,4 +620,6 @@ class U_COMMON_API UCharsTrie : public UMemory { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __UCHARSTRIE_H__ diff --git a/deps/icu-small/source/common/unicode/ucharstriebuilder.h b/deps/icu-small/source/common/unicode/ucharstriebuilder.h index 2aa4757e52cb07..540dcc047fd563 100644 --- a/deps/icu-small/source/common/unicode/ucharstriebuilder.h +++ b/deps/icu-small/source/common/unicode/ucharstriebuilder.h @@ -18,6 +18,9 @@ #define __UCHARSTRIEBUILDER_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/stringtriebuilder.h" #include "unicode/ucharstrie.h" #include "unicode/unistr.h" @@ -184,4 +187,6 @@ class U_COMMON_API UCharsTrieBuilder : public StringTrieBuilder { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif // __UCHARSTRIEBUILDER_H__ diff --git a/deps/icu-small/source/common/unicode/uchriter.h b/deps/icu-small/source/common/unicode/uchriter.h index 38f67c5b454cba..bee842cc259f07 100644 --- a/deps/icu-small/source/common/unicode/uchriter.h +++ b/deps/icu-small/source/common/unicode/uchriter.h @@ -11,6 +11,9 @@ #define UCHRITER_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/chariter.h" /** @@ -132,7 +135,7 @@ class U_COMMON_API UCharCharacterIterator : public CharacterIterator { * @return the CharacterIterator newly created * @stable ICU 2.0 */ - virtual CharacterIterator* clone(void) const; + virtual UCharCharacterIterator* clone() const; /** * Sets the iterator to refer to the first code unit in its @@ -384,4 +387,7 @@ class U_COMMON_API UCharCharacterIterator : public CharacterIterator { }; U_NAMESPACE_END + +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/uconfig.h b/deps/icu-small/source/common/unicode/uconfig.h index 9c82d828125603..c0157efe6d4ede 100644 --- a/deps/icu-small/source/common/unicode/uconfig.h +++ b/deps/icu-small/source/common/unicode/uconfig.h @@ -453,4 +453,4 @@ # define UCONFIG_NO_FILTERED_BREAK_ITERATION 0 #endif -#endif +#endif // __UCONFIG_H__ diff --git a/deps/icu-small/source/common/unicode/ucpmap.h b/deps/icu-small/source/common/unicode/ucpmap.h index f2c42b6b7f4bee..31e1365cac850a 100644 --- a/deps/icu-small/source/common/unicode/ucpmap.h +++ b/deps/icu-small/source/common/unicode/ucpmap.h @@ -9,8 +9,6 @@ #include "unicode/utypes.h" -#ifndef U_HIDE_DRAFT_API - U_CDECL_BEGIN /** @@ -28,7 +26,7 @@ U_CDECL_BEGIN * * @see UCPTrie * @see UMutableCPTrie - * @draft ICU 63 + * @stable ICU 63 */ typedef struct UCPMap UCPMap; @@ -39,13 +37,13 @@ typedef struct UCPMap UCPMap; * @see ucpmap_getRange * @see ucptrie_getRange * @see umutablecptrie_getRange - * @draft ICU 63 + * @stable ICU 63 */ enum UCPMapRangeOption { /** * ucpmap_getRange() enumerates all same-value ranges as stored in the map. * Most users should use this option. - * @draft ICU 63 + * @stable ICU 63 */ UCPMAP_RANGE_NORMAL, /** @@ -61,7 +59,7 @@ enum UCPMapRangeOption { * special values optimized for UTF-16 string processing * or for special error behavior for unpaired surrogates, * but those values are not to be associated with the lead surrogate code *points*. - * @draft ICU 63 + * @stable ICU 63 */ UCPMAP_RANGE_FIXED_LEAD_SURROGATES, /** @@ -77,7 +75,7 @@ enum UCPMapRangeOption { * special values optimized for UTF-16 string processing * or for special error behavior for unpaired surrogates, * but those values are not to be associated with the lead surrogate code *points*. - * @draft ICU 63 + * @stable ICU 63 */ UCPMAP_RANGE_FIXED_ALL_SURROGATES }; @@ -93,7 +91,7 @@ typedef enum UCPMapRangeOption UCPMapRangeOption; * @param c the code point * @return the map value, * or an implementation-defined error value if the code point is not in the range 0..U+10FFFF - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI uint32_t U_EXPORT2 ucpmap_get(const UCPMap *map, UChar32 c); @@ -110,7 +108,7 @@ ucpmap_get(const UCPMap *map, UChar32 c); * @param context an opaque pointer, as passed into the getRange function * @param value a value from the map * @return the modified value - * @draft ICU 63 + * @stable ICU 63 */ typedef uint32_t U_CALLCONV UCPMapValueFilter(const void *context, uint32_t value); @@ -149,7 +147,7 @@ UCPMapValueFilter(const void *context, uint32_t value); * may have been modified by filter(context, map value) * if that function pointer is not NULL * @return the range end code point, or -1 if start is not a valid code point - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UChar32 U_EXPORT2 ucpmap_getRange(const UCPMap *map, UChar32 start, @@ -158,5 +156,4 @@ ucpmap_getRange(const UCPMap *map, UChar32 start, U_CDECL_END -#endif // U_HIDE_DRAFT_API #endif diff --git a/deps/icu-small/source/common/unicode/ucptrie.h b/deps/icu-small/source/common/unicode/ucptrie.h index 2718c984e43197..be06a227928286 100644 --- a/deps/icu-small/source/common/unicode/ucptrie.h +++ b/deps/icu-small/source/common/unicode/ucptrie.h @@ -9,8 +9,6 @@ #include "unicode/utypes.h" -#ifndef U_HIDE_DRAFT_API - #include "unicode/localpointer.h" #include "unicode/ucpmap.h" #include "unicode/utf8.h" @@ -55,7 +53,7 @@ typedef union UCPTrieData { * The macros will return bogus values, or may crash, if used on the wrong type or value width. * * @see UMutableCPTrie - * @draft ICU 63 + * @stable ICU 63 */ struct UCPTrie { #ifndef U_IN_DOXYGEN @@ -115,23 +113,23 @@ typedef struct UCPTrie UCPTrie; * @see umutablecptrie_buildImmutable * @see ucptrie_openFromBinary * @see ucptrie_getType - * @draft ICU 63 + * @stable ICU 63 */ enum UCPTrieType { /** * For ucptrie_openFromBinary() to accept any type. * ucptrie_getType() will return the actual type. - * @draft ICU 63 + * @stable ICU 63 */ UCPTRIE_TYPE_ANY = -1, /** * Fast/simple/larger BMP data structure. Use functions and "fast" macros. - * @draft ICU 63 + * @stable ICU 63 */ UCPTRIE_TYPE_FAST, /** * Small/slower BMP data structure. Use functions and "small" macros. - * @draft ICU 63 + * @stable ICU 63 */ UCPTRIE_TYPE_SMALL }; @@ -145,30 +143,30 @@ typedef enum UCPTrieType UCPTrieType; * @see umutablecptrie_buildImmutable * @see ucptrie_openFromBinary * @see ucptrie_getValueWidth - * @draft ICU 63 + * @stable ICU 63 */ enum UCPTrieValueWidth { /** * For ucptrie_openFromBinary() to accept any data value width. * ucptrie_getValueWidth() will return the actual data value width. - * @draft ICU 63 + * @stable ICU 63 */ UCPTRIE_VALUE_BITS_ANY = -1, /** * The trie stores 16 bits per data value. * It returns them as unsigned values 0..0xffff=65535. - * @draft ICU 63 + * @stable ICU 63 */ UCPTRIE_VALUE_BITS_16, /** * The trie stores 32 bits per data value. - * @draft ICU 63 + * @stable ICU 63 */ UCPTRIE_VALUE_BITS_32, /** * The trie stores 8 bits per data value. * It returns them as unsigned values 0..0xff=255. - * @draft ICU 63 + * @stable ICU 63 */ UCPTRIE_VALUE_BITS_8 }; @@ -200,7 +198,7 @@ typedef enum UCPTrieValueWidth UCPTrieValueWidth; * @see umutablecptrie_open * @see umutablecptrie_buildImmutable * @see ucptrie_toBinary - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UCPTrie * U_EXPORT2 ucptrie_openFromBinary(UCPTrieType type, UCPTrieValueWidth valueWidth, @@ -211,30 +209,11 @@ ucptrie_openFromBinary(UCPTrieType type, UCPTrieValueWidth valueWidth, * Closes a trie and releases associated memory. * * @param trie the trie - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI void U_EXPORT2 ucptrie_close(UCPTrie *trie); -#if U_SHOW_CPLUSPLUS_API - -U_NAMESPACE_BEGIN - -/** - * \class LocalUCPTriePointer - * "Smart pointer" class, closes a UCPTrie via ucptrie_close(). - * For most methods see the LocalPointerBase base class. - * - * @see LocalPointerBase - * @see LocalPointer - * @draft ICU 63 - */ -U_DEFINE_LOCAL_OPEN_POINTER(LocalUCPTriePointer, UCPTrie, ucptrie_close); - -U_NAMESPACE_END - -#endif - /** * Returns the trie type. * @@ -242,7 +221,7 @@ U_NAMESPACE_END * @return the trie type * @see ucptrie_openFromBinary * @see UCPTRIE_TYPE_ANY - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UCPTrieType U_EXPORT2 ucptrie_getType(const UCPTrie *trie); @@ -254,7 +233,7 @@ ucptrie_getType(const UCPTrie *trie); * @return the number of bits in a trie data value * @see ucptrie_openFromBinary * @see UCPTRIE_VALUE_BITS_ANY - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UCPTrieValueWidth U_EXPORT2 ucptrie_getValueWidth(const UCPTrie *trie); @@ -271,7 +250,7 @@ ucptrie_getValueWidth(const UCPTrie *trie); * @param c the code point * @return the trie value, * or the trie error value if the code point is not in the range 0..U+10FFFF - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI uint32_t U_EXPORT2 ucptrie_get(const UCPTrie *trie, UChar32 c); @@ -310,7 +289,7 @@ ucptrie_get(const UCPTrie *trie, UChar32 c); * may have been modified by filter(context, trie value) * if that function pointer is not NULL * @return the range end code point, or -1 if start is not a valid code point - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UChar32 U_EXPORT2 ucptrie_getRange(const UCPTrie *trie, UChar32 start, @@ -330,7 +309,7 @@ ucptrie_getRange(const UCPTrie *trie, UChar32 start, * @return the number of bytes written or (if buffer overflow) needed for the trie * * @see ucptrie_openFromBinary() - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI int32_t U_EXPORT2 ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode *pErrorCode); @@ -341,7 +320,7 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * * Do not use this macro in any other way. * * @see UCPTRIE_VALUE_BITS_16 - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_16(trie, i) ((trie)->data.ptr16[i]) @@ -351,7 +330,7 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * * Do not use this macro in any other way. * * @see UCPTRIE_VALUE_BITS_32 - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_32(trie, i) ((trie)->data.ptr32[i]) @@ -361,7 +340,7 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * * Do not use this macro in any other way. * * @see UCPTRIE_VALUE_BITS_8 - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_8(trie, i) ((trie)->data.ptr8[i]) @@ -373,7 +352,7 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width * @param c (UChar32, in) the input code point * @return The code point's trie value. - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_FAST_GET(trie, dataAccess, c) dataAccess(trie, _UCPTRIE_CP_INDEX(trie, 0xffff, c)) @@ -385,7 +364,7 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width * @param c (UChar32, in) the input code point * @return The code point's trie value. - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_SMALL_GET(trie, dataAccess, c) \ dataAccess(trie, _UCPTRIE_CP_INDEX(trie, UCPTRIE_SMALL_MAX, c)) @@ -401,9 +380,9 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * * @param limit (const UChar *, in) the limit pointer for the text, or NULL if NUL-terminated * @param c (UChar32, out) variable for the code point * @param result (out) variable for the trie lookup result - * @draft ICU 63 + * @stable ICU 63 */ -#define UCPTRIE_FAST_U16_NEXT(trie, dataAccess, src, limit, c, result) { \ +#define UCPTRIE_FAST_U16_NEXT(trie, dataAccess, src, limit, c, result) UPRV_BLOCK_MACRO_BEGIN { \ (c) = *(src)++; \ int32_t __index; \ if (!U16_IS_SURROGATE(c)) { \ @@ -419,7 +398,7 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * } \ } \ (result) = dataAccess(trie, __index); \ -} +} UPRV_BLOCK_MACRO_END /** * UTF-16: Reads the previous code point (UChar32 c, out), pre-decrements src, @@ -432,9 +411,9 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * * @param src (const UChar *, in/out) the source text pointer * @param c (UChar32, out) variable for the code point * @param result (out) variable for the trie lookup result - * @draft ICU 63 + * @stable ICU 63 */ -#define UCPTRIE_FAST_U16_PREV(trie, dataAccess, start, src, c, result) { \ +#define UCPTRIE_FAST_U16_PREV(trie, dataAccess, start, src, c, result) UPRV_BLOCK_MACRO_BEGIN { \ (c) = *--(src); \ int32_t __index; \ if (!U16_IS_SURROGATE(c)) { \ @@ -450,7 +429,7 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * } \ } \ (result) = dataAccess(trie, __index); \ -} +} UPRV_BLOCK_MACRO_END /** * UTF-8: Post-increments src and gets a value from the trie. @@ -466,9 +445,9 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * * @param src (const char *, in/out) the source text pointer * @param limit (const char *, in) the limit pointer for the text (must not be NULL) * @param result (out) variable for the trie lookup result - * @draft ICU 63 + * @stable ICU 63 */ -#define UCPTRIE_FAST_U8_NEXT(trie, dataAccess, src, limit, result) { \ +#define UCPTRIE_FAST_U8_NEXT(trie, dataAccess, src, limit, result) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __lead = (uint8_t)*(src)++; \ if (!U8_IS_SINGLE(__lead)) { \ uint8_t __t1, __t2, __t3; \ @@ -496,7 +475,7 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * } \ } \ (result) = dataAccess(trie, __lead); \ -} +} UPRV_BLOCK_MACRO_END /** * UTF-8: Pre-decrements src and gets a value from the trie. @@ -512,9 +491,9 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * * @param start (const char *, in) the start pointer for the text * @param src (const char *, in/out) the source text pointer * @param result (out) variable for the trie lookup result - * @draft ICU 63 + * @stable ICU 63 */ -#define UCPTRIE_FAST_U8_PREV(trie, dataAccess, start, src, result) { \ +#define UCPTRIE_FAST_U8_PREV(trie, dataAccess, start, src, result) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __index = (uint8_t)*--(src); \ if (!U8_IS_SINGLE(__index)) { \ __index = ucptrie_internalU8PrevIndex((trie), __index, (const uint8_t *)(start), \ @@ -523,7 +502,7 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * __index >>= 3; \ } \ (result) = dataAccess(trie, __index); \ -} +} UPRV_BLOCK_MACRO_END /** * Returns a trie value for an ASCII code point, without range checking. @@ -532,7 +511,7 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width * @param c (UChar32, in) the input code point; must be U+0000..U+007F * @return The ASCII code point's trie value. - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_ASCII_GET(trie, dataAccess, c) dataAccess(trie, c) @@ -545,7 +524,7 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width * @param c (UChar32, in) the input code point, must be U+0000..U+FFFF * @return The BMP code point's trie value. - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_FAST_BMP_GET(trie, dataAccess, c) dataAccess(trie, _UCPTRIE_FAST_INDEX(trie, c)) @@ -557,7 +536,7 @@ ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode * * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width * @param c (UChar32, in) the input code point, must be U+10000..U+10FFFF * @return The supplementary code point's trie value. - * @draft ICU 63 + * @stable ICU 63 */ #define UCPTRIE_FAST_SUPP_GET(trie, dataAccess, c) dataAccess(trie, _UCPTRIE_SMALL_INDEX(trie, c)) @@ -642,5 +621,24 @@ ucptrie_internalU8PrevIndex(const UCPTrie *trie, UChar32 c, U_CDECL_END #endif // U_IN_DOXYGEN -#endif // U_HIDE_DRAFT_API + +#if U_SHOW_CPLUSPLUS_API + +U_NAMESPACE_BEGIN + +/** + * \class LocalUCPTriePointer + * "Smart pointer" class, closes a UCPTrie via ucptrie_close(). + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @stable ICU 63 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUCPTriePointer, UCPTrie, ucptrie_close); + +U_NAMESPACE_END + +#endif // U_SHOW_CPLUSPLUS_API + #endif diff --git a/deps/icu-small/source/common/unicode/ucurr.h b/deps/icu-small/source/common/unicode/ucurr.h index a1c6de80b772f7..7149e7adf13067 100644 --- a/deps/icu-small/source/common/unicode/ucurr.h +++ b/deps/icu-small/source/common/unicode/ucurr.h @@ -159,14 +159,14 @@ ucurr_unregister(UCurrRegistryKey key, UErrorCode* status); * @param currency null-terminated 3-letter ISO 4217 code * @param locale locale in which to display currency * @param nameStyle selector for which kind of name to return - * @param isChoiceFormat fill-in set to TRUE if the returned value - * is a ChoiceFormat pattern; otherwise it is a static string + * @param isChoiceFormat always set to FALSE, or can be NULL; + * display names are static strings; + * since ICU 4.4, ChoiceFormat patterns are no longer supported * @param len fill-in parameter to receive length of result * @param ec error code * @return pointer to display string of 'len' UChars. If the resource * data contains no entry for 'currency', then 'currency' itself is - * returned. If *isChoiceFormat is TRUE, then the result is a - * ChoiceFormat pattern. Otherwise it is a static string. + * returned. * @stable ICU 2.6 */ U_STABLE const UChar* U_EXPORT2 @@ -183,8 +183,9 @@ ucurr_getName(const UChar* currency, * currency object in the en_US locale is "US dollar" or "US dollars". * @param currency null-terminated 3-letter ISO 4217 code * @param locale locale in which to display currency - * @param isChoiceFormat fill-in set to TRUE if the returned value - * is a ChoiceFormat pattern; otherwise it is a static string + * @param isChoiceFormat always set to FALSE, or can be NULL; + * display names are static strings; + * since ICU 4.4, ChoiceFormat patterns are no longer supported * @param pluralCount plural count * @param len fill-in parameter to receive length of result * @param ec error code @@ -320,7 +321,7 @@ typedef enum UCurrCurrencyType { * Provides a UEnumeration object for listing ISO-4217 codes. * @param currType You can use one of several UCurrCurrencyType values for this * variable. You can also | (or) them together to get a specific list of - * currencies. Most people will want to use the (UCURR_CURRENCY|UCURR_NON_DEPRECATED) value to + * currencies. Most people will want to use the (UCURR_COMMON|UCURR_NON_DEPRECATED) value to * get a list of current currencies. * @param pErrorCode Error code * @stable ICU 3.2 diff --git a/deps/icu-small/source/common/unicode/udata.h b/deps/icu-small/source/common/unicode/udata.h index 6419c359f606af..8236877b443d3d 100644 --- a/deps/icu-small/source/common/unicode/udata.h +++ b/deps/icu-small/source/common/unicode/udata.h @@ -264,25 +264,6 @@ udata_openChoice(const char *path, const char *type, const char *name, U_STABLE void U_EXPORT2 udata_close(UDataMemory *pData); -#if U_SHOW_CPLUSPLUS_API - -U_NAMESPACE_BEGIN - -/** - * \class LocalUDataMemoryPointer - * "Smart pointer" class, closes a UDataMemory via udata_close(). - * For most methods see the LocalPointerBase base class. - * - * @see LocalPointerBase - * @see LocalPointer - * @stable ICU 4.4 - */ -U_DEFINE_LOCAL_OPEN_POINTER(LocalUDataMemoryPointer, UDataMemory, udata_close); - -U_NAMESPACE_END - -#endif - /** * Get the pointer to the actual data inside the data memory. * The data is read-only. @@ -434,4 +415,23 @@ udata_setFileAccess(UDataFileAccess access, UErrorCode *status); U_CDECL_END +#if U_SHOW_CPLUSPLUS_API + +U_NAMESPACE_BEGIN + +/** + * \class LocalUDataMemoryPointer + * "Smart pointer" class, closes a UDataMemory via udata_close(). + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @stable ICU 4.4 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUDataMemoryPointer, UDataMemory, udata_close); + +U_NAMESPACE_END + +#endif // U_SHOW_CPLUSPLUS_API + #endif diff --git a/deps/icu-small/source/common/unicode/uloc.h b/deps/icu-small/source/common/unicode/uloc.h index 5531070841187d..882f79bedca62c 100644 --- a/deps/icu-small/source/common/unicode/uloc.h +++ b/deps/icu-small/source/common/unicode/uloc.h @@ -742,12 +742,18 @@ uloc_getDisplayName(const char* localeID, /** - * Gets the specified locale from a list of all available locales. - * The return value is a pointer to an item of - * a locale name array. Both this array and the pointers - * it contains are owned by ICU and should not be deleted or written through - * by the caller. The locale name is terminated by a null pointer. - * @param n the specific locale name index of the available locale list + * Gets the specified locale from a list of available locales. + * + * This method corresponds to uloc_openAvailableByType called with the + * ULOC_AVAILABLE_DEFAULT type argument. + * + * The return value is a pointer to an item of a locale name array. Both this + * array and the pointers it contains are owned by ICU and should not be + * deleted or written through by the caller. The locale name is terminated by + * a null pointer. + * + * @param n the specific locale name index of the available locale list; + * should not exceed the number returned by uloc_countAvailable. * @return a specified locale name of all available locales * @stable ICU 2.0 */ @@ -762,6 +768,72 @@ uloc_getAvailable(int32_t n); */ U_STABLE int32_t U_EXPORT2 uloc_countAvailable(void); +#ifndef U_HIDE_DRAFT_API + +/** + * Types for uloc_getAvailableByType and uloc_countAvailableByType. + * + * @draft ICU 65 + */ +typedef enum ULocAvailableType { + /** + * Locales that return data when passed to ICU APIs, + * but not including legacy or alias locales. + * + * @draft ICU 65 + */ + ULOC_AVAILABLE_DEFAULT, + + /** + * Legacy or alias locales that return data when passed to ICU APIs. + * Examples of supported legacy or alias locales: + * + * - iw (alias to he) + * - mo (alias to ro) + * - zh_CN (alias to zh_Hans_CN) + * - sr_BA (alias to sr_Cyrl_BA) + * - ars (alias to ar_SA) + * + * The locales in this set are disjoint from the ones in + * ULOC_AVAILABLE_DEFAULT. To get both sets at the same time, use + * ULOC_AVAILABLE_WITH_LEGACY_ALIASES. + * + * @draft ICU 65 + */ + ULOC_AVAILABLE_ONLY_LEGACY_ALIASES, + + /** + * The union of the locales in ULOC_AVAILABLE_DEFAULT and + * ULOC_AVAILABLE_ONLY_LEGACY_ALIAS. + * + * @draft ICU 65 + */ + ULOC_AVAILABLE_WITH_LEGACY_ALIASES, + +#ifndef U_HIDE_INTERNAL_API + /** + * @internal + */ + ULOC_AVAILABLE_COUNT +#endif +} ULocAvailableType; + +/** + * Gets a list of available locales according to the type argument, allowing + * the user to access different sets of supported locales in ICU. + * + * The returned UEnumeration must be closed by the caller. + * + * @param type Type choice from ULocAvailableType. + * @param status Set if an error occurred. + * @return a UEnumeration owned by the caller, or nullptr on failure. + * @draft ICU 65 + */ +U_DRAFT UEnumeration* U_EXPORT2 +uloc_openAvailableByType(ULocAvailableType type, UErrorCode* status); + +#endif // U_HIDE_DRAFT_API + /** * * Gets a list of all available 2-letter language codes defined in ISO 639, diff --git a/deps/icu-small/source/common/unicode/umachine.h b/deps/icu-small/source/common/unicode/umachine.h index 6d932cfcfb2ae4..5cb95e58f37295 100644 --- a/deps/icu-small/source/common/unicode/umachine.h +++ b/deps/icu-small/source/common/unicode/umachine.h @@ -140,6 +140,42 @@ #define U_FINAL final #endif +// Before ICU 65, function-like, multi-statement ICU macros were just defined as +// series of statements wrapped in { } blocks and the caller could choose to +// either treat them as if they were actual functions and end the invocation +// with a trailing ; creating an empty statement after the block or else omit +// this trailing ; using the knowledge that the macro would expand to { }. +// +// But doing so doesn't work well with macros that look like functions and +// compiler warnings about empty statements (ICU-20601) and ICU 65 therefore +// switches to the standard solution of wrapping such macros in do { } while. +// +// This will however break existing code that depends on being able to invoke +// these macros without a trailing ; so to be able to remain compatible with +// such code the wrapper is itself defined as macros so that it's possible to +// build ICU 65 and later with the old macro behaviour, like this: +// +// export CPPFLAGS='-DUPRV_BLOCK_MACRO_BEGIN="" -DUPRV_BLOCK_MACRO_END=""' +// runConfigureICU ... +// + +/** + * \def UPRV_BLOCK_MACRO_BEGIN + * Defined as the "do" keyword by default. + * @internal + */ +#ifndef UPRV_BLOCK_MACRO_BEGIN +#define UPRV_BLOCK_MACRO_BEGIN do +#endif + +/** + * \def UPRV_BLOCK_MACRO_END + * Defined as "while (FALSE)" by default. + * @internal + */ +#ifndef UPRV_BLOCK_MACRO_END +#define UPRV_BLOCK_MACRO_END while (FALSE) +#endif /*==========================================================================*/ /* limits for int32_t etc., like in POSIX inttypes.h */ diff --git a/deps/icu-small/source/common/unicode/umutablecptrie.h b/deps/icu-small/source/common/unicode/umutablecptrie.h index e75191a4495209..13e71ef25e8c87 100644 --- a/deps/icu-small/source/common/unicode/umutablecptrie.h +++ b/deps/icu-small/source/common/unicode/umutablecptrie.h @@ -9,8 +9,6 @@ #include "unicode/utypes.h" -#ifndef U_HIDE_DRAFT_API - #include "unicode/localpointer.h" #include "unicode/ucpmap.h" #include "unicode/ucptrie.h" @@ -44,7 +42,7 @@ U_CDECL_BEGIN * * @see UCPTrie * @see umutablecptrie_buildImmutable - * @draft ICU 63 + * @stable ICU 63 */ typedef struct UMutableCPTrie UMutableCPTrie; @@ -59,7 +57,7 @@ typedef struct UMutableCPTrie UMutableCPTrie; * @param errorValue the value for out-of-range code points and ill-formed UTF-8/16 * @param pErrorCode an in/out ICU UErrorCode * @return the trie - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UMutableCPTrie * U_EXPORT2 umutablecptrie_open(uint32_t initialValue, uint32_t errorValue, UErrorCode *pErrorCode); @@ -71,7 +69,7 @@ umutablecptrie_open(uint32_t initialValue, uint32_t errorValue, UErrorCode *pErr * @param other the trie to clone * @param pErrorCode an in/out ICU UErrorCode * @return the trie clone - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UMutableCPTrie * U_EXPORT2 umutablecptrie_clone(const UMutableCPTrie *other, UErrorCode *pErrorCode); @@ -80,7 +78,7 @@ umutablecptrie_clone(const UMutableCPTrie *other, UErrorCode *pErrorCode); * Closes a mutable trie and releases associated memory. * * @param trie the trie - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI void U_EXPORT2 umutablecptrie_close(UMutableCPTrie *trie); @@ -96,7 +94,7 @@ U_NAMESPACE_BEGIN * * @see LocalPointerBase * @see LocalPointer - * @draft ICU 63 + * @stable ICU 63 */ U_DEFINE_LOCAL_OPEN_POINTER(LocalUMutableCPTriePointer, UMutableCPTrie, umutablecptrie_close); @@ -111,7 +109,7 @@ U_NAMESPACE_END * @param map the source map * @param pErrorCode an in/out ICU UErrorCode * @return the mutable trie - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UMutableCPTrie * U_EXPORT2 umutablecptrie_fromUCPMap(const UCPMap *map, UErrorCode *pErrorCode); @@ -123,7 +121,7 @@ umutablecptrie_fromUCPMap(const UCPMap *map, UErrorCode *pErrorCode); * @param trie the immutable trie * @param pErrorCode an in/out ICU UErrorCode * @return the mutable trie - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UMutableCPTrie * U_EXPORT2 umutablecptrie_fromUCPTrie(const UCPTrie *trie, UErrorCode *pErrorCode); @@ -134,7 +132,7 @@ umutablecptrie_fromUCPTrie(const UCPTrie *trie, UErrorCode *pErrorCode); * @param trie the trie * @param c the code point * @return the value - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI uint32_t U_EXPORT2 umutablecptrie_get(const UMutableCPTrie *trie, UChar32 c); @@ -166,7 +164,7 @@ umutablecptrie_get(const UMutableCPTrie *trie, UChar32 c); * may have been modified by filter(context, trie value) * if that function pointer is not NULL * @return the range end code point, or -1 if start is not a valid code point - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UChar32 U_EXPORT2 umutablecptrie_getRange(const UMutableCPTrie *trie, UChar32 start, @@ -180,7 +178,7 @@ umutablecptrie_getRange(const UMutableCPTrie *trie, UChar32 start, * @param c the code point * @param value the value * @param pErrorCode an in/out ICU UErrorCode - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI void U_EXPORT2 umutablecptrie_set(UMutableCPTrie *trie, UChar32 c, uint32_t value, UErrorCode *pErrorCode); @@ -194,7 +192,7 @@ umutablecptrie_set(UMutableCPTrie *trie, UChar32 c, uint32_t value, UErrorCode * * @param end the last code point to get the value (inclusive) * @param value the value * @param pErrorCode an in/out ICU UErrorCode - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI void U_EXPORT2 umutablecptrie_setRange(UMutableCPTrie *trie, @@ -229,7 +227,7 @@ umutablecptrie_setRange(UMutableCPTrie *trie, * @param pErrorCode an in/out ICU UErrorCode * * @see umutablecptrie_fromUCPTrie - * @draft ICU 63 + * @stable ICU 63 */ U_CAPI UCPTrie * U_EXPORT2 umutablecptrie_buildImmutable(UMutableCPTrie *trie, UCPTrieType type, UCPTrieValueWidth valueWidth, @@ -237,5 +235,4 @@ umutablecptrie_buildImmutable(UMutableCPTrie *trie, UCPTrieType type, UCPTrieVal U_CDECL_END -#endif // U_HIDE_DRAFT_API #endif diff --git a/deps/icu-small/source/common/unicode/unifilt.h b/deps/icu-small/source/common/unicode/unifilt.h index 99cce785b6eec8..1a77089233bf10 100644 --- a/deps/icu-small/source/common/unicode/unifilt.h +++ b/deps/icu-small/source/common/unicode/unifilt.h @@ -12,6 +12,10 @@ #ifndef UNIFILT_H #define UNIFILT_H +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/unifunct.h" #include "unicode/unimatch.h" @@ -67,6 +71,14 @@ class U_COMMON_API UnicodeFilter : public UnicodeFunctor, public UnicodeMatcher */ virtual ~UnicodeFilter(); + /** + * Clones this object polymorphically. + * The caller owns the result and should delete it when done. + * @return clone, or nullptr if an error occurred + * @stable ICU 2.4 + */ + virtual UnicodeFilter* clone() const = 0; + /** * Returns true for characters that are in the selected * subset. In other words, if a character is to be @@ -119,4 +131,6 @@ class U_COMMON_API UnicodeFilter : public UnicodeFunctor, public UnicodeMatcher U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/unifunct.h b/deps/icu-small/source/common/unicode/unifunct.h index 66a02ce7cd5ce8..2b1b766ea76187 100644 --- a/deps/icu-small/source/common/unicode/unifunct.h +++ b/deps/icu-small/source/common/unicode/unifunct.h @@ -13,6 +13,9 @@ #define UNIFUNCT_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" /** @@ -124,4 +127,6 @@ class U_COMMON_API UnicodeFunctor : public UObject { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/unimatch.h b/deps/icu-small/source/common/unicode/unimatch.h index 8bf39950187b1b..2d3c5210c38e25 100644 --- a/deps/icu-small/source/common/unicode/unimatch.h +++ b/deps/icu-small/source/common/unicode/unimatch.h @@ -17,6 +17,7 @@ * \brief C++ API: Unicode Matcher */ +#if U_SHOW_CPLUSPLUS_API U_NAMESPACE_BEGIN @@ -162,4 +163,6 @@ class U_COMMON_API UnicodeMatcher /* not : public UObject because this is an int U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/uniset.h b/deps/icu-small/source/common/unicode/uniset.h index e5e7726d604a73..18cc9376442a2f 100644 --- a/deps/icu-small/source/common/unicode/uniset.h +++ b/deps/icu-small/source/common/unicode/uniset.h @@ -13,6 +13,10 @@ #ifndef UNICODESET_H #define UNICODESET_H +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/ucpmap.h" #include "unicode/unifilt.h" #include "unicode/unistr.h" @@ -501,7 +505,7 @@ class U_COMMON_API UnicodeSet U_FINAL : public UnicodeFilter { * @see cloneAsThawed * @stable ICU 2.0 */ - virtual UnicodeFunctor* clone() const; + virtual UnicodeSet* clone() const; /** * Returns the hash code value for this set. @@ -579,7 +583,7 @@ class U_COMMON_API UnicodeSet U_FINAL : public UnicodeFilter { * @see cloneAsThawed * @stable ICU 3.8 */ - UnicodeFunctor *freeze(); + UnicodeSet *freeze(); /** * Clone the set and make the clone mutable. @@ -589,7 +593,7 @@ class U_COMMON_API UnicodeSet U_FINAL : public UnicodeFilter { * @see isFrozen * @stable ICU 3.8 */ - UnicodeFunctor *cloneAsThawed() const; + UnicodeSet *cloneAsThawed() const; //---------------------------------------------------------------- // Public API @@ -1651,11 +1655,10 @@ class U_COMMON_API UnicodeSet U_FINAL : public UnicodeFilter { const UnicodeSet* inclusions, UErrorCode &status); -#ifndef U_HIDE_DRAFT_API // Skipped: ucpmap.h is draft only. + // UCPMap is now stable ICU 63 void applyIntPropertyValue(const UCPMap *map, UCPMapValueFilter *filter, const void *context, UErrorCode &errorCode); -#endif /* U_HIDE_DRAFT_API */ /** * Set the new pattern to cache. @@ -1736,4 +1739,6 @@ inline int32_t UnicodeSet::spanBack(const UnicodeString &s, int32_t limit, USetS U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/unistr.h b/deps/icu-small/source/common/unicode/unistr.h index 8fd144425e87c0..da79053765acf6 100644 --- a/deps/icu-small/source/common/unicode/unistr.h +++ b/deps/icu-small/source/common/unicode/unistr.h @@ -28,8 +28,11 @@ * \brief C++ API: Unicode String */ -#include #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + +#include #include "unicode/char16ptr.h" #include "unicode/rep.h" #include "unicode/std_string.h" @@ -209,7 +212,9 @@ class UnicodeStringAppendable; // unicode/appendable.h * similar functionality as the Java String and StringBuffer/StringBuilder classes. * It is a concrete implementation of the abstract class Replaceable (for transliteration). * - * A UnicodeString may also "alias" an external array of characters + * The UnicodeString equivalent of std::string’s clear() is remove(). + * + * A UnicodeString may "alias" an external array of characters * (that is, point to it, rather than own the array) * whose lifetime must then at least match the lifetime of the aliasing object. * This aliasing may be preserved when returning a UnicodeString by value, @@ -2092,8 +2097,7 @@ class U_COMMON_API UnicodeString : public Replaceable * s.truncate(0); // set to an empty string (complete truncation), or * s=UnicodeString(); // assign an empty string, or * s.setTo((UChar32)-1); // set to a pseudo code point that is out of range, or - * static const char16_t nul=0; - * s.setTo(&nul, 0); // set to an empty C Unicode string + * s.setTo(u"", 0); // set to an empty C Unicode string * } * \endcode * @@ -2534,11 +2538,14 @@ class U_COMMON_API UnicodeString : public Replaceable /* Remove operations */ /** - * Remove all characters from the UnicodeString object. + * Removes all characters from the UnicodeString object and clears the bogus flag. + * This is the UnicodeString equivalent of std::string’s clear(). + * * @return a reference to this + * @see setToBogus * @stable ICU 2.0 */ - inline UnicodeString& remove(void); + inline UnicodeString& remove(); /** * Remove the characters in the range @@ -3034,11 +3041,11 @@ class U_COMMON_API UnicodeString : public Replaceable * uint16_t * constructor. * Delegates to UnicodeString(const char16_t *, int32_t). * @param text UTF-16 string - * @param length string length + * @param textLength string length * @stable ICU 59 */ - UnicodeString(const uint16_t *text, int32_t length) : - UnicodeString(ConstChar16Ptr(text), length) {} + UnicodeString(const uint16_t *text, int32_t textLength) : + UnicodeString(ConstChar16Ptr(text), textLength) {} #endif #if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN) @@ -3047,21 +3054,21 @@ class U_COMMON_API UnicodeString : public Replaceable * (Only defined if U_SIZEOF_WCHAR_T==2.) * Delegates to UnicodeString(const char16_t *, int32_t). * @param text NUL-terminated UTF-16 string - * @param length string length + * @param textLength string length * @stable ICU 59 */ - UnicodeString(const wchar_t *text, int32_t length) : - UnicodeString(ConstChar16Ptr(text), length) {} + UnicodeString(const wchar_t *text, int32_t textLength) : + UnicodeString(ConstChar16Ptr(text), textLength) {} #endif /** * nullptr_t constructor. * Effectively the same as the default constructor, makes an empty string object. * @param text nullptr - * @param length ignored + * @param textLength ignored * @stable ICU 59 */ - inline UnicodeString(const std::nullptr_t text, int32_t length); + inline UnicodeString(const std::nullptr_t text, int32_t textLength); /** * Readonly-aliasing char16_t* constructor. @@ -3266,13 +3273,13 @@ class U_COMMON_API UnicodeString : public Replaceable * } * \endcode * @param src String using only invariant characters. - * @param length Length of src, or -1 if NUL-terminated. + * @param textLength Length of src, or -1 if NUL-terminated. * @param inv Signature-distinguishing paramater, use US_INV. * * @see US_INV * @stable ICU 3.2 */ - UnicodeString(const char *src, int32_t length, enum EInvariant inv); + UnicodeString(const char *src, int32_t textLength, enum EInvariant inv); /** @@ -3323,9 +3330,6 @@ class U_COMMON_API UnicodeString : public Replaceable * Clones can be used concurrently in multiple threads. * If a subclass does not implement clone(), or if an error occurs, * then NULL is returned. - * The clone functions in all subclasses return a pointer to a Replaceable - * because some compilers do not support covariant (same-as-this) - * return types; cast to the appropriate subclass if necessary. * The caller must delete the clone. * * @return a clone of this object @@ -3334,7 +3338,7 @@ class U_COMMON_API UnicodeString : public Replaceable * @see getDynamicClassID * @stable ICU 2.6 */ - virtual Replaceable *clone() const; + virtual UnicodeString *clone() const; /** Destructor. * @stable ICU 2.0 @@ -4748,4 +4752,6 @@ UnicodeString::reverse(int32_t start, U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/unorm.h b/deps/icu-small/source/common/unicode/unorm.h index 3839de129573c1..09dd366a968c1b 100644 --- a/deps/icu-small/source/common/unicode/unorm.h +++ b/deps/icu-small/source/common/unicode/unorm.h @@ -131,6 +131,8 @@ // Do not conditionalize the following enum with #ifndef U_HIDE_DEPRECATED_API, // it is needed for layout of Normalizer object. +#ifndef U_FORCE_HIDE_DEPRECATED_API + /** * Constants for normalization modes. * @deprecated ICU 56 Use unorm2.h instead. @@ -155,6 +157,8 @@ typedef enum { UNORM_MODE_COUNT } UNormalizationMode; +#endif // U_FORCE_HIDE_DEPRECATED_API + #ifndef U_HIDE_DEPRECATED_API /** diff --git a/deps/icu-small/source/common/unicode/uobject.h b/deps/icu-small/source/common/unicode/uobject.h index 53b8eb005f4cc0..6a137af83c2456 100644 --- a/deps/icu-small/source/common/unicode/uobject.h +++ b/deps/icu-small/source/common/unicode/uobject.h @@ -20,6 +20,9 @@ #define __UOBJECT_H__ #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/platform.h" /** @@ -43,7 +46,7 @@ * @stable ICU 4.2. Since ICU 64, Use U_NOEXCEPT instead. See ICU-20422. */ #ifndef U_NO_THROW -#define U_NO_THROW throw() +#define U_NO_THROW U_NOEXCEPT #endif /*===========================================================================*/ @@ -212,11 +215,8 @@ class U_COMMON_API UMemory { * The clone() function is not available in UObject because it is not * implemented by all ICU classes. * Many ICU services provide a clone() function for their class trees, - * defined on the service's C++ base class, and all subclasses within that - * service class tree return a pointer to the service base class + * defined on the service's C++ base class * (which itself is a subclass of UObject). - * This is because some compilers do not support covariant (same-as-this) - * return types; cast to the appropriate subclass if necessary. * * @stable ICU 2.2 */ @@ -319,4 +319,6 @@ class U_COMMON_API UObject : public UMemory { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/urename.h b/deps/icu-small/source/common/unicode/urename.h index eaf56c9614d7f2..e302bf0976e01d 100644 --- a/deps/icu-small/source/common/unicode/urename.h +++ b/deps/icu-small/source/common/unicode/urename.h @@ -193,10 +193,13 @@ #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) #define res_load U_ICU_ENTRY_POINT_RENAME(res_load) @@ -523,6 +526,7 @@ #define ucal_getDefaultTimeZone U_ICU_ENTRY_POINT_RENAME(ucal_getDefaultTimeZone) #define ucal_getFieldDifference U_ICU_ENTRY_POINT_RENAME(ucal_getFieldDifference) #define ucal_getGregorianChange U_ICU_ENTRY_POINT_RENAME(ucal_getGregorianChange) +#define ucal_getHostTimeZone U_ICU_ENTRY_POINT_RENAME(ucal_getHostTimeZone) #define ucal_getKeywordValuesForLocale U_ICU_ENTRY_POINT_RENAME(ucal_getKeywordValuesForLocale) #define ucal_getLimit U_ICU_ENTRY_POINT_RENAME(ucal_getLimit) #define ucal_getLocaleByType U_ICU_ENTRY_POINT_RENAME(ucal_getLocaleByType) @@ -575,7 +579,6 @@ #define ucasemap_getLocale U_ICU_ENTRY_POINT_RENAME(ucasemap_getLocale) #define ucasemap_getOptions U_ICU_ENTRY_POINT_RENAME(ucasemap_getOptions) #define ucasemap_internalUTF8ToTitle U_ICU_ENTRY_POINT_RENAME(ucasemap_internalUTF8ToTitle) -#define ucasemap_mapUTF8 U_ICU_ENTRY_POINT_RENAME(ucasemap_mapUTF8) #define ucasemap_open U_ICU_ENTRY_POINT_RENAME(ucasemap_open) #define ucasemap_setBreakIterator U_ICU_ENTRY_POINT_RENAME(ucasemap_setBreakIterator) #define ucasemap_setLocale U_ICU_ENTRY_POINT_RENAME(ucasemap_setLocale) @@ -930,16 +933,9 @@ #define ufieldpositer_close U_ICU_ENTRY_POINT_RENAME(ufieldpositer_close) #define ufieldpositer_next U_ICU_ENTRY_POINT_RENAME(ufieldpositer_next) #define ufieldpositer_open U_ICU_ENTRY_POINT_RENAME(ufieldpositer_open) -#define ufile_close_translit U_ICU_ENTRY_POINT_RENAME(ufile_close_translit) -#define ufile_fill_uchar_buffer U_ICU_ENTRY_POINT_RENAME(ufile_fill_uchar_buffer) -#define ufile_flush_io U_ICU_ENTRY_POINT_RENAME(ufile_flush_io) -#define ufile_flush_translit U_ICU_ENTRY_POINT_RENAME(ufile_flush_translit) #define ufile_getch U_ICU_ENTRY_POINT_RENAME(ufile_getch) #define ufile_getch32 U_ICU_ENTRY_POINT_RENAME(ufile_getch32) -#define ufmt_64tou U_ICU_ENTRY_POINT_RENAME(ufmt_64tou) #define ufmt_close U_ICU_ENTRY_POINT_RENAME(ufmt_close) -#define ufmt_defaultCPToUnicode U_ICU_ENTRY_POINT_RENAME(ufmt_defaultCPToUnicode) -#define ufmt_digitvalue U_ICU_ENTRY_POINT_RENAME(ufmt_digitvalue) #define ufmt_getArrayItemByIndex U_ICU_ENTRY_POINT_RENAME(ufmt_getArrayItemByIndex) #define ufmt_getArrayLength U_ICU_ENTRY_POINT_RENAME(ufmt_getArrayLength) #define ufmt_getDate U_ICU_ENTRY_POINT_RENAME(ufmt_getDate) @@ -951,11 +947,7 @@ #define ufmt_getType U_ICU_ENTRY_POINT_RENAME(ufmt_getType) #define ufmt_getUChars U_ICU_ENTRY_POINT_RENAME(ufmt_getUChars) #define ufmt_isNumeric U_ICU_ENTRY_POINT_RENAME(ufmt_isNumeric) -#define ufmt_isdigit U_ICU_ENTRY_POINT_RENAME(ufmt_isdigit) #define ufmt_open U_ICU_ENTRY_POINT_RENAME(ufmt_open) -#define ufmt_ptou U_ICU_ENTRY_POINT_RENAME(ufmt_ptou) -#define ufmt_uto64 U_ICU_ENTRY_POINT_RENAME(ufmt_uto64) -#define ufmt_utop U_ICU_ENTRY_POINT_RENAME(ufmt_utop) #define ufmtval_getString U_ICU_ENTRY_POINT_RENAME(ufmtval_getString) #define ufmtval_nextPosition U_ICU_ENTRY_POINT_RENAME(ufmtval_nextPosition) #define ugender_getInstance U_ICU_ENTRY_POINT_RENAME(ugender_getInstance) @@ -1103,6 +1095,7 @@ #define uloc_getVariant U_ICU_ENTRY_POINT_RENAME(uloc_getVariant) #define uloc_isRightToLeft U_ICU_ENTRY_POINT_RENAME(uloc_isRightToLeft) #define uloc_minimizeSubtags U_ICU_ENTRY_POINT_RENAME(uloc_minimizeSubtags) +#define uloc_openAvailableByType U_ICU_ENTRY_POINT_RENAME(uloc_openAvailableByType) #define uloc_openKeywordList U_ICU_ENTRY_POINT_RENAME(uloc_openKeywordList) #define uloc_openKeywords U_ICU_ENTRY_POINT_RENAME(uloc_openKeywords) #define uloc_setDefault U_ICU_ENTRY_POINT_RENAME(uloc_setDefault) @@ -1159,9 +1152,6 @@ #define umsg_toPattern U_ICU_ENTRY_POINT_RENAME(umsg_toPattern) #define umsg_vformat U_ICU_ENTRY_POINT_RENAME(umsg_vformat) #define umsg_vparse U_ICU_ENTRY_POINT_RENAME(umsg_vparse) -#define umtx_condBroadcast U_ICU_ENTRY_POINT_RENAME(umtx_condBroadcast) -#define umtx_condSignal U_ICU_ENTRY_POINT_RENAME(umtx_condSignal) -#define umtx_condWait U_ICU_ENTRY_POINT_RENAME(umtx_condWait) #define umtx_lock U_ICU_ENTRY_POINT_RENAME(umtx_lock) #define umtx_unlock U_ICU_ENTRY_POINT_RENAME(umtx_unlock) #define umutablecptrie_buildImmutable U_ICU_ENTRY_POINT_RENAME(umutablecptrie_buildImmutable) @@ -1327,7 +1317,6 @@ #define uprv_decNumberAbs U_ICU_ENTRY_POINT_RENAME(uprv_decNumberAbs) #define uprv_decNumberAdd U_ICU_ENTRY_POINT_RENAME(uprv_decNumberAdd) #define uprv_decNumberAnd U_ICU_ENTRY_POINT_RENAME(uprv_decNumberAnd) -#define uprv_decNumberClass U_ICU_ENTRY_POINT_RENAME(uprv_decNumberClass) #define uprv_decNumberClassToString U_ICU_ENTRY_POINT_RENAME(uprv_decNumberClassToString) #define uprv_decNumberCompare U_ICU_ENTRY_POINT_RENAME(uprv_decNumberCompare) #define uprv_decNumberCompareSignal U_ICU_ENTRY_POINT_RENAME(uprv_decNumberCompareSignal) @@ -1393,6 +1382,7 @@ #define uprv_dlsym_func U_ICU_ENTRY_POINT_RENAME(uprv_dlsym_func) #define uprv_eastrncpy U_ICU_ENTRY_POINT_RENAME(uprv_eastrncpy) #define uprv_ebcdicFromAscii U_ICU_ENTRY_POINT_RENAME(uprv_ebcdicFromAscii) +#define uprv_ebcdicToAscii U_ICU_ENTRY_POINT_RENAME(uprv_ebcdicToAscii) #define uprv_ebcdicToLowercaseAscii U_ICU_ENTRY_POINT_RENAME(uprv_ebcdicToLowercaseAscii) #define uprv_ebcdictolower U_ICU_ENTRY_POINT_RENAME(uprv_ebcdictolower) #define uprv_fabs U_ICU_ENTRY_POINT_RENAME(uprv_fabs) @@ -1412,6 +1402,7 @@ #define uprv_getUTCtime U_ICU_ENTRY_POINT_RENAME(uprv_getUTCtime) #define uprv_int32Comparator U_ICU_ENTRY_POINT_RENAME(uprv_int32Comparator) #define uprv_isASCIILetter U_ICU_ENTRY_POINT_RENAME(uprv_isASCIILetter) +#define uprv_isEbcdicAtSign U_ICU_ENTRY_POINT_RENAME(uprv_isEbcdicAtSign) #define uprv_isInfinite U_ICU_ENTRY_POINT_RENAME(uprv_isInfinite) #define uprv_isInvariantString U_ICU_ENTRY_POINT_RENAME(uprv_isInvariantString) #define uprv_isInvariantUString U_ICU_ENTRY_POINT_RENAME(uprv_isInvariantUString) @@ -1579,6 +1570,7 @@ #define ures_getUTF8String U_ICU_ENTRY_POINT_RENAME(ures_getUTF8String) #define ures_getUTF8StringByIndex U_ICU_ENTRY_POINT_RENAME(ures_getUTF8StringByIndex) #define ures_getUTF8StringByKey U_ICU_ENTRY_POINT_RENAME(ures_getUTF8StringByKey) +#define ures_getValueWithFallback U_ICU_ENTRY_POINT_RENAME(ures_getValueWithFallback) #define ures_getVersion U_ICU_ENTRY_POINT_RENAME(ures_getVersion) #define ures_getVersionByKey U_ICU_ENTRY_POINT_RENAME(ures_getVersionByKey) #define ures_getVersionNumber U_ICU_ENTRY_POINT_RENAME(ures_getVersionNumber) diff --git a/deps/icu-small/source/common/unicode/usetiter.h b/deps/icu-small/source/common/unicode/usetiter.h index 057adbc04f5f05..f3f470f95aa5f5 100644 --- a/deps/icu-small/source/common/unicode/usetiter.h +++ b/deps/icu-small/source/common/unicode/usetiter.h @@ -10,6 +10,9 @@ #define USETITER_H #include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + #include "unicode/uobject.h" #include "unicode/unistr.h" @@ -317,4 +320,6 @@ inline UChar32 UnicodeSetIterator::getCodepointEnd() const { U_NAMESPACE_END +#endif /* U_SHOW_CPLUSPLUS_API */ + #endif diff --git a/deps/icu-small/source/common/unicode/utext.h b/deps/icu-small/source/common/unicode/utext.h index ff78784c61ec54..6f1e3409d8fdeb 100644 --- a/deps/icu-small/source/common/unicode/utext.h +++ b/deps/icu-small/source/common/unicode/utext.h @@ -766,12 +766,14 @@ utext_extract(UText *ut, * * @stable ICU 3.8 */ -#define UTEXT_SETNATIVEINDEX(ut, ix) \ - { int64_t __offset = (ix) - (ut)->chunkNativeStart; \ - if (__offset>=0 && __offset<(int64_t)(ut)->nativeIndexingLimit && (ut)->chunkContents[__offset]<0xdc00) { \ - (ut)->chunkOffset=(int32_t)__offset; \ - } else { \ - utext_setNativeIndex((ut), (ix)); } } +#define UTEXT_SETNATIVEINDEX(ut, ix) UPRV_BLOCK_MACRO_BEGIN { \ + int64_t __offset = (ix) - (ut)->chunkNativeStart; \ + if (__offset>=0 && __offset<(int64_t)(ut)->nativeIndexingLimit && (ut)->chunkContents[__offset]<0xdc00) { \ + (ut)->chunkOffset=(int32_t)__offset; \ + } else { \ + utext_setNativeIndex((ut), (ix)); \ + } \ +} UPRV_BLOCK_MACRO_END diff --git a/deps/icu-small/source/common/unicode/utf16.h b/deps/icu-small/source/common/unicode/utf16.h index 0908b4f00e9bf1..3315214ae69d86 100644 --- a/deps/icu-small/source/common/unicode/utf16.h +++ b/deps/icu-small/source/common/unicode/utf16.h @@ -163,7 +163,7 @@ * @see U16_GET * @stable ICU 2.4 */ -#define U16_GET_UNSAFE(s, i, c) { \ +#define U16_GET_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[i]; \ if(U16_IS_SURROGATE(c)) { \ if(U16_IS_SURROGATE_LEAD(c)) { \ @@ -172,7 +172,7 @@ (c)=U16_GET_SUPPLEMENTARY((s)[(i)-1], (c)); \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Get a code point from a string at a random-access offset, @@ -197,7 +197,7 @@ * @see U16_GET_UNSAFE * @stable ICU 2.4 */ -#define U16_GET(s, start, i, length, c) { \ +#define U16_GET(s, start, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[i]; \ if(U16_IS_SURROGATE(c)) { \ uint16_t __c2; \ @@ -211,7 +211,7 @@ } \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Get a code point from a string at a random-access offset, @@ -236,7 +236,7 @@ * @see U16_GET_UNSAFE * @stable ICU 60 */ -#define U16_GET_OR_FFFD(s, start, i, length, c) { \ +#define U16_GET_OR_FFFD(s, start, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[i]; \ if(U16_IS_SURROGATE(c)) { \ uint16_t __c2; \ @@ -254,7 +254,7 @@ } \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /* definitions with forward iteration --------------------------------------- */ @@ -277,12 +277,12 @@ * @see U16_NEXT * @stable ICU 2.4 */ -#define U16_NEXT_UNSAFE(s, i, c) { \ +#define U16_NEXT_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if(U16_IS_LEAD(c)) { \ (c)=U16_GET_SUPPLEMENTARY((c), (s)[(i)++]); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Get a code point from a string at a code point boundary offset, @@ -305,7 +305,7 @@ * @see U16_NEXT_UNSAFE * @stable ICU 2.4 */ -#define U16_NEXT(s, i, length, c) { \ +#define U16_NEXT(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if(U16_IS_LEAD(c)) { \ uint16_t __c2; \ @@ -314,7 +314,7 @@ (c)=U16_GET_SUPPLEMENTARY((c), __c2); \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Get a code point from a string at a code point boundary offset, @@ -337,7 +337,7 @@ * @see U16_NEXT_UNSAFE * @stable ICU 60 */ -#define U16_NEXT_OR_FFFD(s, i, length, c) { \ +#define U16_NEXT_OR_FFFD(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if(U16_IS_SURROGATE(c)) { \ uint16_t __c2; \ @@ -348,7 +348,7 @@ (c)=0xfffd; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Append a code point to a string, overwriting 1 or 2 code units. @@ -363,14 +363,14 @@ * @see U16_APPEND * @stable ICU 2.4 */ -#define U16_APPEND_UNSAFE(s, i, c) { \ +#define U16_APPEND_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c)<=0xffff) { \ (s)[(i)++]=(uint16_t)(c); \ } else { \ (s)[(i)++]=(uint16_t)(((c)>>10)+0xd7c0); \ (s)[(i)++]=(uint16_t)(((c)&0x3ff)|0xdc00); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Append a code point to a string, overwriting 1 or 2 code units. @@ -389,7 +389,7 @@ * @see U16_APPEND_UNSAFE * @stable ICU 2.4 */ -#define U16_APPEND(s, i, capacity, c, isError) { \ +#define U16_APPEND(s, i, capacity, c, isError) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c)<=0xffff) { \ (s)[(i)++]=(uint16_t)(c); \ } else if((uint32_t)(c)<=0x10ffff && (i)+1<(capacity)) { \ @@ -398,7 +398,7 @@ } else /* c>0x10ffff or not enough space */ { \ (isError)=TRUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the next. @@ -410,11 +410,11 @@ * @see U16_FWD_1 * @stable ICU 2.4 */ -#define U16_FWD_1_UNSAFE(s, i) { \ +#define U16_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U16_IS_LEAD((s)[(i)++])) { \ ++(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the next. @@ -429,11 +429,11 @@ * @see U16_FWD_1_UNSAFE * @stable ICU 2.4 */ -#define U16_FWD_1(s, i, length) { \ +#define U16_FWD_1(s, i, length) UPRV_BLOCK_MACRO_BEGIN { \ if(U16_IS_LEAD((s)[(i)++]) && (i)!=(length) && U16_IS_TRAIL((s)[i])) { \ ++(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the n-th next one, @@ -447,13 +447,13 @@ * @see U16_FWD_N * @stable ICU 2.4 */ -#define U16_FWD_N_UNSAFE(s, i, n) { \ +#define U16_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ U16_FWD_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the n-th next one, @@ -470,13 +470,13 @@ * @see U16_FWD_N_UNSAFE * @stable ICU 2.4 */ -#define U16_FWD_N(s, i, length, n) { \ +#define U16_FWD_N(s, i, length, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0 && ((i)<(length) || ((length)<0 && (s)[i]!=0))) { \ U16_FWD_1(s, i, length); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary @@ -491,11 +491,11 @@ * @see U16_SET_CP_START * @stable ICU 2.4 */ -#define U16_SET_CP_START_UNSAFE(s, i) { \ +#define U16_SET_CP_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U16_IS_TRAIL((s)[i])) { \ --(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary @@ -511,11 +511,11 @@ * @see U16_SET_CP_START_UNSAFE * @stable ICU 2.4 */ -#define U16_SET_CP_START(s, start, i) { \ +#define U16_SET_CP_START(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U16_IS_TRAIL((s)[i]) && (i)>(start) && U16_IS_LEAD((s)[(i)-1])) { \ --(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /* definitions with backward iteration -------------------------------------- */ @@ -539,12 +539,12 @@ * @see U16_PREV * @stable ICU 2.4 */ -#define U16_PREV_UNSAFE(s, i, c) { \ +#define U16_PREV_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if(U16_IS_TRAIL(c)) { \ (c)=U16_GET_SUPPLEMENTARY((s)[--(i)], (c)); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one @@ -566,7 +566,7 @@ * @see U16_PREV_UNSAFE * @stable ICU 2.4 */ -#define U16_PREV(s, start, i, c) { \ +#define U16_PREV(s, start, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if(U16_IS_TRAIL(c)) { \ uint16_t __c2; \ @@ -575,7 +575,7 @@ (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one @@ -597,7 +597,7 @@ * @see U16_PREV_UNSAFE * @stable ICU 60 */ -#define U16_PREV_OR_FFFD(s, start, i, c) { \ +#define U16_PREV_OR_FFFD(s, start, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if(U16_IS_SURROGATE(c)) { \ uint16_t __c2; \ @@ -608,7 +608,7 @@ (c)=0xfffd; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one. @@ -621,11 +621,11 @@ * @see U16_BACK_1 * @stable ICU 2.4 */ -#define U16_BACK_1_UNSAFE(s, i) { \ +#define U16_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U16_IS_TRAIL((s)[--(i)])) { \ --(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one. @@ -639,11 +639,11 @@ * @see U16_BACK_1_UNSAFE * @stable ICU 2.4 */ -#define U16_BACK_1(s, start, i) { \ +#define U16_BACK_1(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U16_IS_TRAIL((s)[--(i)]) && (i)>(start) && U16_IS_LEAD((s)[(i)-1])) { \ --(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the n-th one before it, @@ -658,13 +658,13 @@ * @see U16_BACK_N * @stable ICU 2.4 */ -#define U16_BACK_N_UNSAFE(s, i, n) { \ +#define U16_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ U16_BACK_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the n-th one before it, @@ -680,13 +680,13 @@ * @see U16_BACK_N_UNSAFE * @stable ICU 2.4 */ -#define U16_BACK_N(s, start, i, n) { \ +#define U16_BACK_N(s, start, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0 && (i)>(start)) { \ U16_BACK_1(s, start, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary after a code point. @@ -701,11 +701,11 @@ * @see U16_SET_CP_LIMIT * @stable ICU 2.4 */ -#define U16_SET_CP_LIMIT_UNSAFE(s, i) { \ +#define U16_SET_CP_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U16_IS_LEAD((s)[(i)-1])) { \ ++(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary after a code point. @@ -724,10 +724,10 @@ * @see U16_SET_CP_LIMIT_UNSAFE * @stable ICU 2.4 */ -#define U16_SET_CP_LIMIT(s, start, i, length) { \ +#define U16_SET_CP_LIMIT(s, start, i, length) UPRV_BLOCK_MACRO_BEGIN { \ if((start)<(i) && ((i)<(length) || (length)<0) && U16_IS_LEAD((s)[(i)-1]) && U16_IS_TRAIL((s)[i])) { \ ++(i); \ } \ -} +} UPRV_BLOCK_MACRO_END #endif diff --git a/deps/icu-small/source/common/unicode/utf8.h b/deps/icu-small/source/common/unicode/utf8.h index 41155f119bbb86..bb001303747efe 100644 --- a/deps/icu-small/source/common/unicode/utf8.h +++ b/deps/icu-small/source/common/unicode/utf8.h @@ -229,11 +229,11 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_GET * @stable ICU 2.4 */ -#define U8_GET_UNSAFE(s, i, c) { \ +#define U8_GET_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ int32_t _u8_get_unsafe_index=(int32_t)(i); \ U8_SET_CP_START_UNSAFE(s, _u8_get_unsafe_index); \ U8_NEXT_UNSAFE(s, _u8_get_unsafe_index, c); \ -} +} UPRV_BLOCK_MACRO_END /** * Get a code point from a string at a random-access offset, @@ -256,11 +256,11 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_GET_UNSAFE * @stable ICU 2.4 */ -#define U8_GET(s, start, i, length, c) { \ +#define U8_GET(s, start, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ int32_t _u8_get_index=(i); \ U8_SET_CP_START(s, start, _u8_get_index); \ U8_NEXT(s, _u8_get_index, length, c); \ -} +} UPRV_BLOCK_MACRO_END /** * Get a code point from a string at a random-access offset, @@ -287,11 +287,11 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_GET * @stable ICU 51 */ -#define U8_GET_OR_FFFD(s, start, i, length, c) { \ +#define U8_GET_OR_FFFD(s, start, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ int32_t _u8_get_index=(i); \ U8_SET_CP_START(s, start, _u8_get_index); \ U8_NEXT_OR_FFFD(s, _u8_get_index, length, c); \ -} +} UPRV_BLOCK_MACRO_END /* definitions with forward iteration --------------------------------------- */ @@ -312,7 +312,7 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_NEXT * @stable ICU 2.4 */ -#define U8_NEXT_UNSAFE(s, i, c) { \ +#define U8_NEXT_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(uint8_t)(s)[(i)++]; \ if(!U8_IS_SINGLE(c)) { \ if((c)<0xe0) { \ @@ -326,7 +326,7 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); (i)+=3; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Get a code point from a string at a code point boundary offset, @@ -377,7 +377,7 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); #define U8_NEXT_OR_FFFD(s, i, length, c) U8_INTERNAL_NEXT_OR_SUB(s, i, length, c, 0xfffd) /** @internal */ -#define U8_INTERNAL_NEXT_OR_SUB(s, i, length, c, sub) { \ +#define U8_INTERNAL_NEXT_OR_SUB(s, i, length, c, sub) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(uint8_t)(s)[(i)++]; \ if(!U8_IS_SINGLE(c)) { \ uint8_t __t = 0; \ @@ -403,7 +403,7 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); (c)=(sub); /* ill-formed*/ \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Append a code point to a string, overwriting 1 to 4 bytes. @@ -418,7 +418,7 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_APPEND * @stable ICU 2.4 */ -#define U8_APPEND_UNSAFE(s, i, c) { \ +#define U8_APPEND_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ uint32_t __uc=(c); \ if(__uc<=0x7f) { \ (s)[(i)++]=(uint8_t)__uc; \ @@ -436,7 +436,7 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); } \ (s)[(i)++]=(uint8_t)((__uc&0x3f)|0x80); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Append a code point to a string, overwriting 1 to 4 bytes. @@ -455,7 +455,7 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_APPEND_UNSAFE * @stable ICU 2.4 */ -#define U8_APPEND(s, i, capacity, c, isError) { \ +#define U8_APPEND(s, i, capacity, c, isError) UPRV_BLOCK_MACRO_BEGIN { \ uint32_t __uc=(c); \ if(__uc<=0x7f) { \ (s)[(i)++]=(uint8_t)__uc; \ @@ -474,7 +474,7 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); } else { \ (isError)=TRUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the next. @@ -486,9 +486,9 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_FWD_1 * @stable ICU 2.4 */ -#define U8_FWD_1_UNSAFE(s, i) { \ +#define U8_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ (i)+=1+U8_COUNT_TRAIL_BYTES_UNSAFE((s)[i]); \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the next. @@ -503,7 +503,7 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_FWD_1_UNSAFE * @stable ICU 2.4 */ -#define U8_FWD_1(s, i, length) { \ +#define U8_FWD_1(s, i, length) UPRV_BLOCK_MACRO_BEGIN { \ uint8_t __b=(s)[(i)++]; \ if(U8_IS_LEAD(__b) && (i)!=(length)) { \ uint8_t __t1=(s)[i]; \ @@ -524,7 +524,7 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); } \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the n-th next one, @@ -538,13 +538,13 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_FWD_N * @stable ICU 2.4 */ -#define U8_FWD_N_UNSAFE(s, i, n) { \ +#define U8_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ U8_FWD_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Advance the string offset from one code point boundary to the n-th next one, @@ -561,13 +561,13 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_FWD_N_UNSAFE * @stable ICU 2.4 */ -#define U8_FWD_N(s, i, length, n) { \ +#define U8_FWD_N(s, i, length, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0 && ((i)<(length) || ((length)<0 && (s)[i]!=0))) { \ U8_FWD_1(s, i, length); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary @@ -582,9 +582,9 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_SET_CP_START * @stable ICU 2.4 */ -#define U8_SET_CP_START_UNSAFE(s, i) { \ +#define U8_SET_CP_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ while(U8_IS_TRAIL((s)[i])) { --(i); } \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary @@ -603,11 +603,11 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_TRUNCATE_IF_INCOMPLETE * @stable ICU 2.4 */ -#define U8_SET_CP_START(s, start, i) { \ +#define U8_SET_CP_START(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U8_IS_TRAIL((s)[(i)])) { \ (i)=utf8_back1SafeBody(s, start, (i)); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * If the string ends with a UTF-8 byte sequence that is valid so far @@ -635,7 +635,7 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_SET_CP_START * @stable ICU 61 */ -#define U8_TRUNCATE_IF_INCOMPLETE(s, start, length) \ +#define U8_TRUNCATE_IF_INCOMPLETE(s, start, length) UPRV_BLOCK_MACRO_BEGIN { \ if((length)>(start)) { \ uint8_t __b1=s[(length)-1]; \ if(U8_IS_SINGLE(__b1)) { \ @@ -656,7 +656,8 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); } \ } \ } \ - } + } \ +} UPRV_BLOCK_MACRO_END /* definitions with backward iteration -------------------------------------- */ @@ -679,7 +680,7 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_PREV * @stable ICU 2.4 */ -#define U8_PREV_UNSAFE(s, i, c) { \ +#define U8_PREV_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(uint8_t)(s)[--(i)]; \ if(U8_IS_TRAIL(c)) { \ uint8_t __b, __count=1, __shift=6; \ @@ -699,7 +700,7 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); } \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one @@ -721,12 +722,12 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_PREV_UNSAFE * @stable ICU 2.4 */ -#define U8_PREV(s, start, i, c) { \ +#define U8_PREV(s, start, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(uint8_t)(s)[--(i)]; \ if(!U8_IS_SINGLE(c)) { \ (c)=utf8_prevCharSafeBody((const uint8_t *)s, start, &(i), c, -1); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one @@ -752,12 +753,12 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_PREV * @stable ICU 51 */ -#define U8_PREV_OR_FFFD(s, start, i, c) { \ +#define U8_PREV_OR_FFFD(s, start, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(uint8_t)(s)[--(i)]; \ if(!U8_IS_SINGLE(c)) { \ (c)=utf8_prevCharSafeBody((const uint8_t *)s, start, &(i), c, -3); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one. @@ -770,9 +771,9 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_BACK_1 * @stable ICU 2.4 */ -#define U8_BACK_1_UNSAFE(s, i) { \ +#define U8_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ while(U8_IS_TRAIL((s)[--(i)])) {} \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the previous one. @@ -786,11 +787,11 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_BACK_1_UNSAFE * @stable ICU 2.4 */ -#define U8_BACK_1(s, start, i) { \ +#define U8_BACK_1(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \ if(U8_IS_TRAIL((s)[--(i)])) { \ (i)=utf8_back1SafeBody(s, start, (i)); \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the n-th one before it, @@ -805,13 +806,13 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_BACK_N * @stable ICU 2.4 */ -#define U8_BACK_N_UNSAFE(s, i, n) { \ +#define U8_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ U8_BACK_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Move the string offset from one code point boundary to the n-th one before it, @@ -827,13 +828,13 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_BACK_N_UNSAFE * @stable ICU 2.4 */ -#define U8_BACK_N(s, start, i, n) { \ +#define U8_BACK_N(s, start, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0 && (i)>(start)) { \ U8_BACK_1(s, start, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary after a code point. @@ -848,10 +849,10 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_SET_CP_LIMIT * @stable ICU 2.4 */ -#define U8_SET_CP_LIMIT_UNSAFE(s, i) { \ +#define U8_SET_CP_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ U8_BACK_1_UNSAFE(s, i); \ U8_FWD_1_UNSAFE(s, i); \ -} +} UPRV_BLOCK_MACRO_END /** * Adjust a random-access offset to a code point boundary after a code point. @@ -870,11 +871,11 @@ utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); * @see U8_SET_CP_LIMIT_UNSAFE * @stable ICU 2.4 */ -#define U8_SET_CP_LIMIT(s, start, i, length) { \ +#define U8_SET_CP_LIMIT(s, start, i, length) UPRV_BLOCK_MACRO_BEGIN { \ if((start)<(i) && ((i)<(length) || (length)<0)) { \ U8_BACK_1(s, start, i); \ U8_FWD_1(s, i, length); \ } \ -} +} UPRV_BLOCK_MACRO_END #endif diff --git a/deps/icu-small/source/common/unicode/utf_old.h b/deps/icu-small/source/common/unicode/utf_old.h index 55c17c01df6db3..b2428e6b31e282 100644 --- a/deps/icu-small/source/common/unicode/utf_old.h +++ b/deps/icu-small/source/common/unicode/utf_old.h @@ -19,9 +19,6 @@ /** * \file * \brief C API: Deprecated macros for Unicode string handling - */ - -/** * * The macros in utf_old.h are all deprecated and their use discouraged. * Some of the design principles behind the set of UTF macros @@ -139,12 +136,16 @@ * *


* - * @deprecated ICU 2.4. Use the macros in utf.h, utf16.h, utf8.h instead. + * Deprecated ICU 2.4. Use the macros in utf.h, utf16.h, utf8.h instead. */ #ifndef __UTF_OLD_H__ #define __UTF_OLD_H__ +#include "unicode/utf.h" +#include "unicode/utf8.h" +#include "unicode/utf16.h" + /** * \def U_HIDE_OBSOLETE_UTF_OLD_H * @@ -162,10 +163,6 @@ #if !defined(U_HIDE_DEPRECATED_API) && !U_HIDE_OBSOLETE_UTF_OLD_H -#include "unicode/utf.h" -#include "unicode/utf8.h" -#include "unicode/utf16.h" - /* Formerly utf.h, part 1 --------------------------------------------------- */ #ifdef U_USE_UTF_DEPRECATES @@ -365,21 +362,21 @@ U_CFUNC U_IMPORT const uint8_t utf8_countTrailBytes[]; /* U_IMPORT2? */ /*U_I #define UTF8_ARRAY_SIZE(size) ((5*(size))/2) /** @deprecated ICU 2.4. Renamed to U8_GET_UNSAFE, see utf_old.h. */ -#define UTF8_GET_CHAR_UNSAFE(s, i, c) { \ +#define UTF8_GET_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ int32_t _utf8_get_char_unsafe_index=(int32_t)(i); \ UTF8_SET_CHAR_START_UNSAFE(s, _utf8_get_char_unsafe_index); \ UTF8_NEXT_CHAR_UNSAFE(s, _utf8_get_char_unsafe_index, c); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U8_GET instead, see utf_old.h. */ -#define UTF8_GET_CHAR_SAFE(s, start, i, length, c, strict) { \ +#define UTF8_GET_CHAR_SAFE(s, start, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ int32_t _utf8_get_char_safe_index=(int32_t)(i); \ UTF8_SET_CHAR_START_SAFE(s, start, _utf8_get_char_safe_index); \ UTF8_NEXT_CHAR_SAFE(s, _utf8_get_char_safe_index, length, c, strict); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_NEXT_UNSAFE, see utf_old.h. */ -#define UTF8_NEXT_CHAR_UNSAFE(s, i, c) { \ +#define UTF8_NEXT_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if((uint8_t)((c)-0xc0)<0x35) { \ uint8_t __count=UTF8_COUNT_TRAIL_BYTES(c); \ @@ -396,10 +393,10 @@ U_CFUNC U_IMPORT const uint8_t utf8_countTrailBytes[]; /* U_IMPORT2? */ /*U_I break; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_APPEND_UNSAFE, see utf_old.h. */ -#define UTF8_APPEND_CHAR_UNSAFE(s, i, c) { \ +#define UTF8_APPEND_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c)<=0x7f) { \ (s)[(i)++]=(uint8_t)(c); \ } else { \ @@ -416,29 +413,29 @@ U_CFUNC U_IMPORT const uint8_t utf8_countTrailBytes[]; /* U_IMPORT2? */ /*U_I } \ (s)[(i)++]=(uint8_t)(((c)&0x3f)|0x80); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_FWD_1_UNSAFE, see utf_old.h. */ -#define UTF8_FWD_1_UNSAFE(s, i) { \ +#define UTF8_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ (i)+=1+UTF8_COUNT_TRAIL_BYTES((s)[i]); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_FWD_N_UNSAFE, see utf_old.h. */ -#define UTF8_FWD_N_UNSAFE(s, i, n) { \ +#define UTF8_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ UTF8_FWD_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_SET_CP_START_UNSAFE, see utf_old.h. */ -#define UTF8_SET_CHAR_START_UNSAFE(s, i) { \ +#define UTF8_SET_CHAR_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ while(UTF8_IS_TRAIL((s)[i])) { --(i); } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U8_NEXT instead, see utf_old.h. */ -#define UTF8_NEXT_CHAR_SAFE(s, i, length, c, strict) { \ +#define UTF8_NEXT_CHAR_SAFE(s, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if((c)>=0x80) { \ if(UTF8_IS_LEAD(c)) { \ @@ -447,16 +444,16 @@ U_CFUNC U_IMPORT const uint8_t utf8_countTrailBytes[]; /* U_IMPORT2? */ /*U_I (c)=UTF8_ERROR_VALUE_1; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U8_APPEND instead, see utf_old.h. */ -#define UTF8_APPEND_CHAR_SAFE(s, i, length, c) { \ +#define UTF8_APPEND_CHAR_SAFE(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c)<=0x7f) { \ (s)[(i)++]=(uint8_t)(c); \ } else { \ (i)=utf8_appendCharSafeBody(s, (int32_t)(i), (int32_t)(length), c, NULL); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_FWD_1, see utf_old.h. */ #define UTF8_FWD_1_SAFE(s, i, length) U8_FWD_1(s, i, length) @@ -468,7 +465,7 @@ U_CFUNC U_IMPORT const uint8_t utf8_countTrailBytes[]; /* U_IMPORT2? */ /*U_I #define UTF8_SET_CHAR_START_SAFE(s, start, i) U8_SET_CP_START(s, start, i) /** @deprecated ICU 2.4. Renamed to U8_PREV_UNSAFE, see utf_old.h. */ -#define UTF8_PREV_CHAR_UNSAFE(s, i, c) { \ +#define UTF8_PREV_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if(UTF8_IS_TRAIL(c)) { \ uint8_t __b, __count=1, __shift=6; \ @@ -488,30 +485,30 @@ U_CFUNC U_IMPORT const uint8_t utf8_countTrailBytes[]; /* U_IMPORT2? */ /*U_I } \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_BACK_1_UNSAFE, see utf_old.h. */ -#define UTF8_BACK_1_UNSAFE(s, i) { \ +#define UTF8_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ while(UTF8_IS_TRAIL((s)[--(i)])) {} \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_BACK_N_UNSAFE, see utf_old.h. */ -#define UTF8_BACK_N_UNSAFE(s, i, n) { \ +#define UTF8_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ UTF8_BACK_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_SET_CP_LIMIT_UNSAFE, see utf_old.h. */ -#define UTF8_SET_CHAR_LIMIT_UNSAFE(s, i) { \ +#define UTF8_SET_CHAR_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ UTF8_BACK_1_UNSAFE(s, i); \ UTF8_FWD_1_UNSAFE(s, i); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U8_PREV instead, see utf_old.h. */ -#define UTF8_PREV_CHAR_SAFE(s, start, i, c, strict) { \ +#define UTF8_PREV_CHAR_SAFE(s, start, i, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if((c)>=0x80) { \ if((c)<=0xbf) { \ @@ -520,7 +517,7 @@ U_CFUNC U_IMPORT const uint8_t utf8_countTrailBytes[]; /* U_IMPORT2? */ /*U_I (c)=UTF8_ERROR_VALUE_1; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U8_BACK_1, see utf_old.h. */ #define UTF8_BACK_1_SAFE(s, start, i) U8_BACK_1(s, start, i) @@ -593,7 +590,7 @@ U_CFUNC U_IMPORT const uint8_t utf8_countTrailBytes[]; /* U_IMPORT2? */ /*U_I * UTF16_PREV_CHAR[_UNSAFE]() is more efficient for that. * @deprecated ICU 2.4. Renamed to U16_GET_UNSAFE, see utf_old.h. */ -#define UTF16_GET_CHAR_UNSAFE(s, i, c) { \ +#define UTF16_GET_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[i]; \ if(UTF_IS_SURROGATE(c)) { \ if(UTF_IS_SURROGATE_FIRST(c)) { \ @@ -602,10 +599,10 @@ U_CFUNC U_IMPORT const uint8_t utf8_countTrailBytes[]; /* U_IMPORT2? */ /*U_I (c)=UTF16_GET_PAIR_VALUE((s)[(i)-1], (c)); \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U16_GET instead, see utf_old.h. */ -#define UTF16_GET_CHAR_SAFE(s, start, i, length, c, strict) { \ +#define UTF16_GET_CHAR_SAFE(s, start, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[i]; \ if(UTF_IS_SURROGATE(c)) { \ uint16_t __c2; \ @@ -629,51 +626,51 @@ U_CFUNC U_IMPORT const uint8_t utf8_countTrailBytes[]; /* U_IMPORT2? */ /*U_I } else if((strict) && !UTF_IS_UNICODE_CHAR(c)) { \ (c)=UTF_ERROR_VALUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_NEXT_UNSAFE, see utf_old.h. */ -#define UTF16_NEXT_CHAR_UNSAFE(s, i, c) { \ +#define UTF16_NEXT_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if(UTF_IS_FIRST_SURROGATE(c)) { \ (c)=UTF16_GET_PAIR_VALUE((c), (s)[(i)++]); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_APPEND_UNSAFE, see utf_old.h. */ -#define UTF16_APPEND_CHAR_UNSAFE(s, i, c) { \ +#define UTF16_APPEND_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c)<=0xffff) { \ (s)[(i)++]=(uint16_t)(c); \ } else { \ (s)[(i)++]=(uint16_t)(((c)>>10)+0xd7c0); \ (s)[(i)++]=(uint16_t)(((c)&0x3ff)|0xdc00); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_FWD_1_UNSAFE, see utf_old.h. */ -#define UTF16_FWD_1_UNSAFE(s, i) { \ +#define UTF16_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(UTF_IS_FIRST_SURROGATE((s)[(i)++])) { \ ++(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_FWD_N_UNSAFE, see utf_old.h. */ -#define UTF16_FWD_N_UNSAFE(s, i, n) { \ +#define UTF16_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ UTF16_FWD_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_SET_CP_START_UNSAFE, see utf_old.h. */ -#define UTF16_SET_CHAR_START_UNSAFE(s, i) { \ +#define UTF16_SET_CHAR_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(UTF_IS_SECOND_SURROGATE((s)[i])) { \ --(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U16_NEXT instead, see utf_old.h. */ -#define UTF16_NEXT_CHAR_SAFE(s, i, length, c, strict) { \ +#define UTF16_NEXT_CHAR_SAFE(s, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if(UTF_IS_FIRST_SURROGATE(c)) { \ uint16_t __c2; \ @@ -689,10 +686,10 @@ U_CFUNC U_IMPORT const uint8_t utf8_countTrailBytes[]; /* U_IMPORT2? */ /*U_I /* unmatched second surrogate or other non-character */ \ (c)=UTF_ERROR_VALUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U16_APPEND instead, see utf_old.h. */ -#define UTF16_APPEND_CHAR_SAFE(s, i, length, c) { \ +#define UTF16_APPEND_CHAR_SAFE(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c)<=0xffff) { \ (s)[(i)++]=(uint16_t)(c); \ } else if((uint32_t)(c)<=0x10ffff) { \ @@ -705,7 +702,7 @@ U_CFUNC U_IMPORT const uint8_t utf8_countTrailBytes[]; /* U_IMPORT2? */ /*U_I } else /* c>0x10ffff, write error value */ { \ (s)[(i)++]=UTF_ERROR_VALUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_FWD_1, see utf_old.h. */ #define UTF16_FWD_1_SAFE(s, i, length) U16_FWD_1(s, i, length) @@ -717,38 +714,38 @@ U_CFUNC U_IMPORT const uint8_t utf8_countTrailBytes[]; /* U_IMPORT2? */ /*U_I #define UTF16_SET_CHAR_START_SAFE(s, start, i) U16_SET_CP_START(s, start, i) /** @deprecated ICU 2.4. Renamed to U16_PREV_UNSAFE, see utf_old.h. */ -#define UTF16_PREV_CHAR_UNSAFE(s, i, c) { \ +#define UTF16_PREV_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if(UTF_IS_SECOND_SURROGATE(c)) { \ (c)=UTF16_GET_PAIR_VALUE((s)[--(i)], (c)); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_BACK_1_UNSAFE, see utf_old.h. */ -#define UTF16_BACK_1_UNSAFE(s, i) { \ +#define UTF16_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(UTF_IS_SECOND_SURROGATE((s)[--(i)])) { \ --(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_BACK_N_UNSAFE, see utf_old.h. */ -#define UTF16_BACK_N_UNSAFE(s, i, n) { \ +#define UTF16_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __N=(n); \ while(__N>0) { \ UTF16_BACK_1_UNSAFE(s, i); \ --__N; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_SET_CP_LIMIT_UNSAFE, see utf_old.h. */ -#define UTF16_SET_CHAR_LIMIT_UNSAFE(s, i) { \ +#define UTF16_SET_CHAR_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ if(UTF_IS_FIRST_SURROGATE((s)[(i)-1])) { \ ++(i); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Use U16_PREV instead, see utf_old.h. */ -#define UTF16_PREV_CHAR_SAFE(s, start, i, c, strict) { \ +#define UTF16_PREV_CHAR_SAFE(s, start, i, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if(UTF_IS_SECOND_SURROGATE(c)) { \ uint16_t __c2; \ @@ -764,7 +761,7 @@ U_CFUNC U_IMPORT const uint8_t utf8_countTrailBytes[]; /* U_IMPORT2? */ /*U_I /* unmatched first surrogate or other non-character */ \ (c)=UTF_ERROR_VALUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Renamed to U16_BACK_1, see utf_old.h. */ #define UTF16_BACK_1_SAFE(s, start, i) U16_BACK_1(s, start, i) @@ -830,122 +827,122 @@ U_CFUNC U_IMPORT const uint8_t utf8_countTrailBytes[]; /* U_IMPORT2? */ /*U_I #define UTF32_ARRAY_SIZE(size) (size) /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_GET_CHAR_UNSAFE(s, i, c) { \ +#define UTF32_GET_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[i]; \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_GET_CHAR_SAFE(s, start, i, length, c, strict) { \ +#define UTF32_GET_CHAR_SAFE(s, start, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[i]; \ if(!UTF32_IS_SAFE(c, strict)) { \ (c)=UTF_ERROR_VALUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /* definitions with forward iteration --------------------------------------- */ /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_NEXT_CHAR_UNSAFE(s, i, c) { \ +#define UTF32_NEXT_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_APPEND_CHAR_UNSAFE(s, i, c) { \ +#define UTF32_APPEND_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (s)[(i)++]=(c); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_FWD_1_UNSAFE(s, i) { \ +#define UTF32_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ ++(i); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_FWD_N_UNSAFE(s, i, n) { \ +#define UTF32_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ (i)+=(n); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_SET_CHAR_START_UNSAFE(s, i) { \ -} +#define UTF32_SET_CHAR_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_NEXT_CHAR_SAFE(s, i, length, c, strict) { \ +#define UTF32_NEXT_CHAR_SAFE(s, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[(i)++]; \ if(!UTF32_IS_SAFE(c, strict)) { \ (c)=UTF_ERROR_VALUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_APPEND_CHAR_SAFE(s, i, length, c) { \ +#define UTF32_APPEND_CHAR_SAFE(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c)<=0x10ffff) { \ (s)[(i)++]=(c); \ } else /* c>0x10ffff, write 0xfffd */ { \ (s)[(i)++]=0xfffd; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_FWD_1_SAFE(s, i, length) { \ +#define UTF32_FWD_1_SAFE(s, i, length) UPRV_BLOCK_MACRO_BEGIN { \ ++(i); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_FWD_N_SAFE(s, i, length, n) { \ +#define UTF32_FWD_N_SAFE(s, i, length, n) UPRV_BLOCK_MACRO_BEGIN { \ if(((i)+=(n))>(length)) { \ (i)=(length); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_SET_CHAR_START_SAFE(s, start, i) { \ -} +#define UTF32_SET_CHAR_START_SAFE(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \ +} UPRV_BLOCK_MACRO_END /* definitions with backward iteration -------------------------------------- */ /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_PREV_CHAR_UNSAFE(s, i, c) { \ +#define UTF32_PREV_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_BACK_1_UNSAFE(s, i) { \ +#define UTF32_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ --(i); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_BACK_N_UNSAFE(s, i, n) { \ +#define UTF32_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ (i)-=(n); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_SET_CHAR_LIMIT_UNSAFE(s, i) { \ -} +#define UTF32_SET_CHAR_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_PREV_CHAR_SAFE(s, start, i, c, strict) { \ +#define UTF32_PREV_CHAR_SAFE(s, start, i, c, strict) UPRV_BLOCK_MACRO_BEGIN { \ (c)=(s)[--(i)]; \ if(!UTF32_IS_SAFE(c, strict)) { \ (c)=UTF_ERROR_VALUE; \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_BACK_1_SAFE(s, start, i) { \ +#define UTF32_BACK_1_SAFE(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \ --(i); \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_BACK_N_SAFE(s, start, i, n) { \ +#define UTF32_BACK_N_SAFE(s, start, i, n) UPRV_BLOCK_MACRO_BEGIN { \ (i)-=(n); \ if((i)<(start)) { \ (i)=(start); \ } \ -} +} UPRV_BLOCK_MACRO_END /** @deprecated ICU 2.4. Obsolete, see utf_old.h. */ -#define UTF32_SET_CHAR_LIMIT_SAFE(s, i, length) { \ -} +#define UTF32_SET_CHAR_LIMIT_SAFE(s, i, length) UPRV_BLOCK_MACRO_BEGIN { \ +} UPRV_BLOCK_MACRO_END /* Formerly utf.h, part 2 --------------------------------------------------- */ diff --git a/deps/icu-small/source/common/unicode/utrace.h b/deps/icu-small/source/common/unicode/utrace.h index bf6fd036f06c41..0af050756fc38a 100644 --- a/deps/icu-small/source/common/unicode/utrace.h +++ b/deps/icu-small/source/common/unicode/utrace.h @@ -66,6 +66,7 @@ typedef enum UTraceFunctionNumber { UTRACE_FUNCTION_START=0, UTRACE_U_INIT=UTRACE_FUNCTION_START, UTRACE_U_CLEANUP, + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal collation trace location. @@ -83,6 +84,7 @@ typedef enum UTraceFunctionNumber { UTRACE_UCNV_FLUSH_CACHE, UTRACE_UCNV_LOAD, UTRACE_UCNV_UNLOAD, + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal collation trace location. @@ -101,13 +103,80 @@ typedef enum UTraceFunctionNumber { UTRACE_UCOL_STRCOLLITER, UTRACE_UCOL_OPEN_FROM_SHORT_STRING, UTRACE_UCOL_STRCOLLUTF8, /**< @stable ICU 50 */ + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal collation trace location. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - UTRACE_COLLATION_LIMIT + UTRACE_COLLATION_LIMIT, #endif // U_HIDE_DEPRECATED_API + +#ifndef U_HIDE_DRAFT_API + + /** + * The lowest resource/data location. + * @draft ICU 65 + */ + UTRACE_UDATA_START=0x3000, + + /** + * Indicates that a value was read from a resource bundle. Provides three + * C-style strings to UTraceData: type, file name, and resource path. The + * possible types are: + * + * - "string" (a string value was accessed) + * - "binary" (a binary value was accessed) + * - "intvector" (a integer vector value was accessed) + * - "int" (a signed integer value was accessed) + * - "uint" (a unsigned integer value was accessed) + * - "get" (a path was loaded, but the value was not accessed) + * - "getalias" (a path was loaded, and an alias was resolved) + * + * @draft ICU 65 + */ + UTRACE_UDATA_RESOURCE=UTRACE_UDATA_START, + + /** + * Indicates that a resource bundle was opened. + * + * Provides one C-style string to UTraceData: file name. + * @draft ICU 65 + */ + UTRACE_UDATA_BUNDLE, + + /** + * Indicates that a data file was opened, but not *.res files. + * + * Provides one C-style string to UTraceData: file name. + * + * @draft ICU 65 + */ + UTRACE_UDATA_DATA_FILE, + + /** + * Indicates that a *.res file was opened. + * + * This differs from UTRACE_UDATA_BUNDLE because a res file is typically + * opened only once per application runtime, but the bundle corresponding + * to that res file may be opened many times. + * + * Provides one C-style string to UTraceData: file name. + * + * @draft ICU 65 + */ + UTRACE_UDATA_RES_FILE, + +#endif // U_HIDE_DRAFT_API + +#ifndef U_HIDE_INTERNAL_API + /** + * One more than the highest normal resource/data trace location. + * @internal The numeric value may change over time, see ICU ticket #12420. + */ + UTRACE_RES_DATA_LIMIT, +#endif // U_HIDE_INTERNAL_API + } UTraceFunctionNumber; /** diff --git a/deps/icu-small/source/common/unicode/utypes.h b/deps/icu-small/source/common/unicode/utypes.h index 49eb12cd40022c..c98de9e6fc3dad 100644 --- a/deps/icu-small/source/common/unicode/utypes.h +++ b/deps/icu-small/source/common/unicode/utypes.h @@ -385,17 +385,31 @@ typedef double UDate; /*===========================================================================*/ /** - * Error code to replace exception handling, so that the code is compatible with all C++ compilers, - * and to use the same mechanism for C and C++. + * Standard ICU4C error code type, a substitute for exceptions. + * + * Initialize the UErrorCode with U_ZERO_ERROR, and check for success or + * failure using U_SUCCESS() or U_FAILURE(): + * + * UErrorCode errorCode = U_ZERO_ERROR; + * // call ICU API that needs an error code parameter. + * if (U_FAILURE(errorCode)) { + * // An error occurred. Handle it here. + * } + * + * C++ code should use icu::ErrorCode, available in unicode/errorcode.h, or a + * suitable subclass. + * + * For more information, see: + * http://icu-project.org/userguide/conventions + * + * Note: By convention, ICU functions that take a reference (C++) or a pointer + * (C) to a UErrorCode first test: + * + * if (U_FAILURE(errorCode)) { return immediately; } * - * \par - * ICU functions that take a reference (C++) or a pointer (C) to a UErrorCode - * first test if(U_FAILURE(errorCode)) { return immediately; } * so that in a chain of such functions the first one that sets an error code * causes the following ones to not perform any operations. * - * \par - * Error codes should be tested using U_FAILURE() and U_SUCCESS(). * @stable ICU 2.0 */ typedef enum UErrorCode { diff --git a/deps/icu-small/source/common/unicode/uvernum.h b/deps/icu-small/source/common/unicode/uvernum.h index 7c114be2cc87f1..0923c1d9189d0f 100644 --- a/deps/icu-small/source/common/unicode/uvernum.h +++ b/deps/icu-small/source/common/unicode/uvernum.h @@ -60,13 +60,13 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION_MAJOR_NUM 64 +#define U_ICU_VERSION_MAJOR_NUM 65 /** The current ICU minor version as an integer. * This value will change in the subsequent releases of ICU * @stable ICU 2.6 */ -#define U_ICU_VERSION_MINOR_NUM 2 +#define U_ICU_VERSION_MINOR_NUM 1 /** The current ICU patchlevel 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 _64 +#define U_ICU_VERSION_SUFFIX _65 /** * \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 "64.2" +#define U_ICU_VERSION "65.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 "64" +#define U_ICU_VERSION_SHORT "65" #ifndef U_HIDE_INTERNAL_API /** Data version in ICU4C. * @internal ICU 4.4 Internal Use Only **/ -#define U_ICU_DATA_VERSION "64.2" +#define U_ICU_DATA_VERSION "65.1" #endif /* U_HIDE_INTERNAL_API */ /*=========================================================================== diff --git a/deps/icu-small/source/common/unicode/uversion.h b/deps/icu-small/source/common/unicode/uversion.h index 3f0251d3994bcb..c8c7a374c820b2 100644 --- a/deps/icu-small/source/common/unicode/uversion.h +++ b/deps/icu-small/source/common/unicode/uversion.h @@ -62,26 +62,22 @@ typedef uint8_t UVersionInfo[U_MAX_VERSION_LENGTH]; /* C++ namespace if supported. Versioned unless versioning is disabled. */ /*===========================================================================*/ +/* Define C++ namespace symbols. */ +#ifdef __cplusplus + /** * \def U_NAMESPACE_BEGIN - * This is used to begin a declaration of a public ICU C++ API. - * When not compiling for C++, it does nothing. - * When compiling for C++, it begins an extern "C++" linkage block (to protect - * against cases in which an external client includes ICU header files inside - * an extern "C" linkage block). + * This is used to begin a declaration of a public ICU C++ API within + * versioned-ICU-namespace block. * - * It also begins a versioned-ICU-namespace block. * @stable ICU 2.4 */ /** * \def U_NAMESPACE_END * This is used to end a declaration of a public ICU C++ API. - * When not compiling for C++, it does nothing. - * When compiling for C++, it ends the extern "C++" block begun by - * U_NAMESPACE_BEGIN. + * It ends the versioned-ICU-namespace block begun by U_NAMESPACE_BEGIN. * - * It also ends the versioned-ICU-namespace block begun by U_NAMESPACE_BEGIN. * @stable ICU 2.4 */ @@ -89,9 +85,6 @@ typedef uint8_t UVersionInfo[U_MAX_VERSION_LENGTH]; * \def U_NAMESPACE_USE * This is used to specify that the rest of the code uses the * public ICU C++ API namespace. - * This is invoked by default; we recommend that you turn it off: - * See the "Recommended Build Options" section of the ICU4C readme - * (http://source.icu-project.org/repos/icu/icu/trunk/readme.html#RecBuild) * @stable ICU 2.4 */ @@ -105,8 +98,6 @@ typedef uint8_t UVersionInfo[U_MAX_VERSION_LENGTH]; * @stable ICU 2.4 */ -/* Define C++ namespace symbols. */ -#ifdef __cplusplus # if U_DISABLE_RENAMING # define U_ICU_NAMESPACE icu namespace U_ICU_NAMESPACE { } @@ -116,8 +107,8 @@ typedef uint8_t UVersionInfo[U_MAX_VERSION_LENGTH]; namespace icu = U_ICU_NAMESPACE; # endif -# define U_NAMESPACE_BEGIN extern "C++" { namespace U_ICU_NAMESPACE { -# define U_NAMESPACE_END } } +# define U_NAMESPACE_BEGIN namespace U_ICU_NAMESPACE { +# define U_NAMESPACE_END } # define U_NAMESPACE_USE using namespace U_ICU_NAMESPACE; # define U_NAMESPACE_QUALIFIER U_ICU_NAMESPACE:: @@ -133,12 +124,7 @@ typedef uint8_t UVersionInfo[U_MAX_VERSION_LENGTH]; # if U_USING_ICU_NAMESPACE U_NAMESPACE_USE # endif -#else -# define U_NAMESPACE_BEGIN -# define U_NAMESPACE_END -# define U_NAMESPACE_USE -# define U_NAMESPACE_QUALIFIER -#endif +#endif /* __cplusplus */ /*===========================================================================*/ /* General version helper functions. Definitions in putil.c */ diff --git a/deps/icu-small/source/common/unifiedcache.cpp b/deps/icu-small/source/common/unifiedcache.cpp index 641f4ec6594e12..f2dd916559588c 100644 --- a/deps/icu-small/source/common/unifiedcache.cpp +++ b/deps/icu-small/source/common/unifiedcache.cpp @@ -13,22 +13,15 @@ #include "unifiedcache.h" #include // For std::max() +#include -#include "mutex.h" #include "uassert.h" #include "uhash.h" #include "ucln_cmn.h" -#include "umutex.h" static icu::UnifiedCache *gCache = NULL; -static icu::UMutex *gCacheMutex() { - static icu::UMutex m = U_MUTEX_INITIALIZER; - return &m; -} -static icu::UConditionVar *gInProgressValueAddedCond() { - static icu::UConditionVar cv = U_CONDITION_INITIALIZER; - return &cv; -} +static std::mutex *gCacheMutex = nullptr; +static std::condition_variable *gInProgressValueAddedCond; static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER; static const int32_t MAX_EVICT_ITERATIONS = 10; @@ -39,10 +32,12 @@ static const int32_t DEFAULT_PERCENTAGE_OF_IN_USE = 100; U_CDECL_BEGIN static UBool U_CALLCONV unifiedcache_cleanup() { gCacheInitOnce.reset(); - if (gCache) { - delete gCache; - gCache = NULL; - } + delete gCache; + gCache = nullptr; + gCacheMutex->~mutex(); + gCacheMutex = nullptr; + gInProgressValueAddedCond->~condition_variable(); + gInProgressValueAddedCond = nullptr; return TRUE; } U_CDECL_END @@ -77,6 +72,8 @@ static void U_CALLCONV cacheInit(UErrorCode &status) { ucln_common_registerCleanup( UCLN_COMMON_UNIFIED_CACHE, unifiedcache_cleanup); + gCacheMutex = STATIC_NEW(std::mutex); + gInProgressValueAddedCond = STATIC_NEW(std::condition_variable); gCache = new UnifiedCache(status); if (gCache == NULL) { status = U_MEMORY_ALLOCATION_ERROR; @@ -138,28 +135,28 @@ void UnifiedCache::setEvictionPolicy( status = U_ILLEGAL_ARGUMENT_ERROR; return; } - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); fMaxUnused = count; fMaxPercentageOfInUse = percentageOfInUseItems; } int32_t UnifiedCache::unusedCount() const { - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); return uhash_count(fHashtable) - fNumValuesInUse; } int64_t UnifiedCache::autoEvictedCount() const { - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); return fAutoEvictedCount; } int32_t UnifiedCache::keyCount() const { - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); return uhash_count(fHashtable); } void UnifiedCache::flush() const { - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); // Use a loop in case cache items that are flushed held hard references to // other cache items making those additional cache items eligible for @@ -168,7 +165,7 @@ void UnifiedCache::flush() const { } void UnifiedCache::handleUnreferencedObject() const { - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); --fNumValuesInUse; _runEvictionSlice(); } @@ -187,7 +184,7 @@ void UnifiedCache::dump() { } void UnifiedCache::dumpContents() const { - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); _dumpContents(); } @@ -227,7 +224,7 @@ UnifiedCache::~UnifiedCache() { // Now all that should be left in the cache are entries that refer to // each other and entries with hard references from outside the cache. // Nothing we can do about these so proceed to wipe out the cache. - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); _flush(TRUE); } uhash_close(fHashtable); @@ -328,7 +325,7 @@ void UnifiedCache::_putIfAbsentAndGet( const CacheKeyBase &key, const SharedObject *&value, UErrorCode &status) const { - Mutex lock(gCacheMutex()); + std::lock_guard lock(*gCacheMutex); const UHashElement *element = uhash_find(fHashtable, &key); if (element != NULL && !_inProgress(element)) { _fetch(element, value, status); @@ -353,15 +350,15 @@ UBool UnifiedCache::_poll( UErrorCode &status) const { U_ASSERT(value == NULL); U_ASSERT(status == U_ZERO_ERROR); - Mutex lock(gCacheMutex()); + std::unique_lock lock(*gCacheMutex); const UHashElement *element = uhash_find(fHashtable, &key); // If the hash table contains an inProgress placeholder entry for this key, // this means that another thread is currently constructing the value object. // Loop, waiting for that construction to complete. while (element != NULL && _inProgress(element)) { - umtx_condWait(gInProgressValueAddedCond(), gCacheMutex()); - element = uhash_find(fHashtable, &key); + gInProgressValueAddedCond->wait(lock); + element = uhash_find(fHashtable, &key); } // If the hash table contains an entry for the key, @@ -433,7 +430,7 @@ void UnifiedCache::_put( // Tell waiting threads that we replace in-progress status with // an error. - umtx_condBroadcast(gInProgressValueAddedCond()); + gInProgressValueAddedCond->notify_all(); } void UnifiedCache::_fetch( diff --git a/deps/icu-small/source/common/uniset.cpp b/deps/icu-small/source/common/uniset.cpp index 1db382afe6f6ba..3807b837475948 100644 --- a/deps/icu-small/source/common/uniset.cpp +++ b/deps/icu-small/source/common/uniset.cpp @@ -278,11 +278,11 @@ UnicodeSet& UnicodeSet::copyFrom(const UnicodeSet& o, UBool asThawed) { * to support cloning in order to allow classes using * UnicodeMatchers, such as Transliterator, to implement cloning. */ -UnicodeFunctor* UnicodeSet::clone() const { +UnicodeSet* UnicodeSet::clone() const { return new UnicodeSet(*this); } -UnicodeFunctor *UnicodeSet::cloneAsThawed() const { +UnicodeSet *UnicodeSet::cloneAsThawed() const { return new UnicodeSet(*this, TRUE); } @@ -2172,7 +2172,7 @@ void UnicodeSet::setPattern(const char16_t *newPat, int32_t newPatLen) { // We can regenerate an equivalent pattern later when requested. } -UnicodeFunctor *UnicodeSet::freeze() { +UnicodeSet *UnicodeSet::freeze() { if(!isFrozen() && !isBogus()) { compact(); diff --git a/deps/icu-small/source/common/uniset_props.cpp b/deps/icu-small/source/common/uniset_props.cpp index 6f7918a91ab9ed..45d3dab9938b29 100644 --- a/deps/icu-small/source/common/uniset_props.cpp +++ b/deps/icu-small/source/common/uniset_props.cpp @@ -802,7 +802,10 @@ static UBool mungeCharName(char* dst, const char* src, int32_t dstCapacity) { // Property set API //---------------------------------------------------------------- -#define FAIL(ec) {ec=U_ILLEGAL_ARGUMENT_ERROR; return *this;} +#define FAIL(ec) UPRV_BLOCK_MACRO_BEGIN { \ + ec=U_ILLEGAL_ARGUMENT_ERROR; \ + return *this; \ +} UPRV_BLOCK_MACRO_END UnicodeSet& UnicodeSet::applyIntPropertyValue(UProperty prop, int32_t value, UErrorCode& ec) { diff --git a/deps/icu-small/source/common/unisetspan.cpp b/deps/icu-small/source/common/unisetspan.cpp index 0a8893472f958b..68e44d91ee7066 100644 --- a/deps/icu-small/source/common/unisetspan.cpp +++ b/deps/icu-small/source/common/unisetspan.cpp @@ -400,7 +400,7 @@ UnicodeSetStringSpan::UnicodeSetStringSpan(const UnicodeSetStringSpan &otherStri if(otherStringSpan.pSpanNotSet==&otherStringSpan.spanSet) { pSpanNotSet=&spanSet; } else { - pSpanNotSet=(UnicodeSet *)otherStringSpan.pSpanNotSet->clone(); + pSpanNotSet=otherStringSpan.pSpanNotSet->clone(); } // Allocate a block of meta data. @@ -436,7 +436,7 @@ void UnicodeSetStringSpan::addToSpanNotSet(UChar32 c) { if(spanSet.contains(c)) { return; // Nothing to do. } - UnicodeSet *newSet=(UnicodeSet *)spanSet.cloneAsThawed(); + UnicodeSet *newSet=spanSet.cloneAsThawed(); if(newSet==NULL) { return; // Out of memory. } else { diff --git a/deps/icu-small/source/common/unistr.cpp b/deps/icu-small/source/common/unistr.cpp index 31b0ed84bee07d..eeb0c3a679a5e9 100644 --- a/deps/icu-small/source/common/unistr.cpp +++ b/deps/icu-small/source/common/unistr.cpp @@ -332,7 +332,7 @@ Replaceable::clone() const { } // UnicodeString overrides clone() with a real implementation -Replaceable * +UnicodeString * UnicodeString::clone() const { return new UnicodeString(*this); } diff --git a/deps/icu-small/source/common/uresbund.cpp b/deps/icu-small/source/common/uresbund.cpp index c9f2c860da7c33..3a9b4340bb4a38 100644 --- a/deps/icu-small/source/common/uresbund.cpp +++ b/deps/icu-small/source/common/uresbund.cpp @@ -31,6 +31,7 @@ #include "ucln_cmn.h" #include "cmemory.h" #include "cstring.h" +#include "mutex.h" #include "uhash.h" #include "unicode/uenum.h" #include "uenumimp.h" @@ -38,6 +39,7 @@ #include "umutex.h" #include "putilimp.h" #include "uassert.h" +#include "uresdata.h" using namespace icu; @@ -47,12 +49,9 @@ TODO: This cache should probably be removed when the deprecated code is completely removed. */ static UHashtable *cache = NULL; -static icu::UInitOnce gCacheInitOnce; +static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER; -static UMutex *resbMutex() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static UMutex resbMutex; /* INTERNAL: hashes an entry */ static int32_t U_CALLCONV hashEntry(const UHashTok parm) { @@ -96,13 +95,12 @@ static UBool chopLocale(char *name) { * Internal function */ static void entryIncrease(UResourceDataEntry *entry) { - umtx_lock(resbMutex()); + Mutex lock(&resbMutex); entry->fCountExisting++; while(entry->fParent != NULL) { entry = entry->fParent; entry->fCountExisting++; } - umtx_unlock(resbMutex()); } /** @@ -184,9 +182,8 @@ static int32_t ures_flushCache() /*if shared data hasn't even been lazy evaluated yet * return 0 */ - umtx_lock(resbMutex()); + Mutex lock(&resbMutex); if (cache == NULL) { - umtx_unlock(resbMutex()); return 0; } @@ -218,7 +215,6 @@ static int32_t ures_flushCache() * got decremented by free_entry(). */ } while(deletedMore); - umtx_unlock(resbMutex()); return rbDeletedNum; } @@ -232,9 +228,8 @@ U_CAPI UBool U_EXPORT2 ures_dumpCacheContents(void) { const UHashElement *e; UResourceDataEntry *resB; - umtx_lock(resbMutex()); + Mutex lock(&resbMutex); if (cache == NULL) { - umtx_unlock(resbMutex()); fprintf(stderr,"%s:%d: RB Cache is NULL.\n", __FILE__, __LINE__); return FALSE; } @@ -253,9 +248,6 @@ U_CAPI UBool U_EXPORT2 ures_dumpCacheContents(void) { } fprintf(stderr,"%s:%d: RB Cache still contains %d items.\n", __FILE__, __LINE__, uhash_count(cache)); - - umtx_unlock(resbMutex()); - return cacheNotEmpty; } @@ -401,7 +393,8 @@ static UResourceDataEntry *init_entry(const char *localeID, const char *path, UE /* We'll try to get alias string from the bundle */ aliasres = res_getResource(&(r->fData), "%%ALIAS"); if (aliasres != RES_BOGUS) { - const UChar *alias = res_getString(&(r->fData), aliasres, &aliasLen); + // No tracing: called during initial data loading + const UChar *alias = res_getStringNoTrace(&(r->fData), aliasres, &aliasLen); if(alias != NULL && aliasLen > 0) { /* if there is actual alias - unload and load new data */ u_UCharsToChars(alias, aliasName, aliasLen+1); r->fAlias = init_entry(aliasName, path, status); @@ -542,7 +535,8 @@ loadParentsExceptRoot(UResourceDataEntry *&t1, Resource parentRes = res_getResource(&t1->fData, "%%Parent"); if (parentRes != RES_BOGUS) { // An explicit parent was found. int32_t parentLocaleLen = 0; - const UChar *parentLocaleName = res_getString(&(t1->fData), parentRes, &parentLocaleLen); + // No tracing: called during initial data loading + const UChar *parentLocaleName = res_getStringNoTrace(&(t1->fData), parentRes, &parentLocaleLen); if(parentLocaleName != NULL && 0 < parentLocaleLen && parentLocaleLen < nameCapacity) { u_UCharsToChars(parentLocaleName, name, parentLocaleLen + 1); if (uprv_strcmp(name, kRootLocaleName) == 0) { @@ -666,107 +660,105 @@ static UResourceDataEntry *entryOpen(const char* path, const char* localeID, } } - umtx_lock(resbMutex()); - { /* umtx_lock */ - /* We're going to skip all the locales that do not have any data */ - r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); + Mutex lock(&resbMutex); // Lock resbMutex until the end of this function. + + /* We're going to skip all the locales that do not have any data */ + r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); + + // If we failed due to out-of-memory, report the failure and exit early. + if (intStatus == U_MEMORY_ALLOCATION_ERROR) { + *status = intStatus; + goto finish; + } + + if(r != NULL) { /* if there is one real locale, we can look for parents. */ + t1 = r; + hasRealData = TRUE; + if ( usingUSRData ) { /* This code inserts user override data into the inheritance chain */ + UErrorCode usrStatus = U_ZERO_ERROR; + UResourceDataEntry *u1 = init_entry(t1->fName, usrDataPath, &usrStatus); + // If we failed due to out-of-memory, report the failure and exit early. + if (intStatus == U_MEMORY_ALLOCATION_ERROR) { + *status = intStatus; + goto finish; + } + if ( u1 != NULL ) { + if(u1->fBogus == U_ZERO_ERROR) { + u1->fParent = t1; + r = u1; + } else { + /* the USR override data wasn't found, set it to be deleted */ + u1->fCountExisting = 0; + } + } + } + if (hasChopped && !isRoot) { + if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) { + goto finish; + } + } + } + /* we could have reached this point without having any real data */ + /* if that is the case, we need to chain in the default locale */ + if(r==NULL && openType == URES_OPEN_LOCALE_DEFAULT_ROOT && !isDefault && !isRoot) { + /* insert default locale */ + uprv_strcpy(name, uloc_getDefault()); + r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); // If we failed due to out-of-memory, report the failure and exit early. if (intStatus == U_MEMORY_ALLOCATION_ERROR) { *status = intStatus; - goto finishUnlock; + goto finish; } - - if(r != NULL) { /* if there is one real locale, we can look for parents. */ + intStatus = U_USING_DEFAULT_WARNING; + if(r != NULL) { /* the default locale exists */ t1 = r; hasRealData = TRUE; - if ( usingUSRData ) { /* This code inserts user override data into the inheritance chain */ - UErrorCode usrStatus = U_ZERO_ERROR; - UResourceDataEntry *u1 = init_entry(t1->fName, usrDataPath, &usrStatus); - // If we failed due to out-of-memory, report the failure and exit early. - if (intStatus == U_MEMORY_ALLOCATION_ERROR) { - *status = intStatus; - goto finishUnlock; - } - if ( u1 != NULL ) { - if(u1->fBogus == U_ZERO_ERROR) { - u1->fParent = t1; - r = u1; - } else { - /* the USR override data wasn't found, set it to be deleted */ - u1->fCountExisting = 0; - } - } - } + isDefault = TRUE; + // TODO: Why not if (usingUSRData) { ... } like in the non-default-locale code path? if (hasChopped && !isRoot) { if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) { - goto finishUnlock; + goto finish; } } } + } - /* we could have reached this point without having any real data */ - /* if that is the case, we need to chain in the default locale */ - if(r==NULL && openType == URES_OPEN_LOCALE_DEFAULT_ROOT && !isDefault && !isRoot) { - /* insert default locale */ - uprv_strcpy(name, uloc_getDefault()); - r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); - // If we failed due to out-of-memory, report the failure and exit early. - if (intStatus == U_MEMORY_ALLOCATION_ERROR) { - *status = intStatus; - goto finishUnlock; - } + /* we could still have r == NULL at this point - maybe even default locale is not */ + /* present */ + if(r == NULL) { + uprv_strcpy(name, kRootLocaleName); + r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); + // If we failed due to out-of-memory, report the failure and exit early. + if (intStatus == U_MEMORY_ALLOCATION_ERROR) { + *status = intStatus; + goto finish; + } + if(r != NULL) { + t1 = r; intStatus = U_USING_DEFAULT_WARNING; - if(r != NULL) { /* the default locale exists */ - t1 = r; - hasRealData = TRUE; - isDefault = TRUE; - // TODO: Why not if (usingUSRData) { ... } like in the non-default-locale code path? - if (hasChopped && !isRoot) { - if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) { - goto finishUnlock; - } - } - } + hasRealData = TRUE; + } else { /* we don't even have the root locale */ + *status = U_MISSING_RESOURCE_ERROR; + goto finish; } - - /* we could still have r == NULL at this point - maybe even default locale is not */ - /* present */ - if(r == NULL) { - uprv_strcpy(name, kRootLocaleName); - r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); - // If we failed due to out-of-memory, report the failure and exit early. - if (intStatus == U_MEMORY_ALLOCATION_ERROR) { - *status = intStatus; - goto finishUnlock; - } - if(r != NULL) { - t1 = r; - intStatus = U_USING_DEFAULT_WARNING; - hasRealData = TRUE; - } else { /* we don't even have the root locale */ - *status = U_MISSING_RESOURCE_ERROR; - goto finishUnlock; - } - } else if(!isRoot && uprv_strcmp(t1->fName, kRootLocaleName) != 0 && - t1->fParent == NULL && !r->fData.noFallback) { - if (!insertRootBundle(t1, status)) { - goto finishUnlock; - } - if(!hasRealData) { - r->fBogus = U_USING_DEFAULT_WARNING; - } + } else if(!isRoot && uprv_strcmp(t1->fName, kRootLocaleName) != 0 && + t1->fParent == NULL && !r->fData.noFallback) { + if (!insertRootBundle(t1, status)) { + goto finish; } - - // TODO: Does this ever loop? - while(r != NULL && !isRoot && t1->fParent != NULL) { - t1->fParent->fCountExisting++; - t1 = t1->fParent; + if(!hasRealData) { + r->fBogus = U_USING_DEFAULT_WARNING; } - } /* umtx_lock */ -finishUnlock: - umtx_unlock(resbMutex()); + } + // TODO: Does this ever loop? + while(r != NULL && !isRoot && t1->fParent != NULL) { + t1->fParent->fCountExisting++; + t1 = t1->fParent; + } + +finish: if(U_SUCCESS(*status)) { if(intStatus != U_ZERO_ERROR) { *status = intStatus; @@ -790,7 +782,7 @@ entryOpenDirect(const char* path, const char* localeID, UErrorCode* status) { return NULL; } - umtx_lock(resbMutex()); + Mutex lock(&resbMutex); // findFirstExisting() without fallbacks. UResourceDataEntry *r = init_entry(localeID, path, status); if(U_SUCCESS(*status)) { @@ -828,7 +820,6 @@ entryOpenDirect(const char* path, const char* localeID, UErrorCode* status) { t1 = t1->fParent; } } - umtx_unlock(resbMutex()); return r; } @@ -871,9 +862,8 @@ static void entryCloseInt(UResourceDataEntry *resB) { */ static void entryClose(UResourceDataEntry *resB) { - umtx_lock(resbMutex()); + Mutex lock(&resbMutex); entryCloseInt(resB); - umtx_unlock(resbMutex()); } /* @@ -1177,6 +1167,7 @@ static UResourceBundle *init_resb_result(const ResourceData *rdata, Resource r, if(mainRes != result) { ures_close(mainRes); } + ResourceTracer(resB).maybeTrace("getalias"); return result; } } else { @@ -1256,6 +1247,7 @@ static UResourceBundle *init_resb_result(const ResourceData *rdata, Resource r, /*resB->fParent = parent->fRes;*/ uprv_memmove(&resB->fResData, rdata, sizeof(ResourceData)); resB->fSize = res_countArrayItems(&(resB->fResData), resB->fRes); + ResourceTracer(resB).trace("get"); return resB; } @@ -1304,7 +1296,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getString(const UResourceBundle* resB, int32_ *status = U_ILLEGAL_ARGUMENT_ERROR; return NULL; } - s = res_getString(&(resB->fResData), resB->fRes, len); + s = res_getString({resB}, &(resB->fResData), resB->fRes, len); if (s == NULL) { *status = U_RESOURCE_TYPE_MISMATCH; } @@ -1393,7 +1385,7 @@ U_CAPI const uint8_t* U_EXPORT2 ures_getBinary(const UResourceBundle* resB, int3 *status = U_ILLEGAL_ARGUMENT_ERROR; return NULL; } - p = res_getBinary(&(resB->fResData), resB->fRes, len); + p = res_getBinary({resB}, &(resB->fResData), resB->fRes, len); if (p == NULL) { *status = U_RESOURCE_TYPE_MISMATCH; } @@ -1410,7 +1402,7 @@ U_CAPI const int32_t* U_EXPORT2 ures_getIntVector(const UResourceBundle* resB, i *status = U_ILLEGAL_ARGUMENT_ERROR; return NULL; } - p = res_getIntVector(&(resB->fResData), resB->fRes, len); + p = res_getIntVector({resB}, &(resB->fResData), resB->fRes, len); if (p == NULL) { *status = U_RESOURCE_TYPE_MISMATCH; } @@ -1431,7 +1423,7 @@ U_CAPI int32_t U_EXPORT2 ures_getInt(const UResourceBundle* resB, UErrorCode *st *status = U_RESOURCE_TYPE_MISMATCH; return 0xffffffff; } - return RES_GET_INT(resB->fRes); + return res_getInt({resB}, resB->fRes); } U_CAPI uint32_t U_EXPORT2 ures_getUInt(const UResourceBundle* resB, UErrorCode *status) { @@ -1446,7 +1438,7 @@ U_CAPI uint32_t U_EXPORT2 ures_getUInt(const UResourceBundle* resB, UErrorCode * *status = U_RESOURCE_TYPE_MISMATCH; return 0xffffffff; } - return RES_GET_UINT(resB->fRes); + return res_getUInt({resB}, resB->fRes); } U_CAPI UResType U_EXPORT2 ures_getType(const UResourceBundle *resB) { @@ -1457,10 +1449,18 @@ U_CAPI UResType U_EXPORT2 ures_getType(const UResourceBundle *resB) { } U_CAPI const char * U_EXPORT2 ures_getKey(const UResourceBundle *resB) { + // + // TODO: Trace ures_getKey? I guess not usually. + // + // We usually get the key string to decide whether we want the value, or to + // make a key-value pair. Tracing the value should suffice. + // + // However, I believe we have some data (e.g., in res_index) where the key + // strings are the data. Tracing the enclosing table should suffice. + // if(resB == NULL) { return NULL; } - return(resB->fKey); } @@ -1480,7 +1480,7 @@ static const UChar* ures_getStringWithAlias(const UResourceBundle *resB, Resourc ures_close(tempRes); return result; } else { - return res_getString(&(resB->fResData), r, len); + return res_getString({resB, sIndex}, &(resB->fResData), r, len); } } @@ -1516,7 +1516,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getNextString(UResourceBundle *resB, int32_t* switch(RES_GET_TYPE(resB->fRes)) { case URES_STRING: case URES_STRING_V2: - return res_getString(&(resB->fResData), resB->fRes, len); + return res_getString({resB}, &(resB->fResData), resB->fRes, len); case URES_TABLE: case URES_TABLE16: case URES_TABLE32: @@ -1661,7 +1661,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByIndex(const UResourceBundle *resB, switch(RES_GET_TYPE(resB->fRes)) { case URES_STRING: case URES_STRING_V2: - return res_getString(&(resB->fResData), resB->fRes, len); + return res_getString({resB}, &(resB->fResData), resB->fRes, len); case URES_TABLE: case URES_TABLE16: case URES_TABLE32: @@ -1953,10 +1953,10 @@ void getAllItemsWithFallback( // When the sink sees the no-fallback/no-inheritance marker, // then it would remove the parent's item. // We would deserialize parent values even though they are overridden in a child bundle. - value.pResData = &bundle->fResData; + value.setData(&bundle->fResData); UResourceDataEntry *parentEntry = bundle->fData->fParent; UBool hasParent = parentEntry != NULL && U_SUCCESS(parentEntry->fBogus); - value.setResource(bundle->fRes); + value.setResource(bundle->fRes, ResourceTracer(bundle)); sink.put(bundle->fKey, value, !hasParent, errorCode); if (hasParent) { // We might try to query the sink whether @@ -2001,31 +2001,60 @@ void getAllItemsWithFallback( } // namespace +// Requires a ResourceDataValue fill-in, so that we need not cast from a ResourceValue. +// Unfortunately, the caller must know which subclass to make and pass in. +// Alternatively, we could make it as polymorphic as in Java by +// returning a ResourceValue pointer (possibly wrapped into a LocalPointer) +// that the caller then owns. +// +// Also requires a UResourceBundle fill-in, so that the value's ResourceTracer +// can point to a non-local bundle. +// Without tracing, the child bundle could be a function-local object. +U_CAPI void U_EXPORT2 +ures_getValueWithFallback(const UResourceBundle *bundle, const char *path, + UResourceBundle *tempFillIn, + ResourceDataValue &value, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return; } + if (path == nullptr) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + const UResourceBundle *rb; + if (*path == 0) { + // empty path + rb = bundle; + } else { + rb = ures_getByKeyWithFallback(bundle, path, tempFillIn, &errorCode); + if (U_FAILURE(errorCode)) { + return; + } + } + value.setData(&rb->fResData); + value.setResource(rb->fRes, ResourceTracer(rb)); +} + U_CAPI void U_EXPORT2 ures_getAllItemsWithFallback(const UResourceBundle *bundle, const char *path, icu::ResourceSink &sink, UErrorCode &errorCode) { if (U_FAILURE(errorCode)) { return; } - if (path == NULL) { + if (path == nullptr) { errorCode = U_ILLEGAL_ARGUMENT_ERROR; return; } - UResourceBundle stackBundle; - ures_initStackObject(&stackBundle); + StackUResourceBundle stackBundle; const UResourceBundle *rb; if (*path == 0) { // empty path rb = bundle; } else { - rb = ures_getByKeyWithFallback(bundle, path, &stackBundle, &errorCode); + rb = ures_getByKeyWithFallback(bundle, path, stackBundle.getAlias(), &errorCode); if (U_FAILURE(errorCode)) { - ures_close(&stackBundle); return; } } // Get all table items with fallback. ResourceDataValue value; getAllItemsWithFallback(rb, value, sink, errorCode); - ures_close(&stackBundle); } U_CAPI UResourceBundle* U_EXPORT2 ures_getByKey(const UResourceBundle *resB, const char* inKey, UResourceBundle *fillIn, UErrorCode *status) { @@ -2108,7 +2137,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByKey(const UResourceBundle *resB, c switch (RES_GET_TYPE(res)) { case URES_STRING: case URES_STRING_V2: - return res_getString(rd, res, len); + return res_getString({resB, key}, rd, res, len); case URES_ALIAS: { const UChar* result = 0; @@ -2130,7 +2159,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByKey(const UResourceBundle *resB, c switch (RES_GET_TYPE(res)) { case URES_STRING: case URES_STRING_V2: - return res_getString(&(resB->fResData), res, len); + return res_getString({resB, key}, &(resB->fResData), res, len); case URES_ALIAS: { const UChar* result = 0; @@ -2151,6 +2180,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByKey(const UResourceBundle *resB, c /* here should go a first attempt to locate the key using index table */ const ResourceData *rd = getFallbackData(resB, &key, &realData, &res, status); if(U_SUCCESS(*status)) { + // TODO: Tracing return res_getString(rd, res, len); } else { *status = U_MISSING_RESOURCE_ERROR; @@ -2296,6 +2326,8 @@ ures_openWithType(UResourceBundle *r, const char* path, const char* localeID, r->fSize = res_countArrayItems(&(r->fResData), r->fRes); r->fIndex = -1; + ResourceTracer(r).traceOpen(); + return r; } diff --git a/deps/icu-small/source/common/uresdata.cpp b/deps/icu-small/source/common/uresdata.cpp index a0b8d3ba904ad6..1bb938be62c35b 100644 --- a/deps/icu-small/source/common/uresdata.cpp +++ b/deps/icu-small/source/common/uresdata.cpp @@ -33,6 +33,7 @@ #include "uinvchar.h" #include "uresdata.h" #include "uresimp.h" +#include "utracimp.h" /* * Resource access helpers @@ -307,7 +308,7 @@ res_getPublicType(Resource res) { } U_CAPI const UChar * U_EXPORT2 -res_getString(const ResourceData *pResData, Resource res, int32_t *pLength) { +res_getStringNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength) { const UChar *p; uint32_t offset=RES_GET_OFFSET(res); int32_t length; @@ -402,7 +403,8 @@ int32_t getStringArray(const ResourceData *pResData, const icu::ResourceArray &a } for(int32_t i = 0; i < length; ++i) { int32_t sLength; - const UChar *s = res_getString(pResData, array.internalGetResource(pResData, i), &sLength); + // No tracing: handled by the caller + const UChar *s = res_getStringNoTrace(pResData, array.internalGetResource(pResData, i), &sLength); if(s == NULL) { errorCode = U_RESOURCE_TYPE_MISMATCH; return 0; @@ -434,7 +436,7 @@ res_getAlias(const ResourceData *pResData, Resource res, int32_t *pLength) { } U_CAPI const uint8_t * U_EXPORT2 -res_getBinary(const ResourceData *pResData, Resource res, int32_t *pLength) { +res_getBinaryNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength) { const uint8_t *p; uint32_t offset=RES_GET_OFFSET(res); int32_t length; @@ -454,7 +456,7 @@ res_getBinary(const ResourceData *pResData, Resource res, int32_t *pLength) { U_CAPI const int32_t * U_EXPORT2 -res_getIntVector(const ResourceData *pResData, Resource res, int32_t *pLength) { +res_getIntVectorNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength) { const int32_t *p; uint32_t offset=RES_GET_OFFSET(res); int32_t length; @@ -507,7 +509,7 @@ const UChar *ResourceDataValue::getString(int32_t &length, UErrorCode &errorCode if(U_FAILURE(errorCode)) { return NULL; } - const UChar *s = res_getString(pResData, res, &length); + const UChar *s = res_getString(fTraceInfo, &getData(), res, &length); if(s == NULL) { errorCode = U_RESOURCE_TYPE_MISMATCH; } @@ -518,7 +520,7 @@ const UChar *ResourceDataValue::getAliasString(int32_t &length, UErrorCode &erro if(U_FAILURE(errorCode)) { return NULL; } - const UChar *s = res_getAlias(pResData, res, &length); + const UChar *s = res_getAlias(&getData(), res, &length); if(s == NULL) { errorCode = U_RESOURCE_TYPE_MISMATCH; } @@ -532,7 +534,7 @@ int32_t ResourceDataValue::getInt(UErrorCode &errorCode) const { if(RES_GET_TYPE(res) != URES_INT) { errorCode = U_RESOURCE_TYPE_MISMATCH; } - return RES_GET_INT(res); + return res_getInt(fTraceInfo, res); } uint32_t ResourceDataValue::getUInt(UErrorCode &errorCode) const { @@ -542,14 +544,14 @@ uint32_t ResourceDataValue::getUInt(UErrorCode &errorCode) const { if(RES_GET_TYPE(res) != URES_INT) { errorCode = U_RESOURCE_TYPE_MISMATCH; } - return RES_GET_UINT(res); + return res_getUInt(fTraceInfo, res); } const int32_t *ResourceDataValue::getIntVector(int32_t &length, UErrorCode &errorCode) const { if(U_FAILURE(errorCode)) { return NULL; } - const int32_t *iv = res_getIntVector(pResData, res, &length); + const int32_t *iv = res_getIntVector(fTraceInfo, &getData(), res, &length); if(iv == NULL) { errorCode = U_RESOURCE_TYPE_MISMATCH; } @@ -560,7 +562,7 @@ const uint8_t *ResourceDataValue::getBinary(int32_t &length, UErrorCode &errorCo if(U_FAILURE(errorCode)) { return NULL; } - const uint8_t *b = res_getBinary(pResData, res, &length); + const uint8_t *b = res_getBinary(fTraceInfo, &getData(), res, &length); if(b == NULL) { errorCode = U_RESOURCE_TYPE_MISMATCH; } @@ -578,19 +580,19 @@ ResourceArray ResourceDataValue::getArray(UErrorCode &errorCode) const { switch(RES_GET_TYPE(res)) { case URES_ARRAY: if (offset!=0) { // empty if offset==0 - items32 = (const Resource *)pResData->pRoot+offset; + items32 = (const Resource *)getData().pRoot+offset; length = *items32++; } break; case URES_ARRAY16: - items16 = pResData->p16BitUnits+offset; + items16 = getData().p16BitUnits+offset; length = *items16++; break; default: errorCode = U_RESOURCE_TYPE_MISMATCH; return ResourceArray(); } - return ResourceArray(items16, items32, length); + return ResourceArray(items16, items32, length, fTraceInfo); } ResourceTable ResourceDataValue::getTable(UErrorCode &errorCode) const { @@ -606,19 +608,19 @@ ResourceTable ResourceDataValue::getTable(UErrorCode &errorCode) const { switch(RES_GET_TYPE(res)) { case URES_TABLE: if (offset != 0) { // empty if offset==0 - keys16 = (const uint16_t *)(pResData->pRoot+offset); + keys16 = (const uint16_t *)(getData().pRoot+offset); length = *keys16++; items32 = (const Resource *)(keys16+length+(~length&1)); } break; case URES_TABLE16: - keys16 = pResData->p16BitUnits+offset; + keys16 = getData().p16BitUnits+offset; length = *keys16++; items16 = keys16 + length; break; case URES_TABLE32: if (offset != 0) { // empty if offset==0 - keys32 = pResData->pRoot+offset; + keys32 = getData().pRoot+offset; length = *keys32++; items32 = (const Resource *)keys32 + length; } @@ -627,22 +629,22 @@ ResourceTable ResourceDataValue::getTable(UErrorCode &errorCode) const { errorCode = U_RESOURCE_TYPE_MISMATCH; return ResourceTable(); } - return ResourceTable(keys16, keys32, items16, items32, length); + return ResourceTable(keys16, keys32, items16, items32, length, fTraceInfo); } UBool ResourceDataValue::isNoInheritanceMarker() const { - return ::isNoInheritanceMarker(pResData, res); + return ::isNoInheritanceMarker(&getData(), res); } int32_t ResourceDataValue::getStringArray(UnicodeString *dest, int32_t capacity, UErrorCode &errorCode) const { - return ::getStringArray(pResData, getArray(errorCode), dest, capacity, errorCode); + return ::getStringArray(&getData(), getArray(errorCode), dest, capacity, errorCode); } int32_t ResourceDataValue::getStringArrayOrStringAsArray(UnicodeString *dest, int32_t capacity, UErrorCode &errorCode) const { if(URES_IS_ARRAY(res)) { - return ::getStringArray(pResData, getArray(errorCode), dest, capacity, errorCode); + return ::getStringArray(&getData(), getArray(errorCode), dest, capacity, errorCode); } if(U_FAILURE(errorCode)) { return 0; @@ -656,7 +658,7 @@ int32_t ResourceDataValue::getStringArrayOrStringAsArray(UnicodeString *dest, in return 1; } int32_t sLength; - const UChar *s = res_getString(pResData, res, &sLength); + const UChar *s = res_getString(fTraceInfo, &getData(), res, &sLength); if(s != NULL) { dest[0].setTo(TRUE, s, sLength); return 1; @@ -671,7 +673,7 @@ UnicodeString ResourceDataValue::getStringOrFirstOfArray(UErrorCode &errorCode) return us; } int32_t sLength; - const UChar *s = res_getString(pResData, res, &sLength); + const UChar *s = res_getString(fTraceInfo, &getData(), res, &sLength); if(s != NULL) { us.setTo(TRUE, s, sLength); return us; @@ -681,7 +683,8 @@ UnicodeString ResourceDataValue::getStringOrFirstOfArray(UErrorCode &errorCode) return us; } if(array.getSize() > 0) { - s = res_getString(pResData, array.internalGetResource(pResData, 0), &sLength); + // Tracing is already performed above (unimportant for trace that this is an array) + s = res_getStringNoTrace(&getData(), array.internalGetResource(&getData(), 0), &sLength); if(s != NULL) { us.setTo(TRUE, s, sLength); return us; @@ -818,18 +821,45 @@ UBool icu::ResourceTable::getKeyAndValue(int32_t i, const char *&key, icu::ResourceValue &value) const { if(0 <= i && i < length) { icu::ResourceDataValue &rdValue = static_cast(value); - if (keys16 != NULL) { - key = RES_GET_KEY16(rdValue.pResData, keys16[i]); + if (keys16 != nullptr) { + key = RES_GET_KEY16(&rdValue.getData(), keys16[i]); } else { - key = RES_GET_KEY32(rdValue.pResData, keys32[i]); + key = RES_GET_KEY32(&rdValue.getData(), keys32[i]); } Resource res; - if (items16 != NULL) { - res = makeResourceFrom16(rdValue.pResData, items16[i]); + if (items16 != nullptr) { + res = makeResourceFrom16(&rdValue.getData(), items16[i]); } else { res = items32[i]; } - rdValue.setResource(res); + // Note: the ResourceTracer keeps a reference to the field of this + // ResourceTable. This is OK because the ResourceTable should remain + // alive for the duration that fields are being read from it + // (including nested fields). + rdValue.setResource(res, ResourceTracer(fTraceInfo, key)); + return TRUE; + } + return FALSE; +} + +UBool icu::ResourceTable::findValue(const char *key, ResourceValue &value) const { + icu::ResourceDataValue &rdValue = static_cast(value); + const char *realKey = nullptr; + int32_t i; + if (keys16 != nullptr) { + i = _res_findTableItem(&rdValue.getData(), keys16, length, key, &realKey); + } else { + i = _res_findTable32Item(&rdValue.getData(), keys32, length, key, &realKey); + } + if (i >= 0) { + Resource res; + if (items16 != nullptr) { + res = makeResourceFrom16(&rdValue.getData(), items16[i]); + } else { + res = items32[i]; + } + // Same note about lifetime as in getKeyAndValue(). + rdValue.setResource(res, ResourceTracer(fTraceInfo, key)); return TRUE; } return FALSE; @@ -875,7 +905,13 @@ uint32_t icu::ResourceArray::internalGetResource(const ResourceData *pResData, i UBool icu::ResourceArray::getValue(int32_t i, icu::ResourceValue &value) const { if(0 <= i && i < length) { icu::ResourceDataValue &rdValue = static_cast(value); - rdValue.setResource(internalGetResource(rdValue.pResData, i)); + // Note: the ResourceTracer keeps a reference to the field of this + // ResourceArray. This is OK because the ResourceArray should remain + // alive for the duration that fields are being read from it + // (including nested fields). + rdValue.setResource( + internalGetResource(&rdValue.getData(), i), + ResourceTracer(fTraceInfo, i)); return TRUE; } return FALSE; diff --git a/deps/icu-small/source/common/uresdata.h b/deps/icu-small/source/common/uresdata.h index 4e28ddccf63199..d1b67babf29049 100644 --- a/deps/icu-small/source/common/uresdata.h +++ b/deps/icu-small/source/common/uresdata.h @@ -69,14 +69,16 @@ typedef uint32_t Resource; #define RES_GET_OFFSET(res) ((res)&0x0fffffff) #define RES_GET_POINTER(pRoot, res) ((pRoot)+RES_GET_OFFSET(res)) -/* get signed and unsigned integer values directly from the Resource handle */ +/* get signed and unsigned integer values directly from the Resource handle + * NOTE: For proper logging, please use the res_getInt() constexpr + */ #if U_SIGNED_RIGHT_SHIFT_IS_ARITHMETIC -# define RES_GET_INT(res) (((int32_t)((res)<<4L))>>4L) +# define RES_GET_INT_NO_TRACE(res) (((int32_t)((res)<<4L))>>4L) #else -# define RES_GET_INT(res) (int32_t)(((res)&0x08000000) ? (res)|0xf0000000 : (res)&0x07ffffff) +# define RES_GET_INT_NO_TRACE(res) (int32_t)(((res)&0x08000000) ? (res)|0xf0000000 : (res)&0x07ffffff) #endif -#define RES_GET_UINT(res) ((res)&0x0fffffff) +#define RES_GET_UINT_NO_TRACE(res) ((res)&0x0fffffff) #define URES_IS_ARRAY(type) ((int32_t)(type)==URES_ARRAY || (int32_t)(type)==URES_ARRAY16) #define URES_IS_TABLE(type) ((int32_t)(type)==URES_TABLE || (int32_t)(type)==URES_TABLE16 || (int32_t)(type)==URES_TABLE32) @@ -423,22 +425,26 @@ res_unload(ResourceData *pResData); U_INTERNAL UResType U_EXPORT2 res_getPublicType(Resource res); +/////////////////////////////////////////////////////////////////////////// +// To enable tracing, use the inline versions of the res_get* functions. // +/////////////////////////////////////////////////////////////////////////// + /* * Return a pointer to a zero-terminated, const UChar* string * and set its length in *pLength. * Returns NULL if not found. */ U_INTERNAL const UChar * U_EXPORT2 -res_getString(const ResourceData *pResData, Resource res, int32_t *pLength); - -U_INTERNAL const UChar * U_EXPORT2 -res_getAlias(const ResourceData *pResData, Resource res, int32_t *pLength); +res_getStringNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength); U_INTERNAL const uint8_t * U_EXPORT2 -res_getBinary(const ResourceData *pResData, Resource res, int32_t *pLength); +res_getBinaryNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength); U_INTERNAL const int32_t * U_EXPORT2 -res_getIntVector(const ResourceData *pResData, Resource res, int32_t *pLength); +res_getIntVectorNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength); + +U_INTERNAL const UChar * U_EXPORT2 +res_getAlias(const ResourceData *pResData, Resource res, int32_t *pLength); U_INTERNAL Resource U_EXPORT2 res_getResource(const ResourceData *pResData, const char *key); @@ -470,17 +476,55 @@ U_CFUNC Resource res_findResource(const ResourceData *pResData, Resource r, #ifdef __cplusplus #include "resource.h" +#include "restrace.h" U_NAMESPACE_BEGIN +inline const UChar* res_getString(const ResourceTracer& traceInfo, + const ResourceData *pResData, Resource res, int32_t *pLength) { + traceInfo.trace("string"); + return res_getStringNoTrace(pResData, res, pLength); +} + +inline const uint8_t* res_getBinary(const ResourceTracer& traceInfo, + const ResourceData *pResData, Resource res, int32_t *pLength) { + traceInfo.trace("binary"); + return res_getBinaryNoTrace(pResData, res, pLength); +} + +inline const int32_t* res_getIntVector(const ResourceTracer& traceInfo, + const ResourceData *pResData, Resource res, int32_t *pLength) { + traceInfo.trace("intvector"); + return res_getIntVectorNoTrace(pResData, res, pLength); +} + +inline int32_t res_getInt(const ResourceTracer& traceInfo, Resource res) { + traceInfo.trace("int"); + return RES_GET_INT_NO_TRACE(res); +} + +inline uint32_t res_getUInt(const ResourceTracer& traceInfo, Resource res) { + traceInfo.trace("uint"); + return RES_GET_UINT_NO_TRACE(res); +} + class ResourceDataValue : public ResourceValue { public: - ResourceDataValue() : pResData(NULL), res(static_cast(URES_NONE)) {} + ResourceDataValue() : + res(static_cast(URES_NONE)), + fTraceInfo() {} virtual ~ResourceDataValue(); - void setData(const ResourceData *data) { pResData = data; } - void setResource(Resource r) { res = r; } + void setData(const ResourceData *data) { + resData = *data; + } + void setResource(Resource r, ResourceTracer&& traceInfo) { + res = r; + fTraceInfo = traceInfo; + } + + const ResourceData &getData() const { return resData; } virtual UResType getType() const; virtual const UChar *getString(int32_t &length, UErrorCode &errorCode) const; virtual const UChar *getAliasString(int32_t &length, UErrorCode &errorCode) const; @@ -497,10 +541,12 @@ class ResourceDataValue : public ResourceValue { UErrorCode &errorCode) const; virtual UnicodeString getStringOrFirstOfArray(UErrorCode &errorCode) const; - const ResourceData *pResData; - private: + // TODO(ICU-20769): If UResourceBundle.fResData becomes a pointer, + // then remove this value field again and just store a pResData pointer. + ResourceData resData; Resource res; + ResourceTracer fTraceInfo; }; U_NAMESPACE_END diff --git a/deps/icu-small/source/common/uresimp.h b/deps/icu-small/source/common/uresimp.h index 16144012a5bc0d..2e477dfad3e98f 100644 --- a/deps/icu-small/source/common/uresimp.h +++ b/deps/icu-small/source/common/uresimp.h @@ -67,6 +67,9 @@ struct UResourceBundle { char *fVersion; UResourceDataEntry *fTopLevelData; /* for getting the valid locale */ char *fResPath; /* full path to the resource: "zh_TW/CollationElements/Sequence" */ + // TODO(ICU-20769): Try to change the by-value fResData into a pointer, + // with the struct in only one place for each bundle. + // Also replace class ResourceDataValue.resData with a pResData pointer again. ResourceData fResData; char fResBuf[RES_BUFSIZE]; int32_t fResPathLen; @@ -281,6 +284,11 @@ ures_getStringByKeyWithFallback(const UResourceBundle *resB, #ifdef __cplusplus +U_CAPI void U_EXPORT2 +ures_getValueWithFallback(const UResourceBundle *bundle, const char *path, + UResourceBundle *tempFillIn, + icu::ResourceDataValue &value, UErrorCode &errorCode); + U_CAPI void U_EXPORT2 ures_getAllItemsWithFallback(const UResourceBundle *bundle, const char *path, icu::ResourceSink &sink, UErrorCode &errorCode); diff --git a/deps/icu-small/source/common/usprep.cpp b/deps/icu-small/source/common/usprep.cpp index 9155ae077b3497..f1c075a391116f 100644 --- a/deps/icu-small/source/common/usprep.cpp +++ b/deps/icu-small/source/common/usprep.cpp @@ -45,13 +45,9 @@ U_CDECL_BEGIN Static cache for already opened StringPrep profiles */ static UHashtable *SHARED_DATA_HASHTABLE = NULL; -static icu::UInitOnce gSharedDataInitOnce; - -static UMutex *usprepMutex() { - static UMutex m = U_MUTEX_INITIALIZER; - return &m; -} +static icu::UInitOnce gSharedDataInitOnce = U_INITONCE_INITIALIZER; +static UMutex usprepMutex; /* format version of spp file */ //static uint8_t formatVersion[4]={ 0, 0, 0, 0 }; @@ -151,9 +147,9 @@ usprep_internal_flushCache(UBool noRefCount){ * if shared data hasn't even been lazy evaluated yet * return 0 */ - umtx_lock(usprepMutex()); + umtx_lock(&usprepMutex); if (SHARED_DATA_HASHTABLE == NULL) { - umtx_unlock(usprepMutex()); + umtx_unlock(&usprepMutex); return 0; } @@ -184,7 +180,7 @@ usprep_internal_flushCache(UBool noRefCount){ } } - umtx_unlock(usprepMutex()); + umtx_unlock(&usprepMutex); return deletedNum; } @@ -262,7 +258,7 @@ loadData(UStringPrepProfile* profile, } /* in the mutex block, set the data for this process */ - umtx_lock(usprepMutex()); + umtx_lock(&usprepMutex); if(profile->sprepData==NULL) { profile->sprepData=dataMemory; dataMemory=NULL; @@ -271,7 +267,7 @@ loadData(UStringPrepProfile* profile, } else { p=(const int32_t *)udata_getMemory(profile->sprepData); } - umtx_unlock(usprepMutex()); + umtx_unlock(&usprepMutex); /* initialize some variables */ profile->mappingData=(uint16_t *)((uint8_t *)(p+_SPREP_INDEX_TOP)+profile->indexes[_SPREP_INDEX_TRIE_SIZE]); @@ -328,12 +324,12 @@ usprep_getProfile(const char* path, stackKey.path = (char*) path; /* fetch the data from the cache */ - umtx_lock(usprepMutex()); + umtx_lock(&usprepMutex); profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey)); if(profile != NULL) { profile->refCount++; } - umtx_unlock(usprepMutex()); + umtx_unlock(&usprepMutex); if(profile == NULL) { /* else load the data and put the data in the cache */ @@ -365,7 +361,7 @@ usprep_getProfile(const char* path, return NULL; } - umtx_lock(usprepMutex()); + umtx_lock(&usprepMutex); // If another thread already inserted the same key/value, refcount and cleanup our thread data profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey)); if(profile != NULL) { @@ -386,7 +382,7 @@ usprep_getProfile(const char* path, profile->refCount = 1; uhash_put(SHARED_DATA_HASHTABLE, key.orphan(), profile, status); } - umtx_unlock(usprepMutex()); + umtx_unlock(&usprepMutex); } return profile; @@ -425,12 +421,12 @@ usprep_close(UStringPrepProfile* profile){ return; } - umtx_lock(usprepMutex()); + umtx_lock(&usprepMutex); /* decrement the ref count*/ if(profile->refCount > 0){ profile->refCount--; } - umtx_unlock(usprepMutex()); + umtx_unlock(&usprepMutex); } diff --git a/deps/icu-small/source/common/ustr_titlecase_brkiter.cpp b/deps/icu-small/source/common/ustr_titlecase_brkiter.cpp index 056b40eb4175f6..457905eb60da00 100644 --- a/deps/icu-small/source/common/ustr_titlecase_brkiter.cpp +++ b/deps/icu-small/source/common/ustr_titlecase_brkiter.cpp @@ -45,7 +45,7 @@ class WholeStringBreakIterator : public BreakIterator { WholeStringBreakIterator() : BreakIterator(), length(0) {} ~WholeStringBreakIterator() U_OVERRIDE; UBool operator==(const BreakIterator&) const U_OVERRIDE; - BreakIterator *clone() const U_OVERRIDE; + WholeStringBreakIterator *clone() const U_OVERRIDE; static UClassID U_EXPORT2 getStaticClassID(); UClassID getDynamicClassID() const U_OVERRIDE; CharacterIterator &getText() const U_OVERRIDE; @@ -62,9 +62,9 @@ class WholeStringBreakIterator : public BreakIterator { int32_t preceding(int32_t offset) U_OVERRIDE; UBool isBoundary(int32_t offset) U_OVERRIDE; int32_t next(int32_t n) U_OVERRIDE; - BreakIterator *createBufferClone(void *stackBuffer, int32_t &BufferSize, - UErrorCode &errorCode) U_OVERRIDE; - BreakIterator &refreshInputText(UText *input, UErrorCode &errorCode) U_OVERRIDE; + WholeStringBreakIterator *createBufferClone(void *stackBuffer, int32_t &BufferSize, + UErrorCode &errorCode) U_OVERRIDE; + WholeStringBreakIterator &refreshInputText(UText *input, UErrorCode &errorCode) U_OVERRIDE; private: int32_t length; @@ -74,7 +74,7 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(WholeStringBreakIterator) WholeStringBreakIterator::~WholeStringBreakIterator() {} UBool WholeStringBreakIterator::operator==(const BreakIterator&) const { return FALSE; } -BreakIterator *WholeStringBreakIterator::clone() const { return nullptr; } +WholeStringBreakIterator *WholeStringBreakIterator::clone() const { return nullptr; } CharacterIterator &WholeStringBreakIterator::getText() const { UPRV_UNREACHABLE; // really should not be called @@ -113,14 +113,14 @@ int32_t WholeStringBreakIterator::preceding(int32_t /*offset*/) { return 0; } UBool WholeStringBreakIterator::isBoundary(int32_t /*offset*/) { return FALSE; } int32_t WholeStringBreakIterator::next(int32_t /*n*/) { return length; } -BreakIterator *WholeStringBreakIterator::createBufferClone( +WholeStringBreakIterator *WholeStringBreakIterator::createBufferClone( void * /*stackBuffer*/, int32_t & /*BufferSize*/, UErrorCode &errorCode) { if (U_SUCCESS(errorCode)) { errorCode = U_UNSUPPORTED_ERROR; } return nullptr; } -BreakIterator &WholeStringBreakIterator::refreshInputText( +WholeStringBreakIterator &WholeStringBreakIterator::refreshInputText( UText * /*input*/, UErrorCode &errorCode) { if (U_SUCCESS(errorCode)) { errorCode = U_UNSUPPORTED_ERROR; diff --git a/deps/icu-small/source/common/ustring.cpp b/deps/icu-small/source/common/ustring.cpp index a1a51f4b1e1734..6886c145d9a216 100644 --- a/deps/icu-small/source/common/ustring.cpp +++ b/deps/icu-small/source/common/ustring.cpp @@ -1428,7 +1428,7 @@ u_unescape(const char *src, UChar *dest, int32_t destCapacity) { * NUL-terminate a string no matter what its type. * Set warning and error codes accordingly. */ -#define __TERMINATE_STRING(dest, destCapacity, length, pErrorCode) \ +#define __TERMINATE_STRING(dest, destCapacity, length, pErrorCode) UPRV_BLOCK_MACRO_BEGIN { \ if(pErrorCode!=NULL && U_SUCCESS(*pErrorCode)) { \ /* not a public function, so no complete argument checking */ \ \ @@ -1448,7 +1448,8 @@ u_unescape(const char *src, UChar *dest, int32_t destCapacity) { /* even the string itself did not fit - set an error code */ \ *pErrorCode=U_BUFFER_OVERFLOW_ERROR; \ } \ - } + } \ +} UPRV_BLOCK_MACRO_END U_CAPI int32_t U_EXPORT2 u_terminateUChars(UChar *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode) { @@ -1488,7 +1489,7 @@ u_terminateWChars(wchar_t *dest, int32_t destCapacity, int32_t length, UErrorCod the output range. [LIU] */ -#define STRING_HASH(TYPE, STR, STRLEN, DEREF) \ +#define STRING_HASH(TYPE, STR, STRLEN, DEREF) UPRV_BLOCK_MACRO_BEGIN { \ uint32_t hash = 0; \ const TYPE *p = (const TYPE*) STR; \ if (p != NULL) { \ @@ -1500,7 +1501,8 @@ u_terminateWChars(wchar_t *dest, int32_t destCapacity, int32_t length, UErrorCod p += inc; \ } \ } \ - return static_cast(hash) + return static_cast(hash); \ +} UPRV_BLOCK_MACRO_END /* Used by UnicodeString to compute its hashcode - Not public API. */ U_CAPI int32_t U_EXPORT2 diff --git a/deps/icu-small/source/common/utext.cpp b/deps/icu-small/source/common/utext.cpp index 5e3a005626e6b8..324341f1ba65dc 100644 --- a/deps/icu-small/source/common/utext.cpp +++ b/deps/icu-small/source/common/utext.cpp @@ -567,7 +567,7 @@ enum { struct ExtendedUText { UText ut; - UAlignedMemory extension; + max_align_t extension; }; static const UText emptyText = UTEXT_INITIALIZER; @@ -582,7 +582,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(UAlignedMemory); + spaceRequired = sizeof(ExtendedUText) + extraSpace - sizeof(max_align_t); } ut = (UText *)uprv_malloc(spaceRequired); if (ut == NULL) { diff --git a/deps/icu-small/source/common/util.cpp b/deps/icu-small/source/common/util.cpp index 838a201a73d803..56dd4f1bfa76a0 100644 --- a/deps/icu-small/source/common/util.cpp +++ b/deps/icu-small/source/common/util.cpp @@ -276,6 +276,16 @@ int32_t ICU_Utility::parsePattern(const UnicodeString& pat, return -1; // text ended before end of pat } +int32_t ICU_Utility::parseAsciiInteger(const UnicodeString& str, int32_t& pos) { + int32_t result = 0; + UChar c; + while (pos < str.length() && (c = str.charAt(pos)) >= u'0' && c <= u'9') { + result = result * 10 + (c - u'0'); + pos++; + } + return result; +} + /** * Append a character to a rule that is being built up. To flush * the quoteBuf to rule, make one final call with isLiteral == TRUE. diff --git a/deps/icu-small/source/common/util.h b/deps/icu-small/source/common/util.h index 92cdc9ef69a58a..a2be25056e9acb 100644 --- a/deps/icu-small/source/common/util.h +++ b/deps/icu-small/source/common/util.h @@ -179,12 +179,21 @@ class U_COMMON_API ICU_Utility /* not : public UObject because all methods are s * Parse an integer at pos, either of the form \d+ or of the form * 0x[0-9A-Fa-f]+ or 0[0-7]+, that is, in standard decimal, hex, * or octal format. - * @param pos INPUT-OUTPUT parameter. On input, the first - * character to parse. On output, the character after the last - * parsed character. + * @param pos INPUT-OUTPUT parameter. On input, the index of the first + * character to parse. On output, the index of the character after the + * last parsed character. */ static int32_t parseInteger(const UnicodeString& rule, int32_t& pos, int32_t limit); + /** + * Parse an integer at pos using only ASCII digits. + * Base 10 only. + * @param pos INPUT-OUTPUT parameter. On input, the index of the first + * character to parse. On output, the index of the character after the + * last parsed character. + */ + static int32_t parseAsciiInteger(const UnicodeString& str, int32_t& pos); + /** * Parse a Unicode identifier from the given string at the given * position. Return the identifier, or an empty string if there diff --git a/deps/icu-small/source/common/utrace.cpp b/deps/icu-small/source/common/utrace.cpp index 01bdb38e907518..04488d06a0e233 100644 --- a/deps/icu-small/source/common/utrace.cpp +++ b/deps/icu-small/source/common/utrace.cpp @@ -477,6 +477,16 @@ trCollNames[] = { }; +static const char* const +trResDataNames[] = { + "resc", + "bundle-open", + "file-open", + "res-open", + NULL +}; + + U_CAPI const char * U_EXPORT2 utrace_functionName(int32_t fnNumber) { if(UTRACE_FUNCTION_START <= fnNumber && fnNumber < UTRACE_FUNCTION_LIMIT) { @@ -485,6 +495,8 @@ utrace_functionName(int32_t fnNumber) { return trConvNames[fnNumber - UTRACE_CONVERSION_START]; } else if(UTRACE_COLLATION_START <= fnNumber && fnNumber < UTRACE_COLLATION_LIMIT){ return trCollNames[fnNumber - UTRACE_COLLATION_START]; + } else if(UTRACE_UDATA_START <= fnNumber && fnNumber < UTRACE_RES_DATA_LIMIT){ + return trResDataNames[fnNumber - UTRACE_UDATA_START]; } else { return "[BOGUS Trace Function Number]"; } diff --git a/deps/icu-small/source/common/utracimp.h b/deps/icu-small/source/common/utracimp.h index c2819830e1ba52..84e7031da8bc17 100644 --- a/deps/icu-small/source/common/utracimp.h +++ b/deps/icu-small/source/common/utracimp.h @@ -144,10 +144,12 @@ U_CDECL_END */ #define UTRACE_ENTRY(fnNumber) \ int32_t utraceFnNumber=(fnNumber); \ +UPRV_BLOCK_MACRO_BEGIN { \ if(utrace_getLevel()>=UTRACE_INFO) { \ utrace_entry(fnNumber); \ utraceFnNumber |= UTRACE_TRACED_ENTRY; \ - } + } \ +} UPRV_BLOCK_MACRO_END /** @@ -162,10 +164,12 @@ U_CDECL_END */ #define UTRACE_ENTRY_OC(fnNumber) \ int32_t utraceFnNumber=(fnNumber); \ +UPRV_BLOCK_MACRO_BEGIN { \ if(utrace_getLevel()>=UTRACE_OPEN_CLOSE) { \ utrace_entry(fnNumber); \ utraceFnNumber |= UTRACE_TRACED_ENTRY; \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement for each exit point of a function that has a UTRACE_ENTRY() @@ -179,10 +183,11 @@ U_CDECL_END * * @internal */ -#define UTRACE_EXIT() \ - {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ +#define UTRACE_EXIT() UPRV_BLOCK_MACRO_BEGIN { \ + if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_NONE); \ - }} + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement for each exit point of a function that has a UTRACE_ENTRY() @@ -192,25 +197,29 @@ U_CDECL_END * * @internal */ -#define UTRACE_EXIT_VALUE(val) \ - {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ +#define UTRACE_EXIT_VALUE(val) UPRV_BLOCK_MACRO_BEGIN { \ + if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_I32, val); \ - }} + } \ +} UPRV_BLOCK_MACRO_END -#define UTRACE_EXIT_STATUS(status) \ - {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ +#define UTRACE_EXIT_STATUS(status) UPRV_BLOCK_MACRO_BEGIN { \ + if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_STATUS, status); \ - }} + } \ +} UPRV_BLOCK_MACRO_END -#define UTRACE_EXIT_VALUE_STATUS(val, status) \ - {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ +#define UTRACE_EXIT_VALUE_STATUS(val, status) UPRV_BLOCK_MACRO_BEGIN { \ + if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (UTRACE_EXITV_I32 | UTRACE_EXITV_STATUS), val, status); \ - }} + } \ +} UPRV_BLOCK_MACRO_END -#define UTRACE_EXIT_PTR_STATUS(ptr, status) \ - {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ +#define UTRACE_EXIT_PTR_STATUS(ptr, status) UPRV_BLOCK_MACRO_BEGIN { \ + if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \ utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (UTRACE_EXITV_PTR | UTRACE_EXITV_STATUS), ptr, status); \ - }} + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -220,10 +229,11 @@ U_CDECL_END * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA0(level, fmt) \ +#define UTRACE_DATA0(level, fmt) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -233,10 +243,11 @@ U_CDECL_END * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA1(level, fmt, a) \ +#define UTRACE_DATA1(level, fmt, a) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY , (level), (fmt), (a)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -246,10 +257,11 @@ U_CDECL_END * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA2(level, fmt, a, b) \ +#define UTRACE_DATA2(level, fmt, a, b) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY , (level), (fmt), (a), (b)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -259,10 +271,11 @@ U_CDECL_END * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA3(level, fmt, a, b, c) \ +#define UTRACE_DATA3(level, fmt, a, b, c) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -272,10 +285,11 @@ U_CDECL_END * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA4(level, fmt, a, b, c, d) \ +#define UTRACE_DATA4(level, fmt, a, b, c, d) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -285,10 +299,11 @@ U_CDECL_END * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA5(level, fmt, a, b, c, d, e) \ +#define UTRACE_DATA5(level, fmt, a, b, c, d, e) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -298,10 +313,11 @@ U_CDECL_END * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA6(level, fmt, a, b, c, d, e, f) \ +#define UTRACE_DATA6(level, fmt, a, b, c, d, e, f) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -311,10 +327,11 @@ U_CDECL_END * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA7(level, fmt, a, b, c, d, e, f, g) \ +#define UTRACE_DATA7(level, fmt, a, b, c, d, e, f, g) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -324,10 +341,11 @@ U_CDECL_END * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA8(level, fmt, a, b, c, d, e, f, g, h) \ +#define UTRACE_DATA8(level, fmt, a, b, c, d, e, f, g, h) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g), (h)); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** * Trace statement used inside functions that have a UTRACE_ENTRY() statement. @@ -337,10 +355,11 @@ U_CDECL_END * Calls utrace_data() if the level is high enough. * @internal */ -#define UTRACE_DATA9(level, fmt, a, b, c, d, e, f, g, h, i) \ +#define UTRACE_DATA9(level, fmt, a, b, c, d, e, f, g, h, i) UPRV_BLOCK_MACRO_BEGIN { \ if(UTRACE_LEVEL(level)) { \ utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g), (h), (i)); \ - } + } \ +} UPRV_BLOCK_MACRO_END #else diff --git a/deps/icu-small/source/common/utrie.h b/deps/icu-small/source/common/utrie.h index 3e2197eda6c261..532ba778eb6ed1 100644 --- a/deps/icu-small/source/common/utrie.h +++ b/deps/icu-small/source/common/utrie.h @@ -182,7 +182,7 @@ typedef struct UTrie UTrie; ] /** Internal trie getter from a pair of surrogates */ -#define _UTRIE_GET_FROM_PAIR(trie, data, c, c2, result, resultType) { \ +#define _UTRIE_GET_FROM_PAIR(trie, data, c, c2, result, resultType) UPRV_BLOCK_MACRO_BEGIN { \ int32_t __offset; \ \ /* get data for lead surrogate */ \ @@ -195,18 +195,18 @@ typedef struct UTrie UTrie; } else { \ (result)=(resultType)((trie)->initialValue); \ } \ -} +} UPRV_BLOCK_MACRO_END /** Internal trie getter from a BMP code point, treating a lead surrogate as a normal code point */ #define _UTRIE_GET_FROM_BMP(trie, data, c16) \ - _UTRIE_GET_RAW(trie, data, 0xd800<=(c16) && (c16)<=0xdbff ? UTRIE_LEAD_INDEX_DISP : 0, c16); + _UTRIE_GET_RAW(trie, data, 0xd800<=(c16) && (c16)<=0xdbff ? UTRIE_LEAD_INDEX_DISP : 0, c16) /** * Internal trie getter from a code point. * Could be faster(?) but longer with * if((c32)<=0xd7ff) { (result)=_UTRIE_GET_RAW(trie, data, 0, c32); } */ -#define _UTRIE_GET(trie, data, c32, result, resultType) \ +#define _UTRIE_GET(trie, data, c32, result, resultType) UPRV_BLOCK_MACRO_BEGIN { \ if((uint32_t)(c32)<=0xffff) { \ /* BMP code points */ \ (result)=_UTRIE_GET_FROM_BMP(trie, data, c32); \ @@ -217,10 +217,11 @@ typedef struct UTrie UTrie; } else { \ /* out of range */ \ (result)=(resultType)((trie)->initialValue); \ - } + } \ +} UPRV_BLOCK_MACRO_END /** Internal next-post-increment: get the next code point (c, c2) and its data */ -#define _UTRIE_NEXT(trie, data, src, limit, c, c2, result, resultType) { \ +#define _UTRIE_NEXT(trie, data, src, limit, c, c2, result, resultType) UPRV_BLOCK_MACRO_BEGIN { \ (c)=*(src)++; \ if(!U16_IS_LEAD(c)) { \ (c2)=0; \ @@ -233,10 +234,10 @@ typedef struct UTrie UTrie; (c2)=0; \ (result)=_UTRIE_GET_RAW((trie), data, UTRIE_LEAD_INDEX_DISP, (c)); \ } \ -} +} UPRV_BLOCK_MACRO_END /** Internal previous: get the previous code point (c, c2) and its data */ -#define _UTRIE_PREVIOUS(trie, data, start, src, c, c2, result, resultType) { \ +#define _UTRIE_PREVIOUS(trie, data, start, src, c, c2, result, resultType) UPRV_BLOCK_MACRO_BEGIN { \ (c)=*--(src); \ if(!U16_IS_SURROGATE(c)) { \ (c2)=0; \ @@ -257,7 +258,7 @@ typedef struct UTrie UTrie; (c2)=0; \ (result)=_UTRIE_GET_RAW((trie), data, UTRIE_LEAD_INDEX_DISP, (c)); \ } \ -} +} UPRV_BLOCK_MACRO_END /* Public UTrie API ---------------------------------------------------------*/ diff --git a/deps/icu-small/source/common/utrie2.h b/deps/icu-small/source/common/utrie2.h index 75028ee23ac1e9..671f44e16a65cc 100644 --- a/deps/icu-small/source/common/utrie2.h +++ b/deps/icu-small/source/common/utrie2.h @@ -871,7 +871,7 @@ utrie2_internalU8PrevIndex(const UTrie2 *trie, UChar32 c, (trie)->data[_UTRIE2_INDEX_FROM_CP(trie, asciiOffset, c)] /** Internal next-post-increment: get the next code point (c) and its data. */ -#define _UTRIE2_U16_NEXT(trie, data, src, limit, c, result) { \ +#define _UTRIE2_U16_NEXT(trie, data, src, limit, c, result) UPRV_BLOCK_MACRO_BEGIN { \ { \ uint16_t __c2; \ (c)=*(src)++; \ @@ -885,10 +885,10 @@ utrie2_internalU8PrevIndex(const UTrie2 *trie, UChar32 c, (result)=_UTRIE2_GET_FROM_SUPP((trie), data, (c)); \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** Internal pre-decrement-previous: get the previous code point (c) and its data */ -#define _UTRIE2_U16_PREV(trie, data, start, src, c, result) { \ +#define _UTRIE2_U16_PREV(trie, data, start, src, c, result) UPRV_BLOCK_MACRO_BEGIN { \ { \ uint16_t __c2; \ (c)=*--(src); \ @@ -900,10 +900,10 @@ utrie2_internalU8PrevIndex(const UTrie2 *trie, UChar32 c, (result)=_UTRIE2_GET_FROM_SUPP((trie), data, (c)); \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** Internal UTF-8 next-post-increment: get the next code point's data. */ -#define _UTRIE2_U8_NEXT(trie, ascii, data, src, limit, result) { \ +#define _UTRIE2_U8_NEXT(trie, ascii, data, src, limit, result) UPRV_BLOCK_MACRO_BEGIN { \ uint8_t __lead=(uint8_t)*(src)++; \ if(U8_IS_SINGLE(__lead)) { \ (result)=(trie)->ascii[__lead]; \ @@ -935,10 +935,10 @@ utrie2_internalU8PrevIndex(const UTrie2 *trie, UChar32 c, (result)=(trie)->data[__index>>3]; \ } \ } \ -} +} UPRV_BLOCK_MACRO_END /** Internal UTF-8 pre-decrement-previous: get the previous code point's data. */ -#define _UTRIE2_U8_PREV(trie, ascii, data, start, src, result) { \ +#define _UTRIE2_U8_PREV(trie, ascii, data, start, src, result) UPRV_BLOCK_MACRO_BEGIN { \ uint8_t __b=(uint8_t)*--(src); \ if(U8_IS_SINGLE(__b)) { \ (result)=(trie)->ascii[__b]; \ @@ -948,7 +948,7 @@ utrie2_internalU8PrevIndex(const UTrie2 *trie, UChar32 c, (src)-=__index&7; \ (result)=(trie)->data[__index>>3]; \ } \ -} +} UPRV_BLOCK_MACRO_END U_CDECL_END diff --git a/deps/icu-small/source/data/in/icudt64l.dat.bz2 b/deps/icu-small/source/data/in/icudt65l.dat.bz2 similarity index 54% rename from deps/icu-small/source/data/in/icudt64l.dat.bz2 rename to deps/icu-small/source/data/in/icudt65l.dat.bz2 index 962fe59750de58059094c56f2584c575cc956ae3..f55e9252f6da9b5319d3f693b6cfa9df0d3c9bd2 100644 GIT binary patch literal 9881112 zcmafaWl)^K)92zA+}+8txI0O879i2C4!!;~NcyYhfUY?!NayG*)*af6xz)Ukb~c>cxETsH7=@5txr zGbNOK#Z$?0>$-bKe5xoIfCNBY^*YFW_td+w15H~~eRc17wHz0_irUB!OHK~t>?VhE z?cH$|77rE!08o~*;b;H_aF?*It!|semlKuiwsI0vn^&$0{M1orjH`z>*`dIMt6sjR z?UQ;~)WnZ^<8RviF^e%1rp-9^idX zuq0OR!ar2lE%czZb>BTQn!QrkEnqy^9dr2TYLf3M?CR1*yy4uQ+xMgy`m!UrtWmt% zt~gEc%&(&I6xdch_ptricLnV-qxR`;hdA4+KFU5&R9ns!xO>gW;Gyj3U0w-ctj+k(-mboE1g^BhwZD#C(?lSj&=xKPo^{vbBo<^1esO*7^*FQ!9EWVBbvH zdn1SRMYv{VBdQa>&2I`Ie}t)_QeY97iW1RphxZJ;LL0M{i&0bZJzcZ!H5S9f%+rT* zYs-fi>LpBpVsTy>$_oGhW-$Q(%$Wqk=5BA`7d?b-}#L9;yV}xbC|<5!fd6 zIwMS8eS+op z9MPTUWI~jjh_9e#G0X^d6d@43JP#h=~vUgBwL{>ihKFH-9>|j{bxO8t(tu zMSL0?z|lmnT}Uk(6O2L|68P{aDhd#10!6|5BLq{muVQz+atZ>l3wB`Q+i;gx-~Gi@ zRoyDO&JtjG-+cVq#fSy~DoFxW$c*d|MF^y`y^(P1vG=Nr+H+IgL2_>sTdt2~|Fwo^ zC6aXWve)>e*AKRSH?h{8x8`Ji?Gf60xnp<)@CuX%Os;$hbQLn`J)dUVDu4!)jGNp} zxa1GT?CEES&8*-h%~C_b>Y7!Z4odr){2OqODB+U-RFE3aF5Pj-<_!OFBlNIuVG-!nz{3> zdyjm9j0!Zx(x1;7V1TfA$SjJ|j>|(Yt-1KNVPA(oh8e&PfL*wD?A_a*^Yt}rY*x$* zE12*Ur5=p@8i?&$qtjjA+uIgZ1^MSm_q>$Y`tNy5FvV5@&gXo+!hQdtevPJ1Sg`SIB_uoD6?rw<>|t!N;M#tm5$C8 zsNogr5CYBQDgr{eF2Lzrc!3;Hw|T=OBL&6>!G*97d?nBhW=KvgDMe3JhoE8cMessE z5$foG@U8B4ANa7gt$!!E=B^l0m5t6CuaN5l8!L(W0@F9K1Ms~eseXl#Z zzQOnYhjJ?$f?lMh@5BO!3fvq%W4#F83-rQzi+u2xM0cNz?lIT-s4(;f8+dvztcpB~ z9wqr7T(Q=Uy4%YQ-KeH7%>Yy>VaH@}SDib6QV4{hXeQ3^+E*U{Sf$$f0{f8*_c%tY z7LD1`8@@GW9!8f0sz6GpFMGU(eNF`M%T_m3u!W?*g2V_DJpHj#ad0&&|5-%?L{Q}_ z*+Xtf{x9745w`Ef#h!W}VbloQHyugayyQE&JO7Lf{Eztol-Fj+FE6uXJ_63?-3Zav zr|8%wcWA+}n=FPDd|}v5Vm=Q(PcEh&-LY$1eq9eI8LHGQmu}c5*nPWH6$FqfC*-DQ zzzgC9rd!Ux(N4G2ph7Lcp&HE zLec8sSHB-{M#31wfq|mF@27B3FZ>9$;=dzbTUNubeK!P9*7ySMk)JAt*k$V6{Os#_ z09AOv0z1ExUK-K=VE=bw{D=O{29>;)F{mP1zl`bB@9L#(Q^&g1L!t5KZ%{{vkDvp% zy!%Os<~{IVz5j29((82+jfYrJ@NXa*(#wN7=j|R5p#hPNo;xz*?#8a83b83T9|SQk z7dtrEX0zk=qfTwbsCO+ap}-FzZ+Zv}fbsD+lc^KuU78oHK6(}qu2gO39Wh2iAshKm zTrD+^`2g=k)MQ#2X31bs1ynMO|F*4+gA!jUO{1pqf~+n-klJ_qr8D08Gpy%*&93v6 zt;U(i)^7gVwyBz{eSpQIyWA=a`Kosd-z9yOs&^>E3un< zTmu)x#I^<~LV3;l2GzRE+y%zkg#~&NqDOSMzkhn_?)e;`uDouFX3vpV%satnJ9Y)dc5wa-os@yc=tj9cRIcR!|tBohaZW|0EBB%kB75e*c_k& zCEzCSK>YGvZU7p9U}u!)>EbVlcChZ!L5bP)*(Yz;wztpnghZh3N^HR2<^Jvm%HZBo z!Vc_&hc@6k7^b-NW!wS1Qrw8C}8|#Bhf`I={ zPTvjw>opT>)i2BqFfinF|FnIui@c5mYZK`V#+=zPlnee(1Qh&-{dYnR{+}{j!GG8P zzY-|;|JD6B4URRlVK?AiHRb3mt1W;C-dpv~{{U zF4EJxd#Yd>L;wKHehxTAM8wM2kf;ayBHBEW*2trmz;_9|@e-$CLet>Q{DsMo;oTb$ z68Yde1`g3tyhzKzx&=QuXivo&U~{>_8=F{EcfoKpyS>M!r;mZ2XFqKN&!v>d5)RMw zHpvkN005rt-Me={Ko$CyqwxxCtlgDC>Qvlg0RH}klx1>FOn|RD7+PGOmvnU&QCp8= zTO4r>rLq$)Ht^|i|A~nMiZ{vE>3Z+T{wy^n1}*RMXKvkAeRU0Z9inJ^f@Q4&VBxQR zJ7Q5QQ^eEFSCeUDdCMfO)T*juV^fb;*otM>f%!M>OONCx*D$fs5zos-sym+y&vMu@ zY@RxB`=L8hTWsqD+RGu*+19O3fw{=ve6{_W$NG}smhW6x-d-=@EB3=60%NVbcOhpR z+6!}cx2;{YG|OD)kB6~dO^1%uR$rT6Glz=g_BIb8nCG9M8@E37D&=?Z!@Qm%53v51 zH}C=wHer)uM>zNS1I*hZBYJLm*UoM3^FLlpM4}?WNi^_`4S==dVJzfHXHIe*Nu-QA zV>3jxHu%`0sZ~29^`c;489BTp2mmB9bBNn$1`rf<4LXej*^~>=Ytzw#?;EEdeIJVH zK7jxeZL^%)WAHiMk+t0opxy7Cv2~Bo$mMI3y`%52?K0|sr{=4@fc7YU7_45( z5|#Tnp{S^cc8G&yRsebcZ2=r7ycrxBCa*P*7FxEN6jLOao=HuiEUN%tfsc2+D>U}azFb*7o3IG6aUlzv{QtO%E1CWW zzmVH3PB~6WR!W6L6Y&#Ha4-OI_8)Y3tAFf2lx?-33~!dHf(%BE=N$*w+5NlVf==(!sk$+t{&HsA!kOh(0Vvey{1RD4IoCOK zlMYw?JhZ8&L=+ruL{njiQE^O3yW{@dT?2=6LZ&~`g0s)SuADfhM4`2ab6*d(EbxRWa)rujLzBQg}uU0(& z+r;)3gOxhBA%R0LywmCBCdind2Qi)g*=D!#X zEx*o!2Pw$y+g_|I_&q@m^xWFdCTAq+C_H%HMGewq^TOuTdZjLFXp~A1_+iKqcH49h z7h3idX$r?)o0-Pxt`isP63A{J8Pg6)+lg_hRu=lwWb2ku6{8oetjtI&>aB9jw_APJ z36ZF=-5S``=dxi|%*YAJJ49!ukh2nxbE7oY!U`)JV*2do)Cr3^b{5T5ysUsnxG)s@ zl)JxS4J%FhA(SvAN#{mo4w6G=$B|G_t0R-!_{GD_wv)z$RiMgE5`1g=*_9me?ej0w zp?TcJe8j=}zbQ|D8#60?I1AmGnXSI606!yjx-7@oqG{V~H>ABtGpUK?qtbk0Z7-6t zsbOTQwJmoSq(e+!QL0>dN$Z;it>?WwAj?T_U)~NnI^oJ{DKnTyK*M1lu`NZjnD1L+bhf;wBDu1$yA}2ED%ED} zz(-$UNI^PHB2pga6bp|`+b0_MAWatMexx$r!=V}fWx=GPPPZy0@G`^WW%S92r}x)W zYC^IR#~F3lnFn%5XB7CsWd)Q{9nWXz(cU1KRIX7G8cmh4$*eh`rFikfK#-YN)3aRh zJOZ=?)RCMg!N?1^Bog;@T$Wa_LS@ZVwlqpC(Bj)wV$#2-TAm2ey5%j2a}%T)1Sey_ z!%L@ST5xUfY`;w86vkE`Bg-F`w4}|mHhp7iKf5`DWe>_tCyXa;o*4<;9A$i2_?UgY z;i(eKf(xXV?^n7unl_wewNWZMK(%VSH3?n)@bK3JTxVh%n>+f_^b*Sajq#TeOvFLN zO_|7xH7V2ze9smzsr@0PC{))L({R-SbnZytkhz#*%x^wq#CbAP*?jW7`%Up|jQyI) zIo|Oy@4119-wPDt>Rm{>ty0J}0q-arvCX6={_wn5mr_FUCsSB8rR0q1i)yamVpEqu z>LLQEU-#{DKk<2Tg4C>{Ql5z%wyp3hJGU@@#Y5R2vN~#(@lP4I8KknB3g+1US9;tX ze2%}W*!ne)H$#YZtWq{3)Fz7p706cQq-r+nKE6Lql{iF5;n7jm7ML{Jv|5$mthVWD zRw7PXexgj}jcu+o8>yKfp`q2%5{dBYvXc*9{hFnMn}U3u)byZta@(Ekg;;l7h3mDh5J@*qR9!W`|~pcggaYqo{j3HhQM=q1AC^T+Nt zuI!J$`X=6rabGHyD_+LS~M2a&32-UJ3sG?i5HN!;UZ@Gmu7sN=jZX zb>!UWstA2sE|5?$)C9t()Zct%SM}ny&XJ9D`=`bvKEBVBLqhNO-wdI@Vjq{O)&88_ zZ-4(y_J!wf&X#WJF9Z%~{o_LbFWDBHHSXQt6*y12H{^8?kgZR0R_1X%qn6B$F(&~Nks39nuXA>90P^#*buDOba6fh#hAR`b+qr=048GV#0 zcREr6k2a%<8^5=u@HH)>s0r+Jcy*E6?NDQVx9aYW%FQ#5e8yP%{^TVFxb%JCl*af2 z{nn5l?<4f;`~%xWW9U1eght5{A;)LLnA`XL_nou976Kh{YJVSwqFlb$^pSCZza9*| zclb*zXM8sm>fYxQJNviH2!UvJ6 zB!5JQW|GB2fN*#vX)1g;pR}#Lm-xKHk*cJ~6tlpqNwfvDRQRAI8R?12;KC|Myyh&h zH4ZPlf5Jt_ihMxJf~YE&v+zB59A}F_i_f$$CdJY#$uH<_)#P!DW9FqG;3 zzx7n{@(M+b{*(O|TGal+K9*yRfs8lFJ@(L|Dq$Tu*d6^=qvG_V%!zvrqq4@ZD+c~S zu+sHC)Vq)9iQs9F1HFLu>Gj8_v;H43ab?9N%wRL#sU$Ey-r+-6bWk! zp%gxnab~P68Kh{Bu#~6~k_?*XO_1egD4HxD(NFh|K0u?z7~EuJ(3RW+;@j#{|ow|uF7+>*(!UGFy@`kWvWKhpq6;rdhv=jst zKGE~vI{o(W_fJs2RsAysax(vC%O&(nOcH=Da)CVIa;057+FhR*x1b_XMyMhR)l0Myj8N5 zWEc&cY5I)Pn&*V}&TLvGGMwVt(rL(PRh)Z;>UI;-W!dVp&OBz(4e!P?nN}3gbM!21 zRzHZkp$Ucqd2QxX=OOH=5(~0r!Cj+31KAKoUj3L+P&E^uk|LqEY$hZoR)!4}gU*IY z6VEJJ(Lya&E)8f)T}k4>nNN;vZRfJKSuR11(3}q*Ri8I4D2oA#A3RdejNN(Wxt`p7 z$jG_xbIz{nuXle8JPeI2gCJ%f^$wRR!`4KMX6V1trt6u+)93a~?V3T}1FJHJ|jx*SKb<)YN| zPRcZfzO`4?atM1p`gbSmobzH%?zdV$zU3`%-jiW`-1QPBFCFiKP93d4uxm%EFMEQh zSE2bIRL))f6>fgJPuMa`sG%9<-%t^pPh%CJQO$E97~x*#mDp@=ZM}KB-C#to3b@#_q;qGQ3W%0 zc$Zg-{8bgR7|$7J<&x3OM@wehGgtb(H1CU&>W0!mn4E3+nseL9&Xw@%2S^N#rKw+A zcJJXAE9BtPgq~t52;R7+4}7%sa1L*`Zk&yvTFsjIEN$ zSDiWO8%k_JY(>piS8+}WX+=0hYq60|_GmYoqKO^p49ezANC=_PlJM&YQ>5Pz1iq0m zX=|sUmjX-5B8rX(^~lgQz*9P*@N|IaQ21287$l>05F;Cggp%YO2mIvJw@8&RW_9&3 zg>9vUR|j8W%H~D_O&FD2LGAec_iY$8z29NSADxWkI?8g)(wNJ(obX0Vo<~qGA53xq zKYqdT=zGJ=GSRjD$@0qi^99p^er3Lx(RMA-8mkYF&M)2M2Fv{0RM&gnYxQ2d!x} zZMf8>h?q#}l!O3$GV9*_#I8v)SQA=<*w4J`bS&%GoCSJ^Ctz@elXtu(O$t{5Dr%({ z+pb~-504WY?b}_k-p1!pbvEiNggRooU)xWA{+{*al}};orqnJQxUFkn=jQX9Tr-D{ z+_*jco*{N^IN0aAT~!q)O|LXnr($f&o@U%LwvEtB|2@-jubQz2qpOAMFLWxJz1e%sy)0}ja9{sCR|%-{Q?I-ryjG&VzKe|zl0b~7uNr71a!n60tZ6%5 zZZ&vWftzTJ7d&wy`}B&5sT34<7eZ4sMVD>P5IMh_N#v(iSg<>Ty%&g@ zfN=0zO~i2Yr}4?~sR(FU=5MpcSjV78H58PzxX%*Ul@H%VF12K~$+ynR^FHe|U-jNi zH>-yH4k^7CsDBYab`7vh$=j99fz#xx+U&jBFs#ipt?a&iCJ`9}J?Gb~E3@JZ>(oF7 zYJ+ir0Ox#N_aUhR5(r)_;k);{WK{$qo3+620EvpE7rF zae3$(Kj(T0h2;~c^vQZ(!x=l(91L}Kw>()k9|wjDwn`kvk8SQaXSBt#5PpUl^_i`% z`3NnK)H|?Z=5g08XZQ)eLm^r-iEK8lx!-f$9n6%cp%17H3HPyZOTnLYtG0E3VqB4U zv}R9=8r$z))Y@^9kZsj78dVfc=$xH{Y8X3rjWKOoH3t`N**pILvcrIQsdI!`j;x5s z$R@A)EoL?>+CAsUico5Y(!t%jveMj$S~K%%qAVu%jNMX{Zv!ZT14!thxtbx)gzuPt z5~G~guFuap&{9Y(LhjI;8g=9NSlcl8t*xtr%gauN)?La#Q`WIL3fNlod9umrsWiKi zc-N$kQ+B73p|=7sHQsW2o{YE<*B1vLzx@4-&Y!QBvUhDa0+fwCzN{T0Arg2=z0CaE z4}ii#JW|1%%`q-qM5!{V?ceN{u{#0i4-dw~YW?0@30*o}fvPS7GqHg~mX($EzQ;fN7$%qBPxnjrzOkAe z>%Kqh((!d~Lkcu|V)Y|W0dKECA5EG~RS{8{&70gq)#Y8V1HL+2SQ{jMG@$wL{VN(= zG_&`V6xR3Z)-JEG<^}Ac(a(eHmnHRX6%XBlmP4QrX}&ejeO~20F`v-I6$2)4W2Nq} ze@;IgD*oSFtQlsM+QNgGUHozV zstw@S7?J*1c8X-lfF-qKf(eY{&g)Z!36jr3MBwFC6Ir?PN?zZ-x#37qMROC6ilqg1 z2omF*o9Sw+w#&HV7@5adbq^C{X>Ks^x0iA}7mVC-{@i3%(|Cq{8S^=~sOw+&)q7zG z`j9t-d~#+Q$%2mH;Wy=S5l#PksKhwAhQDM@G0CC)qo^K~t# z8rNruwPxJqDHKzhnWbYiGHE<7D75f0@L?ecTb3-rx4$J&THOJ~}DB%Fcn4kI2(X~0?w z@~dLjtVr~odd%R)TW0Ud^h-wd#-2HA2#X~F;L7+FZ+K9H@QgjwTB?Tcc@$tr;^8`P z&yIPPX~Y${p%O=q5qX6uGmpyQB^0PazfJ62*QAhNcORbp+WXj-UohWrmlaU zZ>!jlqH2+Kz3MrM?JOA$%GoK-GRUx`CH zl(rCmUg^5%KAh`a;uJ|9!-9BpXObma-35wu_x{H;RKa57YW-;6VeOS{l7SmJb$iB?f_z+S4Zghdrh zoLflJfR=&@7BodtAweYxrC|(v3%ny7M+T6f+mZntL948SqB&?bUNG3a;FB&bgsdW> zRi=QA&|agoC{?qH4-y-J&Zf==VS_}QW5}mz6vQL7LNp54KoN(uI9iyR%VechY(Tc+ zVmr_}8)qd1rxqtq^LOXQ?C2bNrbOQtQg=qLR?Y6_D0v0KkmMS_8 z{$v?Uh8zVc@Oy0rm56sp{E@SCk>RP?IMuCE=-F@t{DUAp%p#|%(kg;zh-{HM9Ihg$ z?2|T8v^Fn;`XE1TJbdD8;yUs$h-5wjfxn`yY8`bhMMf`V4+jvh$uti)3|LLH)k|Vp zSBy+9Ed*twOB>Yi0wK|bgjJ=(Y1;qpx$&e07!uC7z<6}RSQ=^6MKTbhjyxN%pxaVL zHXIBS#5LM-CM1JQ17kp%bkP-?1uZQ|wP+zN;|`&`R%uGAnvsfyWCjLAIl=6?O4=3k z%gpL+q4TrW>!A_FRyCSvpMVk$T{H;M$p{pP*x-*6WaK>sotQFSAz`L$p=lGoh99TB zxU)UAr5%zo$VM}?yss!HaePyKc>WdHOd;?5_*zCA7V?JG=yuYcd4Em4-@XFNZzIw2 zH~08XIab$)uwTQ}x=lJx_mvLSZl(>_UR^bb=2JJVBCv&~po&k0x1gY^pjEpXTokJf z#E=XPQDkF7Z-Eb;MaR(o_r%dmQ-pxhBB|IS#EX7|tXSVJw1$M5gw zyaSoH_6hG-O0QP@CjYkfck_RX&w?vsQV^1*w^j9OX!=Q*9lL4$YOO4A^M;-l220A( zwwS-o_T_){?Q3uQv;G=$_RG--{WCkFi9ff2p>|0dYe%Do5^nNgoSl6J8#9Cq0>4LC z9Z5!48Z#HpR+WKamdX_x!zP@iUD_I6ZTAUzHKG;QAr%*$ppA}>28f}Jt~t+J$bh67 zd;G0vGy+aSu`LF5wrCazpDG&@3PB-7uL!LrR06lEe3jRnl@0lXAC*s`K(8r<#}%E-P(kZ(%&j%;3~6%X}l0eXCPh zz$Ikv+4H5~)Zg_oIt0!NYM6s-`|Id~NDlsOje?b+@zaAz^@uzA{R8u#8l4ss1CjT$ znJ18+j3R!L0a?Ovb~qtp#AfhlPzrrhJL0rIkC=lf+tw_^VvBd*_b#qYCtlxd=P-I|<^qD2XruOx`2>X0GGEMKxYL1rp$(P)TvQF@VP%)cco%KVuKXv^KhXHa+G z)J#h*b7Pe%lw{P5WO&EeQZ3WAM3iPHuh<6MjCGD_XO<|5X46u3=%k1XC5~c1@=W7S z(~yHNq=m;|d`II3R1O(Zw%F1a;!l`M82y>O?czhkx+X;KrjX}(cIo$(JdW84C|Gi0 zmuT3dbDfrL&h%1QUKF_&eDVX+rPZ7HG&*#g-R2=+>}tY?;GR-I3}-`GO(FF#ngKl^ z%Tlo>>W@i)XvQDg8}=_*=fe7jaf|!A6Q9D^<8H}L3* z>G+N!nYpIjVzrV+5WoFM|Y-)*Zp~jl27Y|4LXM{r4XdS7Z>(iZMx@ZD6%qE zlqO0vm?6sgg0Z)mpMAhJUeB3&<@eoK-FFQRm2y`SnLs(Z;#@&KO-h=CmNwOT9z)4l zTNaO*QHw^FE-uYObEzd+LM8?nPMB2ZL4*q2$0ufAWur@7aBf!)*ET05OASw=*FcO1 z@hX6Lr8OjJCLnkfmXX;e`~cDgRzy7>q)DxD%v!rwPv!T9T{PTy*W8RM@QAw?CImob18V(mZG9ZTh`yczQ9Ndxj_MR%4`9$1Mcbe0Uy3isUw+pl77Kdb6cs z`T2_`rcH>4$Ej=VjOH(GMw&QTpffMiFoo?yG4hENTb<4E?N-ifY_jRZ5D%^lLB_uX z+%EdZ%SY%RLu>p1#hV2VD<`-*R&xQJnxK0pM#@WL-M6m4^{stDGn!+Fb+XAC1w6-P zdIW1Oo2ALe*UG4|?AvlEX(3-7SmIVoU3w{XPuAYLgPsh@y|}!f4GT)>e@kmM5Gs`o zHkBDF1>;hqufFSrjYp@OY`KmjHd~`*ELtejiesrY1ow2 z{`z91V&-zjechQ_{B-#Cz)j3vWGf=VsH^OI(ZF|(W`8``TLP!z~_q?R>+y6iYL=vi|~f2b!N zF`MS=oeKIUE6{{>5^Nh((i6wZQBrk;7Mm(R(7;H@5vxyGwa(%CNMF7jrsc@D@P2+$ zjP{+Fp|xA0{*zRKm*ksFFISPw#qgn%mC98Lc$g4eR9(%zhc7ApO*$DFjV6RqBaV{{ zH+w_+LvLi9+gv1@qL`OS7xr_bl(r&%($;4JscH&Rq4LnK?3&Mltz}#D`ogY~Zu_D| z2j8svck}gCfQ?CF#eyFR8F>S>R#7+YKtW^e&jzsIi-%UV*_fX$Apj(saGFt74U?yL zBVk(594&ayy;6TB1q)3nR1EEpMW1N0Bsgh+euHb=QLN#HFL5KQsbDuYN0vBFV>( zIY3S6Zofu~w#-oyG&j75V?LO!E@fd(Q+8A~txf%M%>JaDE!jCN?iS1LSf7re=9)8UPVlJf}krO$CNDr3!d@7%KWs2K>$v?y&4Oo7^w60ZLI{ zWK!-C@vp5VP@`{k#F6}A@?#BR+N7^2R{FALp>aHMK#IE0k7bTFbN%Y;EJH@e>LYO_ zuELX-upt^Xc>*=jl13n*q3#*UI5Ec!OAO)B*gCo!I>x|GWbjAO$wFD3Gc_nbh^sKA zdNE3Y%Q{(zQal~(ZWJz2mR=Nj?>1&Nt%jFi$zHG`jR?n!Up|dO9mHJ7<4UfP9+(x$ z2BDb}qQg3K!c|P%Pk*PHwSAP>ya6SPJNobgBUh1K1Wifpy8l3$wG3H)crNf8uT%8} ze@^#hub`fwaJ%H@Wy>||o&7@Q;r#qUvls1Ql~u`e+yj5$Pr6KOr%_Y77X)_6VI7}warb2w)K@=OOIF64|35w+cXd&QW z_f+>ZRL_zZPdX_Njh_!OAfxfqnDd7hXraoHWPp%stMq; zTM2j!MkX=CpnI}&=_HP+nze8^aWYk zXiyJDWZ2~IK#NabG1V@vaT*(^Y*+ATQNhpVfZ&lTdvA$bi$v zR(*l3Ewa_EF-C#jGBX@bTRPJ(_PL})H)_FdF`UfhzEPjF4MT$(Z*YPey;P>ZJeG13 zMvD@eqYqhMU80y<4>~wFK=|rbw`u9yj-C|95etXkKLaih5rT(MIfqeJGAZLEM=X`_ zG6r1LTmNUM}2qp z7qTEnRWHkb5igHc-Z_7>4zLGEOUGWpUFY}mvcL zL|h-?QGi1E@U8BG6_B}FXcW^3{bkZ-E{0rV=^M{K`R25#fe2f!PNwPcN zpBwKCuEfLZGgzD5x3=oL_2*`ex!;r_L7z4=%-2p()QQu`28A*b6a~MR?`Oqs=C$a^`i8462`>Tfek)>7iA@t&_<(X(c&}SYrfrqb zhM*chaN9n!6v$QG&iJlQm3Xm_odwQEd+BePd5113GV3|L0e@uX21)BIAWA&+QIpHW z#Fix%KAw$vKo|9Na^P`uz#LAhj`J#Cq9b^cYoj6ckA^USECf%n>2E`(XD!APZ$OkQ z$;mHClVkXoM4@dtlB3X6BZx+X#vWWD5ym8|eSB-en03Gc5N-GOXa&~k(dQ>wJ5nPnsM_~P}jMQcB*!RHS%Ru@0!V0iauvT2lYGQ0zSW<04aw7y8HdNw1} zV29MxO0Ol{F>5T%WM{P0DjoCik=dH_wPA{V(64&g%8oy%k{Rv9qKqOfel}bk(|;#0 z@k3aJqEFLyAB#sacvg>{KM2>=?k8?veqEk(Gw=0g?v#7MyTLGd`BgwLMvIp!_AdKd z_Jinxz*{Q)GVo3myfwzagq7lMAF?`7t zuxv2%;7{~5Y#!;94d0$S|zh1+?OgV-I?bZ<3@F<8QDxX!DpKu^QKg!<_)5$M2 z@z4`Z^snh}S`QSHojGx#zN6V z+qtUczqTkK4xYkGPthO0Ncu0FINVQ_J-3h|ep!#12*c+%dp zxalX&^mu`HHG$HaoH=^L;{;zv;2XpaA+i<#A)q{izFvnttMtC@*kIUT9(w;US?Z(= zuqxM5lCJHzY+}=})>F@uL0_g=BYCkzQZjr<#@nXSSjmb1cdPvc0t!}rutfHT7}bf_5u1KJ>sV(e8CFE=7v9cH|I6YqvFFZ<3Z$?K zt&CU_;_l@6uTGK#4o0i{bq zlCSDY*XkvjQ&?Hr?64*`2e~TYIeqyPXq{@&?-+J{&;q@V2cI;B#J#< zK5(U-V#HPx4wKPSjDDPFT(pb)LjGarbNKusiHUExTh5_PVR^II{9n)-dkVC_9qM~! zBxv~ePqAgBR~YP9@7d}%p|4zoUV6G4D?=OLZyPrxm)U5W z$|v31yiwXcrn-ARP8Y_&$O>lT@MKZlV=>7b(fxCCQ{;B9ty>!D6S)wL} zp3DALBp!IljC$Sf%ih1@9Nud+Uvk}>76IXo%6*P+%DwzKP42zJt~ER6Jc`~kd8CB| zcw3aWgpP&LnI(<35s?q03|1yj3x2)kM!fe^n(Vdbn{j+qNlg_RW^MUc{i*_!asU( zW;G32n-)BDFsyB71i7szL>)h(Wq9CJ5$Ul6I^?$w@~+V3mvNVd(h7<&dSog8^o`MC zn6+xmQ?MAEeOU8gkGtt0arf z%6H;zOsJU&DV|%>c6ocw&iF4gUI#?tie>TNlC%F91zH4pEh=d*_vb68YlU{FDbOD{ z>Ixq)#0qi~tR6+pKFL~GAIi)tPm<9hsg`&7wt@0g9(ZQ(d4`VgzYT?fifkx|HGj^! zxcR`6SJ>jy6|FKeAhAtK%%%Jv(DNiuw699loCSdK?+q*B7Dqd!4BTm6MxLf^sQmwo zYZ+H+Xz+bw>C_$&n~HbtR8hU-?aJ0Mwz%3(3t4frJZoG8X?a+ML@s87Ff7Wm6>eqy z^m%nT>Xd9tr}MNUXVl_y4qp*=o6Y*`+NM00ZA>E3`kn9WG)|DEY!g9aH4DP+ zfIYQdTXbjia)RdX=*ePP>lI&f)QSQaLvWf2L)c+i-p4`90uqetnoBL{v~Av$WAbgw z4At>&k{pZ)F0YU*a2V4Ou70hayN4Vb`k%*)EXTeg^L6zNDSoGl@FlDW(xM! zRKN>JZE914VCN|)Bi?K95}>7Y(se|lpetP9mSqF=f_K#v#5BWGlLdvGB#(-sgsQWx zA|(BGv>dWS%kam&*-Nxr(=Xux<@cw+^yg%gq3xZ=U;F(6>n(kYMLY$xh__1d&l3yN zRy%N7H)K1(YbqcGEv|2!yzfN2bF?NXp)}i~%QWVLDMog3dVV9i{gSJ)wZGpv;LK_X z^szwRF`q`o9c$19cWni5Y8L zXu4u_wURxdta`9Pcqkn9@r|RDh>+;JNqUcS>krKt<4-EDrtHcAryYqQ*N(5l4Z%Yt z_HGBk&W&8znW!XLB9p(jaYOuMCsSu4ElohE)uK3GhAuR}(hj&s77vSC{+1PkaS>nz zvK#k0N0hAn5^s3@VS^pk*w(|e`vvC(?=LjlNK`-tm?(1okuCPE|A4>irnrP3E{pdo zbE2lj*IdR(!p*a0Ew}s5<$l)p-2$J&k6=7hB#ne5QI<2~$0EiN-E~?jw&wjC;>Zc^ z1>bsJNxS_Y(tCn*w=N6E;_)Ovi1c5`&?USOQMI0u3znFbBz+ke(W4h+XjQZnIa9J^syXhTkp|K-SQd$(NKj!fOP(1p7mB5P%x>I9q&+n!fky#!I1tDk%nt~XDu%*y;906aj$ zzwSQY@b5k+Hm~^S-#;Gfsqp>hyw#!((~*&(NMbAlAj`!cGl#DG>&LR<#?m#J5Zw^S zTA{lf28{Y1X{V}N$^M#MDKmPZ8HyqTAO|Z&G>`)cE%8yw-4wDU*1C$M7ekF))bD%8 zl2^ao0E_TufgJvSF9b(K5SIOe0Sv5YTYQ>ugv|?qCcsJt2mk{J4SSnf7!9VzO;!g^YW*sEQKXvE46gX^JgeO;J=Y)jnJGz3 zzulKBWF{vrDdSaA%SZw6Ut*80$piEE-VscR;EorC3HMmNUD z3mMHz;CNTsh!XcdWBD|?tt5P)JsA#Tj-;73gb(GC4fEKuBMBXb=rSb+k+!TCC>WXn zj7Aei2~NeLbf0O-R673daUjSgZnW*u!cRY;roJJQ6CsVx!0vyQB@?)@!SM5;sXu(ajr6s6_z@;Y##C8a z74$WcS(I8;hxQTldMw>r;*^8K^%AIbem@U9I($Q-K7~C-W~RK%*r{&m9nRcxNhI^= z52P|eSV7_-h~ns(suIdI4NJv7J6-9tbuvGf>e?ow&hu03>Iz||!F+G%6uW!4W0NfPP%Di{i4rkZ6SlQJuDrdYZJM5s`hLDWx0^}s2Y zRWvA^=M&DEJ9cR%W6J{; zwk351ENQmRTPxo98C5&6QObuNfkjZk_d=K>GAoU&fYhy z=so*%YB!n{9?O#0?`CU>*<0bgt>w&cJQQjuyWH~LpV;t+p{quG&aZLg2=(`ZekHjvsn z*(!l*foUp%L1`Yp*Nh;LES8ESE@5 zqV%mSPJ(R8sxdBzGZ!x9#%_#i>q zMsSiMTvm5isMtX!N-7NkA`jQ$d43-H_}Ra|-=>CIXPMZDBoygu#{GUZ&EP$(Z;eo@ z#|M>@7wC?MK?`@>N%)$q(DD{rWhwWzZw33DhSEtQbKH^$4$@;-1F+W|4lZmWINl1L_>v5(#tPqEx^ z25ld33vB(ln2vkX0JrVdV3&-X}}Yba`avuEz_b-@%)kZ5|;oDpG`;|YOqaYzoKFW8sK>1HRl%Uf(W=BoZL0Ox*6mwpo2OaI? zapV+M<8#2tYa=DmJu4)b#HFy2Rah!_ ztkZEjS&OfwYF^f@TN-DK^4bG&1O^Qs=YG)aHoKi(2UEar8uhwzuYORbMMa-3LZ)@9 z-dz>;l#!>Z$7efM5viDg{uENiA})H84J2)iaZd1|N6^Z801QFk0D!~;@lp{nK(*l$ zpEh}e->Lx`P}ndUD>D+HNB{=Lsn}SFfiVVT!dj@4LD>k2NHGW&=)s0<{*AuD*^<{0 zM8T(}NEkFcy!69FGdD$W%X_lC-7eGWTjd3ys3!lDSX%)sx3GeUEoPB1^sGxN>>0jN zsyas#YXxxPLvGt5E*#boP-VfG!+HkUa!YONtEL+)o|73$a0#+&3Cqa&JPOg_Lq9Dj zA*~~T2KWW>xeVjD79tk}>^2DVc$(l^#0k2$8O??X{4+XO;|_RKQh4 z6)_vSN`b7%(F__!X@Nmgbwg0n11vlUq^zbOOJ${Q>0|w;iB`d5)a<1AkbEa{Ub9oOhI~j$o zyd?cqA@iIHW=EV2x>M+B zye`ZU@Oo}fm~C!;=ju86_gGa=Qh&ETaMD`Euxnn1i8RJG*w}_W5H5C+vpP@Sr3QDN zIEF__`F=q?$)k!3G?TkOzAGJjh8k=EWmwIoHq?ABOPA$xGZyc27}kkoHG8t6->lXA z_mhd9S>s^y7PpcG4YVf6GxbwycB-w-f;Iq}4Z7qN7+g)o>);_o^re+&HOY&t=cu7G zQ2`+h0|$8;H`jqqP`XKGiqslj2Q$j8*kECoy~(Y;QNjAm_sO5B=l>to)CP?Fs3F3HY(t7FhpO3uI{hV4=m)94-A`FjYF?ymrZVVqf=2CzVDymbOq*tZTASa z(i=$L8nW#IYz4t^!jox82?nVMM$=+}kQ~gP#D)SONasJ`&@W%7cXz<+`~_}17WlP@ z2@0j18q%u5$s2Yyv&AJw>v2q`H#wR4jTb?Zj#}B#BKQD<+K> z(s(AK)fF`L7KqYH>OKKs@9yEdSHCHe5d{pKm7;LM#kxymVA{a#`H>|9%(Sy}0yo*R1Wbna(l~ zt(iSTsnqH2wMRT(Y1%1j%1MCZG7eiRAHIksI5k&);(-Jk(3G7lF<5pmLgKTLP z(5-pU*t)tCBD>JdmW*G!->oTlySzv}6+AUb*hi6?c6sJGqBK6 zGu9XykaOCH)M#)brkaL3EMZHY5z9pm3j}5|rlSVXvU+s!O~@WexvSY|l^b;t;2IHP zcU)rE2Gs^V4QEqei6%<94FFxqf!D3r?h!x{al=>J+*#?@Y{)brcsO*i6@wgnPK?ra z1QWz+YzcrEzWa`wV8#m~8wavw%#bt*lS>D!8OSrEfR;!aXrgt!?Mkdz#>h#@@sZji z8U$QzogC&hWFBJ`)FkHpn)GXVL@X#Fl2fuQqESK!F3hF8d`6{KVmnKeL=ax@pz+w< z+;+YE$eHEbtIsRjc+YdPv!Ep72Cx@B*w25uHMr$|_NEHr{1@itg3|6_CnzS0O)}D{ zfdopGco0bhh#>+BD4_;mLARDhdQD!g!W6Xg6;8x#4Y}g2&LZ&SrPACX4HT92Pzp08 zL3*~;Buha8IH+*SD6+J?$%ZK+3o4m7NjNl=lLZE3l1nNRCOp11u@prOW40qibJYyN z9MU%8xSe=Sn$?{HoQWXRLvWQ$$*xPC#Yw=xHGpWB(Jg@mAZ3mi5odyr0xECD>UW+| zu9v)0O~w?H%9g;2cFO9?l2M*8nvB@!z|yzwEM057RAq)o8|I2a@jM>{`-Xwvr6NJp zah?&wn!eb3Vp==|!>CV-sXEL$<%J~}vnU0Ao$G~g!O&&gw{*B|I3f@wjZ+Nhl_>C@ zj*1LcR*;!Q9d*AwcRCTE#+vrbZ?5~m%f#;DcWM;tqlVctbY(S`$uV{n_)KW?TOIJOI*u^2eO=j@#__*IJWe1%j)%s>t>5#0&3eSG7A+G38bQsnp#AdyflL4i{m+0O{|hgA(zia9+U}VqAxOLE32oC zYI`%0m~X&Ch&Npii?Y^q zQPxDBONpb6Gr|fLrbY_FwBN0V5yCF?FBN!$5Q6HQml&)}90*oSa8ne?6H&I(>ay() z^3Mfo$-f;Xnab+QoFJ!JfMG@wB!g{bv#uC-#)~EfS6WlDcpTbyIw!8oF%wsvJ<1y3 zD(q-S30lZAu2)XgRT$?tH;qomTE1|{B(>${H<_5cUn-(OyeXF@Y=Z)0lHoj$GX{=v zog1d7sxjzNShq_@j!y|TBM3> zqnrk%R}`h)0St6SY$3}1{>oaqt=EtDK0oKH=kj?xrPO<0r5yL@@chpjOL%@uN^Dvq z#(l*y+b(lswA^HFbiIzJ@=isCNgGJx+Pk-Rt`|%d7 zhK29X51o6z#QPpY+v+IocbGOgnB3}VA^{xR1)xQIBh{J%u~Qu#3owZK)$JKXB6u^) zLpx0-DjZ1_G#DVl6c6JVKK!HLAps>+upA*2qC20!&V#CM?jZy>lP$T2hR*B0xF>y< z?t2`p_-nV6zHs#5v^5|GMUIzTNNcPObMMgyu1VRL*285WbqcBsOLpOr1Z*)015zO*AjQTvQ z`I3hz03jmjILXevZ!NT2vb`kztQ5`Q8Z_Bz9rTLDCmh_>A$00 zeD`?g=~>V=`w?)E5JU)oW+yXf`uz2wBT6GhoX=`Bj;+jy?V;nUO&V3r;8MaA) z46g!#G+oO_sI^U+k`+)`6JmJWk4zERZCnliRPs3KaqYL@p~NIF^b9e&8(uAV8R!wG zww65pL>1ZXQ0?`C8$n%a`H4_NE0?x_prh=1&^w)I(J0bN$rKVxk!&jz5BlX?zIZLS7bIM!qf z7dVQY=Jc@~Q&LX#(VC?uETzi}yq`eHkGsqYiBHFE4+s%x0zd^EB6^p z*PQM90}=au23d;lxeufHJ&zM`@m_y}_PL%bkH4ppc98(Pkq?S=)#}*kW5C!C2&-qr zG+;X$9U(x9{^_X{4K$Oth(AB1$k54AhzC0gSx}V7uk825Lohi9C^%S>EM>9`B)}*; z11XF`WeI0T!+h{ET-TEF16RV}4$qmJ_L?q`ijSt~%vwXzd2RDkYao3Nz+; zT+?pmVBl`BNQ6wm>Lqq9vbU*JjkBWh3#kJbBE7$G0@f77`AyvW=8PDgC| zJ?UhLC#3$~A*+75x9C3wu9;q|74(O~RQ=vm!iX0n&X1$u26Ou+jiUW$W#weoQITb6 zk6*v;x;eR)ii(m%i{|<@C=k46Kgjj=>}7f+;%%R4NhAz;4J; zYZxG*6jy;D@C%VBO4G2A3=dba&@6}3#UfrZ0CC&%CS!n1GG!&I7T(u4j85*9JTv8q zG)Y8>Nc$X?%6VQ9DXLYjjiGz_-ShmHvr@TJhLOTN@wE!Qc_Wt6Sm^bRPA@UHAnUVp zmEig@{JneBu2uB*dUN3cS8w zQm3(eXZzm8-`_FJ=sZzMC6b>j+vwE zg9D@N#DPa_G;mE~wZ^rmswDY=kid{YLQu#M(-Le+?}S51F^!2dgT84h z2~|W&l+Y*=KoJ_=@h6hT1Q&PAd@9Z6s*02p1cLRllT>~UD)xBbLahTwjhe;_2NGLz zBrTWE#qpyYqbB`>fcw6R@8NQ}KV{_^_I!4OLox5Iu3OB>Q5Y@sFTo@naK zhAyp&2AXx139uSK4GFQF;L;YHVv~Au5-3WVp~QfpG?)onh}zDU#fzxkqd97Xn$iy= zDCw8ICTn=D3v>@kfuQtJ;|p;+n?|y%zLs}+8HW0CwS&c2&K$E8&5>|AZl#d^`k1~_ z_0-=)XW;O|I(9B<%O>KjgR6PBfpAwmsoB+MzPr6GY_q8vts_IElI~F8S`j8jp!bSN z5QOoTs-UG#pkbyMgrv0&1~gb`TX!K0LM00mKZA##!s;a%+6SM@qMFBbJiN7`#>q(+=VP=KIVH0DkWEAUvibu~~t5htGr9@;8s5BQz^qaK;0 zgudQM{?IyVO%$L49|v4Ng)U85`L#FrWqtb-%6x)$@?Y3b^W`v!&)8~!8ekAXksz;k z)NXBI;{u1*-_;KHxv>d!z^_!I4X&+dYd5%ogep1*gT_2eeBoLy-uFupqTwk+3qs9+v`rxCBge2vD$sU zX2!=hitW(-HibbI1)*uNRBE9rAhME@sHmtZLqJ73MyfF`6(rFK?Am}hRGJ}-X(YtP z4UK>Zh2j9nJqR}5wwt<|F3|U@!CxWzYkod*UrVbO>li(5(upc_Hdm(UQqF<3!AGQ` zGnV09^!s~?rPZu8ncCm*cSY>_j+66#RDL1xJ|1^GFgfMHs3j(nfu+wdCi-S=kQYvs zA%>89X{sBN5vQk3B@!G>l;Bm7K;nRvGoiCDFA&Eh5(x_n&XP#n+H#iP0xH#O+SU2~ zX!M_~>71>CWDwCYms6+GS98SPx0)<*)-GjNssJ8QWyhT zqn%0>$uY79@v<=QFJ$4D@}lCJH@@SC%+<5cR@zsb;0$bUD#PeCDRLs?B`Op)$visb z*yPj8tNVJl3B<8545o33%1*ldtF4AXqyotszG5^gu4m*?*EI3IDci7wlS3O7q|p&WGa0+<3u}29 z?A~{ttv7^16<#@64?`Elc$<2J6(`;zqYee;DlfKF++0v%#fX*&Z9@@6BgpU` z;yCQ`S?LToSGW!kR%DWfiwz>CgqaYT5XO?}`*cVp`@5lH42c9m0dw%w zD|FCkr<`@pyP4+a`4ao;g+PfD&q!e>onl@&Llu%0=izJYc$*d_vNL|;w|DTC|LF9- zS0$5WiIAFQ+(n_j0bIw$&ntrCQflOtDG*V#!Wb_o`ILc7oMwa+F~2 znaecfc{+6??)?5x(~LLb0HkC?L`Y50*p^axYpbNPm93N-4Lp2R+fqH3QDv}*F_f`} ztYkxA!nB4R-ontEqgf_^IwJ~#BfHn-wfVguv7O&msy0_H#)RZV_juhmaQ+Vx^%GaT zZT~sXx_V{eT475wJ@-dpsYy8Ix(Ro&v|SfH2jOr3)3vI6x7d`+Fcj#_(ef?c`ODVR zn%(!-`&>uf0s3MQ*t1U1YA8`6B_R;fH^!4v0uTWJR~|N123=d7H%XIr1ZyQ~4N!?v zutKFEP-bOiU`VYAGKggwT18UH0U|_bQ9z_9X-ZKVDk33B)eR#Bsz#txs`z4|j1s8D zB?C|%ZJBP)SDWb~ zaVP_rd8eZ0!DJQfi4WZNUFQ+G6V)y!;3)?SS@YJFHkD>)irN`XTO?6ezM;v)_*7;S z@n8WJ9EcE^=tqZ5mkrU+3op?+>MQ&ugIbPdTFYv>PlACWwY49OEy$hCcy9@ zhR{j+qBmizRM%E*stCDX2>-052a_!}; zT~9;Y698iQiPKF(39u~JTbJ!h!^Tg1J63Lrq5EYq0Zza)Oh_0=Zpb*g0QCSo2PQTT zkR~l@G6km6ma_F+CN8DbRIqT~uL6fCVLsP{uz(;EKuAG0sx3|q7Qc_>vr5eJosy)B zlTw040%m=>Zo^Mcx?FE^awA)xI;W8;JYR}g>vPMIh{r(*c>hP)`LD(KE%qcmX3e|2 zlH}#bF}MKoI{k!D2a+EQjbJeOy_j-Qml2BIRaI40RW$G8Bd+IsF6+|j z@Y}C*#o*y;z9*Ezx8CQ7k-UBFeog=k1O?!(Z6lS=Xb8MW2y0=2NG~Bu#HOXOjaYLh z05EYy_vC(2!(&3mFhNlUD$9&tY^q6#Bo7W5!iGT*3`sgdM1wGh6N4~ws{^s7XJdo! zlp6>e78gt^WUq>3cs0!y!EkG4BaB%HLMvNcWl>bqS3J{AEU%R@nNm+ZYJ(+wY^FyF zB{(_Ik~6|riK5CHxgk{&(PSSrF%p!tvRR)s2DsNuWUg7s%#Bq>h|46AjIzOSl`wqJ zg2~W&oaZ)aLB210-uBBpT;~kUwu&IRNg@gsAeaa$xx1Euo%#GER$lAO$CLP6<^VdA&RTnlvQX_+V4y-OO|=z z3y#3s_6ozXHq%2v!wSQ4;IOe|qU4g|s8|-8*5HJ~?uGogWC%c(a-CA8SQNSO^SfhT?9PhnBjCiKOa8lS} zxT;#m(Dz^`!+k5hC%;U#O1Rew z?k1m|inZJT`V6#FN?1QUjPg(%OXD@Bd0 zsuyln(JrO;IP)|}8tmeWT{eVg%Z9mhaLz5F?GsrSI=VAFl{->|A(AdZ>gEz8375~6y=vsqx94RzHl^;9+Q&b(5cV(YA? zpiN~#ZM}|hUHic?vGrU|wd&thQedvT^jhm_l7=$%mEOI7406uKPk$vt4G_rt;q|;S znsGZX8&4(4Wjpn0O>;iRoQ{S41m=@8kg>MWYNhMCq66~FNNvgsYQx?U5!iv0_>(8fLxX=7UsWjX;Q7I-jg&7Hwn{ja)j14lvo(UStjf$(1%^%vA>9*k)M zu(TGG%`BrPCtk!+vP&~!($~WgfwbVr{pzOF$}b7)8Z}FDcSs${u-d<@0jkey(g=y^1yll;cEQ))(*U>(iKIb{9FCNvLaM#un+C zF+To?&m_&ypK}yOWV@jHv&Ti$rhN>W8ac3vmqpP0(bBtgV96x+l_Dj$;PS-$0^@Q?syqKW`;*Uu z7Ol+nRLl^#croS8b>zlfW(_ zc5$mxVpiZ4TN~B43q|ZMbr&=vg)4KNj9s~h3~kGSyb5mBMr-!hR4CJva^vlW5kzB6 zV!RN*FGlsFJ=?d23EP7e%|SiKI7@RjN^dcE^HoMVEr6DMqKtUty(8!lqZGICMwMWc zSAnuoU3J`6I&xvjlI=32G*yPnt`pw5a{b!qy!;muDbc3L;LMAnG~vT7@T{@CmbIa( zg=JFk-&))*i}A~bMOlF+>D`LTmkjpTJoVSr=C+B(TevDk)=tXqv|x@~Gi1qoCPl+8 zH&0e8f<LsHdh3lZLg{-JmhMOt7l{93=xtR<&VMcqmZso4r z77C=27HQFm*+Xz+rc1bS)a-Jxn1zaizUTn{7b77U@cYGV99qS z+6Bv(G2{LV*+ki?zMI)sbxe|BE(GW<{rbX2Ho#`hf~js>j%)A7j2+isrwC=n2_u!+ zu0t@xUORJWXw2ul@{D;Zs{I2rGU3WH=wn7$#)@xaYHwgp)tPH6@VuFZ7DKu!y!L7+bybTXv_b=4Duz}-*#m+h!x1Z5c_1~>1dS>0 zb%@6Rra_B^;vob2@uR;h-CorFYd*i%zSCfrSDH^*k81x*PbJWN8GTBRB^pt2%}E1$ zVMH{;)X~dSdbf?)r&)LxOfYEK%ZHjNk!gKujXR|NM=QM750TCT*{r;wKpaEIlf!F%pWnrWPK>`ayNQn2+hz(LuEhP&= zHC<@?#>O<*#aL&jZH6eYGtszsdMx&zHHu~7!?SZ+W2Vt>nX6)Sp8!CpC6?zL$3KeK z?9OA`S*+C)?MmlXwyJf0itDV79Eh%?un}GW16~nTR}H@7Pf!{h4jXa}u??ZcS+>>> zvefRL^r4b$_2m-Ku%spV$)rRj4t!>0FTr^ z6Xg8|Dvw4%3zQE+_QCLrJmTr}gvhy5Lz;h#XQNbUZ6lHuiox={zNOwr6MELCm(%0B zf39ufFLWRpYi7AQyW*Aos{_O?6JrfsQ>uh;g02fWN^w@(7i#@+S;R;bJp{r?5qEN5 zUHN4$2wz{DABT(Wv;Mz^fHN@HFDM>O&Bgl8G})IJbN-oiWMBW~IlL#p(p7>vqd-cQooHpb@Y9ei;Zq!h4(IhHf=^MB~%GREJ&Wa)8XfwJ<&}TNbV>uZu=IieU zpTVt8s6j9lqI5#n<3gfODu=;OAaiySYY#Mn2{S9)%gn0*C=)oob4CR- z(G*uzRFR1!2pn31jF@^V<&x1Ff{IK{uf3Z$>aY*~w^bf*!3jr-9!r@(n2x~aAxoVh zn`Ue_6q>8_mmSLB$oa0ci4&-lK;+(qtciRCvG@rfXCb{&r%2$?{VJA?3+~M34ewJI z*jcO#oaHoad#`2PY-yx@Ldz1m7{c^tO(F&+hJiqPuU+cBO`R8*yo2czEZWZUQet4j zw}6%B;7%vF+9>&(R8xwQxJ8Do_GJat zH4h697P&K5nGIgESv_&Uo6RO~O{uT1*yZ22b9)9mI-#jHa@ApOZXIHxtYFt-LP=8D zBvGcCR=&!34Do%&&h>|Hx3{ssx_gfiwY2bL`T9RqD}Ea~mqGL1S8eG|+T2MzH^hls zV5|Op`-{8b{O8&3GzWN&u);Y&HBr(a7|}4UM?E#`3igo!ei`s;-dQhGpwN$w>f&3_hHnV9spDKl+N|a811qb2nhHYnn*{}2NOXK* zZqv}u(P>XavvDO{4GJj(K`m2HUorPd)WLAFwaUTJ0{2DzGqV>qMBQ{Rc2JZaAb^Z9 z&|}d+#`tuUc5!lRDf?w@`Fpr4v`wWGAknQpSn%|d$8EMNdyt`D`(XHU{FfPIzNX!s-uz=U|8 zugusEl5l1+SjmDPGqJDFW-~km^>^^C(PvqJf42?9p=VB&3zSQJ;nfro%6iN`Kd6d^ zF|;?aeIdc5MF&DN(^FGI4W_y^8v_GhqT5e4T&Cw`x0q>=Ege;G;i@I!5o?`GyJI%x zR=KFEpV7uztPRQPZ^MmxNQFyRE8O<{ubq+3ogwE}k>u0Iy@@Iy@}SjQMe)s+8v;dMT6ZFN^an{x7Xh`i_Ik(yI+E|3Xr&1#q>p z78H7vW%Tf>bALXk*O$;s_FD2R4&J&l62W800cJ&tOw;5W?s7x`*hha?BhyjQyCb}< zF0i;3OAx@fJNj`zZ^OR*6>^UfdHoGGxM-Eg>LxAH&Y#uM8oIYMI^}&< zj4Y(I6GS@#{Ty@s2p-5#EF+f7&L(+jLBv^RBfW!}5*X)!iy;?Tx2Sc#8WT;70^t8d zxv?$<(Pa0xK*ht!V+0Zjas$jP7g<}XPgO+wAJI_ zO5V$9TV=8*Vej(kSx<&xf;U!e|>N6&d2vZ*D{ulefU%gdHr&^&Z+h& z$U12Ds^7Bz14(G=`+u&MuQbWWSiS)9N_HVv2Lha+N6&7r1gx)bx``Bx_W=etA0JGH zGy|&^^Jo+JAA5pGLsXZXKm(sg;4}~R2l#Aoptiv=e`NN6w4Mqm9eWpIr`)d}F_|FOy z;a&)IYof)RlgPUvNohA*0AYB9se5E_#=Ya#F%{XpE`7TFlk1|7kx9UT??55anh;@7wdPgs0 zgn{h;%4}v|lfCkYMWbJ*pOq5A@kPi3obc@N1e^-!Z@xyL_kKqjkP+8!($5JgPg~S* zt5e|Uinn}#cWEIXlMwozdNNc7jP?Yx{=eS0jofTX^h=cDKnQh0Cr*}k%8ep@>JK;Q za}!FsipEv55JvbzCb{jDDT2`KnQwwnbc`GknXqw}zoRw;8VM2r2~-*>)~N4+(Hw#h z5FOrk0wmugfDFU?V-ZuxhJ#EA{-KK|;G|Mj5H9=vC}8L+w@dY*k0X1%#|JvMcA;^a z5}diIgA>=q|5HXhduWQqQFs_wnEg~v1<&vf#`<0AB`h&2n8_5?`lFt2x|yJDf5Yp}WYD@6@$jfr zx|ITquVUw~@a?Wb^tX0i&jen9=CXoKqAs9Sn2BFIaR6ZH2b1eVp*$$*b^^K*)^&AYhAlSPzy>!PB6ELurf~ zLv1$3)nt;q9R7tjSRsLArs~D|NKqsU>z~4yGh`7F5?Yj)n-RZ5^T#xYQIjtgaY9g% z2)i};svs#s2w3W=LKajp;KYQ1^9y~Z5ONFxBGHf`treWr+Ah`>QoUlOkizXRop(t~FdhxAnoIC~Qcjv)UDhk(EGOZp&FiR_tCdSC=+) z2n5~xa~L8bA|fRqJrA4q3gs74jUu*(GZjUH`gH*ioJ!W#h!so`t2puhX7&MvsZ7|$ zRSe>LuLNcV0R$3D(uyc8l0lHF^tqdXQr!r*0}_dd2M{_VAhRKY&Jcu8USe>BvWtPE zZfO&WaBU#+6rzAt7?f6$Qi(v|qAqa8vM+R)lr?l*RFO&L*=?nboHSQ<>mgXHu8|_} z;6UO#&6Av!VRMF5*doHOMhsF7EiEm176XEU1tbTwk;sl3!ZPKNFuHOlMqF{PRiKFl zvL&h7)B!yKS!zRW3%ICy0Gt8}U>P29O-M#kL|Fu=g^30L8K5$i#Tby7p{yaIgfK}D zn>rD9ZWad^1xUnKM0uTNg!e1T^w>a+p^?Z~MzT*K-3 zic%$T%J~F}*%!D6&M%Qh3T=%ss;a3WzfZRJADg)N zpS)rh)4P2&(gG^sD4+@&Ly$O^+CT>YfNl_9!HlYmKv2}uEcHI+6 z-boadF{NhcE-O@{m}o4^0joaxiCd~uxeX*JLo_jfG-xV8G9k{znyLzfH`ub4_~*Bj zC%p143NU0Q(hjZY>_WRs<%?cq@ofVt%gP^Cjyg;gJwhG?O{#+!HEM>YKpt!H*(-L9 z*D2gHp*D$)tGn2H`<$9?OC_F$_u5pFs7w?}lYM75r^ONG%dAu9!8suTqQF)EK=^cq(LULLmHNK49yY z_Yofc6DAzvM^LHpcW}ySmYGZx+a_VP55dOWCx5n6uFy5GwoNFahAVS6g%qG0Bvo9= z6;)MLR`O`5TBmEzeSR^OR6?^Z?uu?Ug((tJL3oj7?%hiJql&90>V&J@DbYYEgs6Si zw1zOm(cvZFsSOQR463|ANTNntRA63GN_OQs?HO24-`CMOd}u=Udwf{>jxLkqPG zvxeqWR>QGHWOi3k(Kg{268n=6Y&gH3#1l_ud@T;YO~L({)N$I1b=v)g(%!koa!E?^ zESFKZ+LpF=6l+oTQlsAEAdzPMvag|%KGB)|C+hFJC~1Qi^1pDXO5~-#jm0-Q`>dM; zj-Yh1IXv#uWvs;_lbS2G1xHs+uk z*Ql{qX7!h7m0&E0M#9Kwm)f+%^$-R$yo+1qd=hcgG|fVa*2dhR)hLu#z24ts)1|&H zMluyyc-OtX#i3W~dZLjiqLi^aIYTH@O10cvyLI>5tQu8O6(J>Eg?0i62%L}udIvVE zQw|;3{O z-4sYtk|{6diIu`dSGKI$s;Si}-Hc!`Vs>e>hl7ERkU)Ix2m{McDxKzG<^ye}J}1ka z*-#M4ui7TFHDf(`_Nf3r&EvEyC!Ar-fCABl%PR6r(5A$WHCshsh!=3M0GN=F6jGwR zc!PZDAc%pDS?3EXMeA&?(sMz8W>aRoa-kL$s_R#Bm8!xKYnFN1%y-kc78;yl>{xg^ zlgn9NB)ge3EdY;3_!vfPm+?pyp!@gOWeaB3Q{Y4hh!${iH?pF+M(Mq{6?iWF=AIzM z%L1w@J7rO;oYvJfF_KK>C{u#QiGWzJpIAgjOC?|jg48D z7YIY;4iM++-wcEXAX)&JAp-k^AOmcZxD-SxY*dp~s?7qr?(*z~9g7^U+k~sL)`5!= zu?o8~##-WVg$K~y9i8JpCgNQ}IfpP)NcF@sZO9Alj*ded3arBzE~m#s$ste$5dw$< z@R2bC0~(gy^X;M-CAO5?s}f!jt3UPsAq`$`t|#5wv&xVHaq9$JhZbO0ojcbIRx0gj ztB+@MO(hdR_`b(;G){`@Qd{{eQUzLtUE1br^y{UgU0wilVT;h~^f<|7rJ>nX(q&Ov zwHn0h8u;D3iXkSu0svb;q`ymp;Z3?8rdfYAJas6F$kdY$ZqkiNtta0X7stPM=z7K> z#4wOy1jjN|SH<%N!$A@+%6!_n#@aK($Nr;J9VFA@$yfwd9#xbR4!3M2vGHJbNUo-v zvjg+oupNx7hyXQGN)m;kp=di)g7!?Hlpbd*D=2o#s)dNHE!PSi!J`2X%Yh9&vUMWy6QY=i1niaOJGP+Ww zQAk4@P=!S^EWj#>(iEi$O);$sM)d(bqK5x|zApz!0Ev1ddAF2hmAbxyj$O-<$%^+l z&T{;jOXMf<|L;W`&AA_k_whe>_^;w$1+KF$?m?K0)0Td58F>;RCfjR9)TXJg9;l6Z z14{IgYJ{a7h{Md$<5m)*qs2?16<27%UYJcrhppFFp2lal_A?`R3edN=RLQ%fB91Ed zbZM+c-3s=+l5~~E-NDOIb8=H70xA`OI@KpbhJibx7Xa<+mXM2Ob4XjQ^<)ciyGtsV z*ocA~-mGchYYT|~EI7lW2&K~_dcO&IJ~L%Ec5)@Ky$uP9J4zn!+!HFeMZLG*~D)jnpt0Suhe1 zy?EFpK!Bgk`S2j1wRpaY^w%q%uQpgHw4qehV-*l0$WqU6AqX@AWi41pxqYZ4kWf^D zPVh)@U;?l_3w5lj?cz#OuEbSIjA}O6rL-SJNDLS0rjCFmHd?rkh*cC_jH*DWiZQPo zfL>Vh_*6(~O^UhDw0prt`Y@ryjB7~}h*r?c!C1opMS}7OF+g;ZLo;2}l2_E@AgL{d zn#n0Nh+&)Or*|7NQiCES5FiZ)Tun_WfT;*UTSU4lk;XLMpgn_D)JinbtEHV*4QvTe zJPBzuT-127$Goc)K+H;;Cmi8ZkkZxLQzdDku(|5a3NU5RchcWn|AYeb_0YX1BkP9n2TkS zm62@SA#e#LzyeD5?Cc{Y*{gl&H;wIfd&E#$tB&LN7y4@7XJ)Onc=z+UNdcSBxIoAh z10kqFSeS5<0Bs>QAP^A1NEpEgZ4IQ8K!h+%7$(Gk0kA_uNERr-5<#>C!5}6yfD)5J zCJg|RS6kRi#CaaV;=U#|xmrn*Xj3o~F;kAb#`bnf z=M?+Qv(c*Js6tHp{C5wB`>ap>(DP+3+PGdPUPU|w(cDN}{D+F5`ENGc`(+~BG)9dB=L*SDI3qj6BhJRl*n=|ifCM836as}(V$ zBYuw(i6%Z`YLsS5DP|_8g0!(Z%wivZ+WAVo2eLWKsjDQD-KM+r)xXZwxZi)b?Y4DV zeJV7W?KGz0lZemGPD+TN)6J-44pBkX2RW544D&5BtTmMa86bDU7z)Z^nwJh7?@8qM$62QQ&As2QQ4D{9Xj>l~yQjk1ILFXbZdrhnb?UDyAu+dUG>SDbYlfbIg1O(6H zEAnNrSZWJWyN3c%NW@BPpydvFnV%&Mo#a%~d3;ui*4CF`!FD@BxCm%goi>>ONpiGv zXj3O5wcS+~C(+o-#km$)b|p!n1y;`UaB%!i*HgE~-IKcKq;m%pJcDR6C`jaRIj(2h z0Pv!wXvf#q&@YRVQ+q3!ysc#0ccfsYW8jl^Ak0XBIXqgO^7!08-)E<*VZ(Fd%{H^^ zvsE{#+{>1xj!#!nXkwnc)reuVdns%pPFpLOCfMdsN+H22b@j^W4HiUiU9Fm3-9_g6 zWKyPb1otB?l@EToK}gD=qD9oEhKi9<75PMwX_r$w4&1zKasC(&-V1K6XKN&CtSxy5 zux}9;5zgDp*jZi7=z&+R%`THIbtZCp0jfR@lCrQeG)gGr93-a<8ZPk_7Qm`xiZ zg_xs2(#vee92A2pvlMZ_ne^0(u2-7E7HQz|XXDHs=RN(-M=SdO7vcBZfbsni(w!Ks zb__b0Jw4oze7i7;lsEAkikmnpJ>h}suUY)du&q^wO@R=sEf8fe7p)PZ0vxPoXZJ>Z z>d4KHwI);23L6nx5Q*Gi*|0=n@GE6#BRC*bEJ(8|jqwfzfD=t9w9>TIBGqPNR#D2F z+tGqul(bQ|uMFMX{bloEb!(DQxHbi3L3&!!C9otIoYif9s-l&Al6Oi)!;xGW38tF} z0Qq)jVUUQbsH2?Ds;)`|l}cWI;)3>aGBi-Nz~zN{OM(lH(sr<_#MrB(2&j@703ih} zQqURHs@eyCZ!C!5xinKsUD4r9tZd+EaeYNvz8*wFAssSo6V5YXhbBGmRu5( zHXN4XOolf3nTrcr+)UvJc0|~*k@5O7X9mlG#<hp!m!%4s3a0WB%8aeNrNCK z!A;h%LFfKljum+TK8imM$37O!-YUKAKZh@;fUO%V=tw(0+n&t?+Iv=wkjrZ5)AeVn`*|Y8BqW?VJ!z<{*|Cb(7=^PT)4a}{gsp9xXxI*LZiF!Z$C%#%HaB4rjtkB<^)XA zX~Swh-&}3oG^7#0Eom+BldoX_=Ewjp*OqMc_@Z-QM4KWkjGWk8fEAY&qKOr&Ey+nh zT~$q;g@ST7(R-04cg$G3ZAGp|WX9N+O%bJ~S{hcAMB{RL^R47|`ug6T>H5m(j;C*K znnY1WQK3PhcY91@8l`r4(S5tLz5-*XX2Ap!MaWho)%TNl(~#@OT>e8=`}6Ca`Y&!0K zjlW^tUVOfnO(Nah&Og{>QFpXqOy)txa%)%X8I_lkJwpUEedp0-(oQ^dmAkF1i+7MJ zh=Bk|AVd`ROi^i6R92NrXkRjsJ<>q-iy=c}4nKI~-sfbGEt{O6b>+CGinnEn6Wt44 zUd0xQ<*{kR&~a+xTxVSM6#Ff1b8(%cMGuJEMXhB7vhC@(Sf@>*uxLg^_^~Z~H+-{r zo39NW>3qwAa)bISx0!L}*GCJ&(o6Ih$zqn|?Dmv=NVJ5u?mvVvg21G<949hn>T zQAG%*C2qKsu7n}457wa<+g6A7vEKZ<4yQjk#9|&`r`)xPvJ$(MHBQTOJ1&CEi}m?r zIr`>l^d%ZJ3hLO*D{MgEeToc>uy?c=O{CZ#rqhj+;fi|0a?18a86L^4ORXx2nP^p^ zWT+(7LBif`x;OGTdTWQ4?p#w4SC>d1%YPjCqPuLEHT%E z1kI&hu!<{n<$LoYi`AV+766jsSu+60&QnCp$Vtx?BTY%5k@p!TMoN5DtDE_np)`@< zS(P6^yea5a+U0a}Ii5dsnV?sEsDW7|)bvsA)ZOTyS_Pc&@PW~U2OK+P3`Y}?n5oZ+ zpCh3^yU2alH}`uE*{;d#Qr1C5r3DmK7OS?9qpWNa$Fn;MF=Q%3xbk%=p{wv6l92Cs})I3 zAzBXaI2lxdu_YkYa>UiI7CG#OsgN{Lubp8I+B@tqUv>tfuRL6VQ%B@>E_++}G{y5U z*w;W1pkZd&=2}W*RuQmddkigUnG$Zfka4uxAC^R*1guAmp2J0=+cKA%qgxUjK+}o5_ zbFX5m_K0lRuBO{m!@lgZ!MUbs)RZkK7*79Q&nnt!KQKY{5g5QJ-dxqm)0(-lFI&m_zZ-(% z`cDwl?lrq+w%b8&B+Sgj;Z;>dcIY*(=RL=G^#!`t^O>N$ zKX+Q%(@G;+DmlQU)kE|#e z3zH_zv@H|}$546uqaxY2e)czvG@htM2sAx8WW4GVycxUVIIY&?-R=mE0#Uy3uYTQF z=DkmYjYejYjW?W!dM=>9OjA(V;4jxyox`^{ddaj)VfdxLN{@lwJHRg!=-vM%@lVPG zK8qVJjt}_OM*MKwEEJ8N*=Jm|gF(Fo1u?gn9gQTm+LEeD6>yR$u5#QFN)d5NJymVX zD`U#(aWmda5X%nXgGJq9!D@&#K!{*A8i1J+>?rV*3XyX~XG)4F4N6(`qqNG^b9830 zwcN&YTKGsf<6mC3sM>Y;vji+4FlJk!FlvU<9f z%(l9JWRc!~E`F?fDX(sf{w>vOce9Dex~pdHMyudkvu<~2M`^CRE@yGkrz4T!B~??oiJen6b#YRqEE&ks zW%isD_-*q=ozAm5Nl5X8l<#A(t_e-#xQgA&@}xtaY~R(yGU6sg@}b4a*qS7z1Co+F zc+&U9vE_M*y2-mH$$j?8GI=X##pb7IYDAdD%6YSgFbP-e@H`(? z=ka@qk!{O^3l8GzqQ`|&c5V=&$#C+ts+nnKKJ#0_VELR zj&RKg1RVn3$yS4 zH}h%Hoyl;Rrq|Zgdt3;Q+H9pgv^Dky`;4v+|FnH?B^u?zPs>GU;wWP(i35PKgFgIv z$23X5pnmt@^RQQ>M#4H01GO#!NF8HKO-bmQASw!=(pOp~c~7h(NP-B6(v2|;Dzr4I zl$kDagy*FM!5o~dRiVO~ycd)_V0hm|v&si?M%UEpHb9^veT_tdkOX_h005tp6gffd zKnr|`*c8Lb(qVDj>fzfGRDpU<;rfF7S7iOg0R*ng%tGX}W%|uln}*Q%-QLe=M9_&| zQL?uIre^q?#1twAOsr_5g;2a#r?^dj2Y_CM(l505p6wgVWpt?fm|bQ8(^j|A#QZ+9 zjk)-`KbxrsD(jV&})DX^waQcck6Cq$?~&FKqaQVGi%5+oJ66hab~tk+E= zT8Py&P_UF%lT{f&t0*y5O`~L~5R|APP)<~v30Mghf})->8`R}yviICf4u4O=b2`Cb z0+caj)lWNnlrjMdTEd(Sd0$?d=z%ZPYh1Cx&9MASrq&|(f4igbr2L<0*W;Zi$pBKT z?j!(JRa&Z5RaI3|sc2QDS`}4Rg`rheidq#_RaSv$6;(x{Xr%>JRiS8AS}9dkRaI40 zRTZFBRRI!#6;)JKRaI3LRaI40RcTdKRaH?@RB2UJQ4t2IR;f`HRRyI~5d=k1RazBA zT2&c4yOe^o(A6r{DwL|I(yFScs+27Nv{hHor9p}`fY8!3Gt-R~DJb!D14SMM3Q>}z zB@o+CA&}6GCqf{DFLTZBnT%}q?+X_*26r;aK@xfTD^nSyobi!0hAsZ_Eet_;JIzJ! zS@rZhuhqhYIRs2O>m*iGTFcbTN(<*xa_5msuSMKR1)>-+$W0r46S1fK_h&x=-f!+M ze;@69vT)qF&v$<={LOhkM;iLL#k34#D8OxvwAk3vU?GhOB#tSGBzBBIlVAj*5Fu~_ z7W~l%GH{0oaAwY*H=OpqFFzgis`Oi)zn$jiX#jOB`*+&a^^^8SU^gSjk1hax;t2+* z-Z7xxc=*$X412=gG)W_K$|rc6n8G}oZER$#-U$g5b;v)ij2s6<`?j)u^I0V9mX3Wq z{U=pXaUtX)-d@T%Deu-`mwX4A!ZeTkd*5YTg!-mJ3hUn>@x-T~w8ns-xNx8;F99?G zh#-wS2bF$`nT? z(0nlG`FyBG0Pu%YK{aC+?t<4|2&noe|Bm!+{BiTQd0Ar6}E(EX|dvJ}Y?Z z^KQ1i%`An~lNCP>)wL!T!n(s%kgaj%mdLHw8~!T#be}BF%B4AxtVYsLr?Q@U^GCpU zTfUCXo0#}dp7(zr<1ri|3MS!U_Syi+H48pww7V52T8 zW57&kw$(}+RiH&wQ93T8o8YmVoop~gQSjbxUe3w6s~p?jn>hU=<>l>+0D%G`=nWg! zDI`U=cbcjki0|C}#w8$#ayR!9Z@F-?;uXt=HfZhTOAd&s)ht)O>^2>pI94k@ODCSB zzJ@EfbNUGCbly*{<9zGW^EkBbNX-+-U>)-{BZsE^pfbcd6G!`heo|6+chlKa@c=>XyPd_};7Ll_y5pjnoRFwSY;M+Iu$czw=_ z_AMs&agEH&z`62M0M^Mfpuia^7$O_;=Eys(@7&qEZlu4bAAeu@XU&x&F`2y2pNkf53wMDz2(@n5);@K@<}!SW>`dUjxqg{%-a?Kso@$ zW~*nTjz(~`1sntcK>?f8uNaDCi4^~ShRnQ>WbHFKTkP-c*tpN(lI+r_1>FtBnq-kG zA|m7(D&Q9kJ{ ziOB;uv3PhoosV@kuR?VT-h)M2@u6xr30`BV;Y)Vwo1qzvA03evQpo!euRL3dO<2w8QgQ^=eGhtJ};2vh``!B4~=kWA6`q1E73rfYJUjd!M>{5_sh(Iap z_n8AO2$WDzVGIJJRTgeRATVGtd>pBWq<^!IMpX&P6HE5HlWA!BKGUDidr_t(%6^?U z32f9dWfY}f9XN&xuxh^(!#StSNzWFhF3inO^XPmtB!7GHd~a*vYwv%@t2{gNNdiF$ z0st*49{S0%KIIb|`SIEo*k2 z{qdxkZ0zI7^&jKI##&*_YOX>hpUJT?IuaI+jLdwZjUpJ8)#f|BSJ?1X*v;O0UH>_M zHWAB#DwzV@H-ZeVuRGfRDbOH@vx5LhD!&8RZCSj=HV@mA_frR)7t)}hAj>OHt=yTK z{LCIUFF)UD+m0Np_=u2RU@1SWq4(5a4nhL%XRC>OeQHc~6CLV;pL2VHMuzu74l{w6 z$s{mI22lC^F~N+M>U)MXn(=1Knkji`vosda@Gi8ptToNKLV#w~6%vdjN>YlOaID>~ zG=hu<>6JeQnZpE9fI32dk>zKF4WeG46d2Z+bU+|9jM68Fh;A zMm#W5#r2A{Fnybkkn_upCWw?py6;lt#fNaBPm z=akikG{u!>mJi)E9abNSmz43%y#7C*U=rw_hV7%1Fk?AHmH6u3~p0V zOQf^Bof7L;e%aa9XOdwiIVO1H2^-rFp?m5Tv)i1udLW*7j(l{PP(iXB9kGHCf=9=Z z@>~P}x!P~Lpn4-8LAss|hfmq^X}nTC={n&>N8R8t~;-tmbPF3;vjsL7$8u#3*$!moR~Pm3Jg$` z!l?6*cK0VQo2eq@xj~L7*hMr_9+KOA3!bj)bU>B3Idhg-Pzw3*C#;HkrLrO<`Y)h^F+a4ZCaNK1|;4OIQao9)OR<}-5UOUM-X0d5aZ(~i0 zNR=jX<+XC*%vD{+Gf6e7E=Ioq33EEGu!bjKZc8aT;b`0cHD1cb@jh<{R3j zsyN?HCQlKADbB$LU$}UjY@kEsNky`OBgPW4S}nP8OyR!bMrblZ9&+@yITuJUmed+Z zUV5fhEeGX%&&LHn1-ItQH59`6t}ej@$W@*t8YK*(yH=G?npL9_%Ph~3+ANkX!q&Pe zO6!18VV=eX6?R&hiDB@JwK0rhQ+8LXy6be!y`9m^D^e|@#?n`q4oU1vh=C9ffq-eT zFKy+hO94(s)t$k>6$LD~*1Qi&8dv4SkSAPk=X!%Gn?Y5=cj2B&okNYcPdxYU*)r^c z@&my;8A9VE@One(l_#Q>3pA}5x0I3Kg=*3Zw1{HbObx~$;hPc+BSwVm5$}$?(BPDNs-in}OtFLMB zy3S-`P?`uK`VSkRVtp4FngvA3C`|I6#VyFn9@WTHBqlN~Q?40TI|hriJa2dMCbQPv zIKDh`oT7)VigxovKvIr2YAo_vLo6%qe5k zGEE|yX1B6uob7=)gLG!z%(c0V=5(ZLrkOGobC}%~AMUB03QRR*q9yWC71+IUYV_?$ zqJ9EJOE)CvCeKCN0^2&&si&b)b6EzG2WM5>H5Z%pQ@W1aEIZ&B#+R*}yPJ$cWD zdU)TJ+nJnlpRzL}QkID(6T%Q}`VH}m9<{}XT&Y8Zu9l@xOb9^!L?9uggaP31ga&{O z4H}N#?e5k@TETn+J)++5ht%6)Z8KIIyeZV_dED^8eaNerO$ih#~>iF{DAF zKu~e}qhAR!%{A-epOYphzL~}z9@JLr@Xzr+-#NXh+oR0%3AEl$9<5#2!B%+8<;fWI4!c z3`;i_t=HA?+=+al3wyqEYq{D60Q80iVijS9I$Tv9{WY2%k$5X(+#9$UHLb&qsnP1X zR@lhWH;uI6`~0H6a`+z?o-_^`0S<`Gq{*$Q;f=SuQ89*t7DhIwcYl?6g`@H|9o9`a zvBp-nW_VAoh$p>}0*x)<2BWkn2u`k0f}%c>Q8&;$4^v#bQ(%^^I!N5UBuFjKCnHlI zX5zKqrr!Df>q2>)O?!wmfb52tVm-|Gi9-(Z=NChv_U=}uvCttR>Kq&_(uR${ED5D=e!?65lEwp6Mx!6Y3wvl~|RCV3X9g z%#^q%ld(!3sEn8DinM|I|DuG`!SmkB)x#4TDOzS%dgAcCTAS^m(_N*Wb$)d+koufY zll$IBap*wi_dy&WKm_XP%P9ib)~RCqT$eiPp$)f?i`>Dh-%@_ugjsLq+@9gzS)(oJbyiZF9KiZ z79uQox3g*O@{Nn{&SYNrswAlUKa{USySaMbo8xP8r?+?HJ<6HE(cR&OKZoJ606raW zz(fH6pn`QeD#J4MJeNL|vhES#ye{!kZS9hVno^x+^s2>LiRkgFSv%(Rw!SlU{ZCfO zN0`vvwq>Fo-{hS+IDMS94b38mp93l$T2_3&oLxw86M(-Ygh)vs0R?k_lLVq6 zB3VERj4E5j$a|HG>0g}5ZckEJ@?Y`FhR{B9-&M8`C?IX1v#LtLI!m1~GwYs3v&{$#sqyhj?eaN6ylNn{;T-|PAm3ssDJSIa>9MejXYwi!9_PoSnU0VN95!%*6@kzcys zcilzx31?dWuoMV{&fsu?rq5#tkFxmUKz+|2j*nWxYppBNNZqs}ei&x;En!3td~mfu z!X4;PbpTKyL5r+Grb??~h$4y$7}HIV!WwCeWK~v9<3@D5x~Vd={1*+sX0=?@ThQI^ z_1ouE=vl(eXltm1rGA_7;bN@|*zf4saAmH38Tmc8KR~Z;E7zt!Cf16S#@^pyvYg5q zd@m;}ZspMXmr&agd9aNw3)x9W-ZcSggi+=aq5EkO5vTCyUvfc&T5F@NLFtT98l_D) zG0f`Hb_ zX)+=~&PFep>{Zyx_nsK=>*gw#=60JBcmEn>AYSBXJn?Tp9a6!gpa7^wO5UXgRw*KABOQ)g6>K|dER>E%jUCvbzZ0Ef7=}tv5pMc zWE`MuixOOe>}0mEH`2rCn@#nQlQR28(URRzhTp3Y*N6;O9RRoR(F9Bci?jkS&;T?b zfe4!Qzlu}JGuy_3bYKU!qJQ_~c(q(|+g&{Dn30{;aGu)-Pg_~-G#J}$U6zC&1Iy0# zoA0!<*lXp0BsK!j=(EFN_HTQYb6cX65NJ5r=)541wR%I~UOKWG5QD*+o#Ux{^kr_N z;QW0P-L(c6+J>n%MT1m`JsCP4Yelj`7a|C^RQs*Vo;B4%uRq*KFHz_j`@cTRcK7hO zBoc_`(?Td903bB<2wc)H9@Cof!cS?f?CxZ2+HjJE=;TgP zxcuAqy5oI46&!D$zT3dYZQ}%kREQA?p^m%bB%zH36<%%6Ld+Q`@66rIiPZ0TT@J7J zIL+bkk1s!5)o3B9(+Nd{iwwd@TA0~nI-UG3z2k-a)A{OSIGw^y%VxM@<0r4D@yjq! zs%e+!ZXboKKY95Yb-#<0E|6Ep6vEon^nD@N7j{zh-6rP|!p{vZEh5G+sKRN|h(4Uw zzaw0U#=~~5hsE-q1ALvHv&huHq49lB?hmxISw>q%S+Nr$6e2TFLAr#1qIXy_E+R7~ z#Kan<(q7_MKgdZRx#kFs+uer-e;}e2Yh<5~TN{IGA+EyK@<*C#F-cGeCL`2;J z$(mh5ars_CReZ+q-x)5Lr_W_hqTsDq7I(vvlH`txrxsJC?cC1PgXudK2SrlWt!3D^ z9d!P;#ZI?HZ(I9RX{w&=zOJni=kb|b-^cpC$F9&B#ilTB^TNjhVrXcZ3NM3ste|L0 zh&?=5G|@uUcv%V?CwpYdw8KQ~HS_ohB99>`-dne*r_-!?IGgDfjSmpiqjqP#tlOjN zxDxPXmLa>QD5>t*WUEV(2!W4thxdNFStC=l|C{IxWKsHW+^55R0E7;`BL`5kUFLRaYV3S}1Y=5CBr%120ywI>7X^XnuLm zkFVU%%L^b{jj;~*;rCJy;b1Y!6xt=)G4?KlBP*!(w>`IQ@v=CbHk(KqMux$$v5f}s zhY1W+6h)$%8d?EIypV|p6Re_dI*YNlRb!NP3)_p|rIB!15k)3hvSXJgg!hpmfve3@ zS}Sz3Av!6cyQ!Do%+a~crXA1gvQ?BZWp=qzH*D}Fz?&AANWOmm6WFXta68(0Y>De< z2;b-59{h_sdpN(L4v^Ci?EMLRuS|6GPNYHsFepft7JmDO&9(0gQWLW<9nD@0noH9# zi6K5CFB%~hK2jdtZ=o-LMydH6UW)d`=H~0f`d!bz_<7?T8%=`d91Wq3wuYF70wO>n z1OUUlnMmEDu(R=bHg&V}h8yWFtuPt+>{po~V0vYGd38f(HL?3SGxUlp&AQ{3Yew#T z>S=6U9^wj~?Q%*wnY?84TsZ<{8+W-z1xiB-O@yk0vMk>>kjR%end|5C(3K}I=}O>U zi}EV31E$KbIv~sr8J|l)bexf+k_AA3qvTy)cyvZKZ-dCsZ1$N{gFME)(&PzaH&|%6n3!J|6lbYzm!{czaJDIAi2&B`bjt3t>Aw(L} zRRybXa#k&6AZ^GX72Q?nlNim^mw4SJvpL5#}~nr`<4AK@~(t3{+Zat=0`Hh02N}M2DZbBEdy7BwFbBT zJyM;gVlW$P>|-HoFtV!rvvxc^g+bX7!@nUAN-DF4oS}F&$gGlgJ?_23Q(5avDYCh@ zdL0F5lvrR0GxgdabUErYF|=JAK#L3zt1#y=Wy#O{%y?|QWtLt884a=nKoB0+=O>H6 z=`S`ijI`eKY5G(_tI3zm_`AlZ=HgPs7(sU+HAv-C8*EE|dfAuk&c9%W80-^oB=(>B z>FC^VB4105NOt6^R_Csve`A>9Rn=_hQ5MZmSY8^8e!si2{m7ON7JVrxMqf*Kf>2hD zY~{)Fl~b>P^9!Y<4*r6=>%2X2@OJV(HaCmot5T_>;EyG$tM4XLNN`a&vtIY2xC=yzss^gCgA^j?DUdJ~ zV%YqV!KbJBUA(!AiQQ1)$oXr%0j*YTW69D81tIK6p@{-{rpOMz+WXahmtScq^+7B^ zNn*hPLC#FQE1LMQ9_9EYlx68nUn+*?@{;s_y1xpDT-y9IeTlHw6_fZ!axPEWZh>V( z+p9Wc8!$-Ny*9ph``;I(yo;>t%FimXq$w9I7XavxK&>F5NrGr?i8YB9!Ccg4FnbK$ z7j(vg>DF%}3t`u4rRMN?vge*#$D9~>PdIktj}EQkj9C(h?E8ex*E(fh9>yzaYH>6T z-QNQzdE+%dW?@=%a%1=NwyQJ3s57vj!HYTrjJrDsmoa504hJgL& z+}>B#2L2gYU}2CMZH@vOLaUVo>&qI@}_!d zHOzCi*;OYZ*9i$^43Oj8XNTmZUH;dN1z#~y{>p{84Oo6D^{P!(I_}PIv-E}PyX-%! zAXvHwsst#@zQc2Q9OvD5ZhcylUX&Q1f>Q*X!4U$g!X4zYA460xrRcC4a){60bops2 z!r-7503NF!4eMk$oKj6{XGrFG#L-}_1|sdpcZa!kaZZV-sauI9$Ptm~v*7S{_Wc%; z;QJk$^<& zGnsk0#2~$0PGyT8_ZNY9by3&~0(?2EjAq5OHQMh$l8y&It$U;E2Im&+0Js0-&EHLR zBcRu^5UiLy10sm8rEG*#geAY1FoQn49G=k93*uE|3XlY^9-AwGVMizWZ^Md0`2rje z1o+4Ghdht#V#Lgk3Hvq=&Z#5{p_JNf`8n3E8qMY&v~A;rkdg0TV}L+FKo*vfX{y5{ z2p}}6&yom=BGMz!uyceFT0}aYUDeQ_D)n6VBL?69?Vu-h3uEEvaGr~MRUx4_(TR1lwd`I(Mg4Tpm zIS~j7q7M~LvM?YQ;CI%MR3B6`30Uos##x{DM}hx;XfAS6(=D%4+#?BV%Gyw?LQ*># zbp8+fXY<-S&ok?NH_d?ZgK%sj(%U_n*K+GJwP{LjjNag+4qpP(v$=l*37yyHK;80P z_(AiNfY=_048q>Mc~LX~+%9lsZM)u@YVBX$PTW2p$)B{WI|=C6ElygAdrM;lYfuRl z+t~Q1FodvwF?W(?#NCya#!YbPG85UvVx#Q84zDBP^SavnZ+VbOmdYzSpS_$UXSnyr zLUuMrp(9N!)Ie~v(Z+oMa(apIm1i~SAa%dsP{qQ60@002f7z)psv)~f`S%3PUeStZ zP0AX&rMBv@NPh#{>iQ!6R*id;T%8hk+a7U3hTRtkMykVC%};b(ggD1Tpb;ZiuFpk3 zRYcxnndc*z89hBLJ?`Y2<&J4GQF$YFND`+Kd7NJ7 zbC{NvSRk6zazS1*r&~3R{~=P~*L!k`dP*K*iSZl1aZE&dVPdnz!||`e!Qk~e_4%)% zjytW^6XugJT?c8TUM~MDTZf~>tvj@fEJf*C^zBCep=--@x-}MR?UMLFhK~loQc47Y zBV&M%au9-0ix-L!3LcMGvKXci3S9F<4nZOdN31Fur5PkBlXy~sr+jhk1JVDgkEf`U z)qW(?_iN2tGuJq141|`7v^b~RU!>GK^M5}W;%ZAxKTK!BLy$m71SJ)^=%O|$Bo8M) zU+4MGPA}Vz+;VNFQ=D@FOm0l)^irYEFOki=lIQm7dx}C8r;DLf>v1%1wK|>@agLHx z-S0Wn{-b_B)%gqL5U#qC?x2kmPa7BMs7~LNW_}c)?iBGMalfYeZ~_s4{Sa67t{=`p zs!NRjH(pF40n~uwsBV=DP7{%8*ktB$gZeTwt8^kq2Tevspd&z#l9uU2CPb%W#!@A_ zCGMGXtAIK#kLXo)Hc+aoWzC8276>f2ur-jposN_0eyrDI&tDH64H{T>`X}FDjb!|Z zL6(VJT8TF1Gba%Oq>wke zDZ;PLK__;j9M0Plr(XT&7-UIqNcM6|eG|VHgc}${5Tv?KS@kOQ7J~^(sBW( zbEWk)XkPGLbbUXk-F}zqa2_D%JjeTn2#OXp4w_0)j24ttRD0fL)-a<=3M!8l1X7o# z;JUs{BT6qt-@|V?!s}RQ^sjY#+IikbhP-BijVjYi!6hG+(DVBIK3vCdr};O|BEBh=3RT}WbW@KQ<0ir+(4<3JGDt55fZ;eXW zY^<3f1(G3uYk{djB(+6dp+-b;eYqg1F;QcLi}KZZjSQw{710&ptw<{7QpQd>xDW^S zy0_QBUddU7qp%$KQjf9AsF;Z~FZRvB>Dy@Am=vR)E6mEm2HTApzQ}KBylDp879ua! zeY_Gt!FmQg6A!e+Fnu3Lz$OQ;F~u-i@RC4cfneo25ok3^szv~@&!l}Yyd#X^KkoK( z0}@b2J@&8~pb>o>zItS$t7`%RR89Z>p37q6dJVz6yW6R%LoY zHk4VD#qL`aUJLboKe?kuhgr#EI1s)5+|Hl107x{@Lll4nAoVVcYS7Rv{ookmqW*%C zEnSwTPZgynCzOky>D$g0FzOOoUvmV>sXzyZi60BV8~B21^lebtE98mXY#~8sVh{Ams~V2Jc)A_*Q*&k`iZ!0Zk`EY zA;GlOd_%% z%9e=v+H9T>4om#@gJ@cGUQZt0>m%d+hYPDw_nGsZ2X1~RH0VxGL@UJZTejgiY^+IG zaE;xJw-_U9f)_D>#sTjOhOV0kKec)Yp?bb zE~PfixT~bQgwt7Le&v$$QUqF~598sAsiKFp*sBByBuEM>TQ*xP{D$$a+sfl>c47`C zr0^2VmSJ$r8CuzSOSD$yxP~RmjH{M=G)NIBm7fVCNMPS91!bd1G+(P9q&KMV9|NAH zb1psBA0c&js2?+ao(-$yy_=cDyYhT@z|i^aA4Z)NCpmz4G*hCGz?H2j3JD>{06VTW0r; z@#DdxV(kf-r=@9_&$!pA(benY3tdRS@lU{YRLQU_x_pOj@{2E>{Tgxn;ukOd|JjVm zy7z_%X(ALis3{=YZ_zUVO8e&l_eFOpSgbB4maeo+JH#a|C;?SvHAVoS1t1U-NRWgK z5s{$RXEE@jUSewOPU5x}Os8KX;bY|=Z<&2uAAN0EEbcgT8+A2FL%68 zXA!k=NQ7~1Q^xBGnMwdD_6#kjwI06C@()rVf%8@No4|Rp4`#^Q32d?T5#bzI-$mv z;E8}Cc6)_EDHbJAbGa^###;0kB1svfjUHUn_`nHt1!^K~5K zES@zy)RRXwXU$VIEEPWQ(dj?_*VxC&`WVqr739IBoJ^zVT!wAk>^)yEhmw|}s|YG( zJQv(7J5CRBDM>hZ@QM?=`8uVLZSU=l)uNZHh{CQ#|k%U6% zK3Vn9{vgU5JCiz9Iez>iu#3U}f`chcQzpWq)(uOMI1g_}5}AR~0}4o<{3M%mg6)0( z(pO98nJ_@98URW_wZ917DFA<<*x3#2=lO&wuw0I1FBJT(lBSs!fpHfUlb@B%D~HDE z|4AS@Wi?AT?*AGo=}j-d^)gqPml+T$1C>;7?UC{}Uo+u#ekaJz)1p52!Dxe!jg4-n zIs0a!#fI5l0vjNRZjfn4kWsGM5|va@1yQ7W4i_&k{4>=zRXpw*60yzd`Y$l4p+1hD zqSZ2HCo-lfO$3u;4eVl2jt7H}Ln5$lJkxm~K?I7^&DZ8g#d-J$n;zyDxZpOpv4>>l z?4#ORri=Gomak~7(oJ+OM|jjGU9m;{U9^c0vto*oq~BO149>8{$T4IUc%ayIo2b=BB_hK^qdp)2koWC>wUj{ z^LL=rYNLJ3wJ_cf03fw+_WVWuZ$qG#hO(jO@S}vYi%`l?&87u@WE9DgiU|ZX1c^hv z6dvH!`&+wfugx#CknIAhU?B0d=etRv+A45|Jse1uybQ$E)CYLAJBt9aX2XyQ|H^&AGF! z=%O+brIT5A*Q*WHJV&|tp8k^}0S&P=y@hcT@494%qODwCUrny*@mjkOmPOpE0Salq* z@UdN{NZh@|k&-?LU){thAVc~L`GIj43s+f_inX~#*yB|kjIwbt2~nK)|BgZ-(&52zk_V^=Dy;xbl;yTA4|IJc+VIjjMxc{gGm>; zSi0UmSoAQz3}?cJz$n`em}AIZ2b?fJ!^0pJK37%Mq$pn## zAQX}6qAHac+G-ZOx<059wWrG&Vbr$(xqXN@hu> zTejQk(eG>24;lPYkNBf9oHtDJ0mmKuzm6|V$zE9@yl`4HZ zo)UlfNZ{a(PA?Od@^bUJ>ja%M;r9oO|JIQ=k?1a{U3|Q}Wk|8y;c)!tUuX7JQ>(l2 zGe1{(`uWWA+LQi(=91>xO8q1w&7#6XrN7V(RdhD=eUB52p$oliE5-U}(6F7YBJt6j z&>To2nC!oOXmi-jn5#u)0jA$g2hxkS#Q z&|^xW<8QJ%8QUnKLtJvjN{K2um7!y6m|K3o=98&$Ovd^9TJcxF{95!NZ}CL~tLrq` z0UA%5rB{cpVT_)Xg9s#@EBUQE&*8Kw(BPT?GK|SwLd$7q(Pi$v-v-T}&&h7ROxxYd zY_(@uqxQG=JQ>SK-{1Nl2&lZYA_$~&sdg5CsQgg*${KR;Dx&s(t^`3fb$S*KOtQES?fujxxzGu zW!n9@P0ke!vPnSzsv^>@A~d4Vij7jODa4bAqQsCbC0yz`y7c}2UVa!^c`Md6Dr>q+ znsubf?p8%L$}JlR)`q2A2|8Z=mv{@=kjMzoa*||KL$}^JK3Bo`D%pfch@>MjzE_)T`Vj$SbL5)TbIjbuB#R3LJju9bOK9H50BS=!aERR13i8r3wX` zkEtiH|HFh$^J~IU_xq-1?&kYYTShMK#Q;{(1Hm$oz7AibA!($NAXljH<_AYuyQ@le zE?OjeQema*XDZ&pG;XnQdu(qZ;CcsUBCX~N7aki)@lyPeGKB9UK$!rh6R#IT`k%Fn9{~ySXN|By(zVa`Tc*Q)J*| zrb$yecyrX1f}D*vM_CwAVe%XAuytIIU&OkbRK=*31fYd?as|VdiCed@;<3G z09#GbEf#?2Ujeb5njocwhlFZ!;=weqQ-B0x`84{ihWj?rA5(r*{>)mTx6I*Ff0diA zXN}a)y<~|Q$PBq;_1SW0svHA|!^BQf5$DxcBOjmJ_4SW+NcCk#Te%9MNZ2aLW=JKV zg&eM?Qu17P>2kV|P7IQvOC+^bE0}RfLKJ~J!_uda6>}Nb)>v&K%xo_1_f*&QRzIz| z^qkj)mzE!Mm|tVQ?ii8d8Nv{n@OjUT*>Mw~%o<$|KQpDDM6|Qvf|Hu|tMdj_*yoFU zH|jf_)L3$Wf8^z^frARr5DT8MPyxfNVRz0sN)ARiBY}hm; z6-N?oEvZPXfX26xpmy-|oIFkhLF7c^6KQh(N>I{98!5#W096=~1Vm+kkX#cADab^u z3`&yY(dRNYmRI(_XPf=lGJcyU^y33BlGg~?aOry+_w8Qqp-mfjvvYfOC}ow_ktIoP z=hUDxL5+=aG%HFC6hn43b#(NZs_XTt*=R`iQ#)Fe`rmg1+21=4q2De8*fHujU}9vj z%#wNH+LY+aZ7a8?w3Lw{Iw6q&i~x7Ng^)>2nxi2n0H#O?1vr$#KrFo-$n-P1=fDvF zihlo8gFWg>@`zn*HYDpfNGTGFb%QDYB_@0bt_*TjA1wSs+l=PyI0d52+EN6SZ_jByWC?h>M^G5+J%^j^fs3 zIVjGjKFb`uO3RT(&aQQNIIbn;`ECMMsx}+MWIeZcQ|V+oDFyBoy-@M$;*U#Ac7!l* zw5L?A7L&&im)kAgTQ&{@nNd8na9W_uxoJRw0v4b3vMiOZOh3y})?2at7o0B3>urjM zdJL7U3>N_a0#{+>e{0u%#NG=TaE8I{J{;Xn7YR`m|Jv;5s5^6#U$(!5{YLC1iz_Zt zVVVcf5(xi7Xr8o+7alThy)1+)W;pI z*5F@o4XJX-^YBJpp|5FladYSTYuJn38*Rpx|Cn!e z#q8rE@BX}5(_dU(cTEKYip(9FX1>Ix-xG+$92k5!IKpADc8Chb8z-3CywqX$9ax;! zrwxh(FI(tLCdMOiw$4ENFH}=c9X!R#$-eVvFur{KcW2XcjNXpJSM&v8>{JOXX{|gbI(eGWB%to?}W2526Ch|wmcW`oVTG7lq zOFJrwP!WRJ^rK)c;Mh~&&XBxdPAMkcQgMU zRvzKG`hOjn|E7QP`@g#6V)9l=27_Pfn>O_jhn1 zzcEGY7L1-eMPMDU6DG}ZbO>ODo)40?LQAO9xgwp_gr?UI2Y(*MdmU9GzMk1`sF>-}aJ`rh zLRNU*zboYIP2}axOM{YmP9hfO4vvV+yQbi;pw@H+5dbzO@nlSqpJZ&|TZkWF_Wt51 z(dhS>6ZV{M)q%5AiCsSxd`$q$7})pCcQUpP0-^i<$EfBN(BM97oeECcuu{-Gds|CG z(m#2;P8W)QFDP!>b;%mXR-K+KaOB}_=t4j61v%a&Ioxn+}kk(Xd6QAt&FPCf% zx~}ITbh%Sb-ymaadTDz+Jhq~FE-oIfa~OG|d<&HH$K8J*r&P36E|AaT0yMqcg1%i1z|jBWv`Mz^`F3oPefJy?ZK zSj&&eN!yTBj(>c|Yql*NuH~4GPJW)xLnYhV`%>*|c=7{)^Py{6!fC#lqlUTlGT2V+ z_;R$W9t{qOHEvCrDkMz)mg>~4e}60LPY7SC&?@(u`L{#?AsV!Ny@l(Mx}m*jbXJW9 zyQj0hwZGrsgyPx~*}97YA>1G2c{DR+0=1Pn2_x^twj>g2BcTjM&;{A-r| z-?Mdpdxg3?hRvI1JXx+~w*I+0zblP@zlI+DbeiP$F)sN->F@XBTdmN!?!RL@w!a&D zz0XVaY%&p!kf&#}SFP#p?suIoz29MtI#k=T(^9S z{)bmbGP#3Go@XnM&d=E{{d_IBV$xS|HUV23$48CP(OxcDuyy35uJ-La!`0h4I$C{w z=Rc6WYAsi|H|6?_-an&#eCTZ#Z4|1*X&(ziE$8o6<@yt zkD>~2Lj7oJVsdeXBrXkkn~(>F;HDFYm^L9G7X^ZMcZ9&;r7%0(1$=gqH+OjK4d&?3 z8j;pUqXzkSof$0_spaZ1c0$)fj=El$)8TZhuCRA2z2Bc*ke-CAJtwM5EEQ)-bf>ye z-7ZMF==T~VjU6)dHpE4N#R1Y4OyAo4}4Rl9UJI}*_V63?)?*DG(Z0Fq7bvw6< z{_9UkwVKjj)YWmHH?JqqU{|Y3<*JdqU}E~ZN;OFlyifm!{1b|Rp2mm z+=qE=k=vUFvI@~re92NNZo(@<-wV^=DS+gENpyS#Lr&Ct8+hc^pvYbhg=*g#wNe0zM( zAl#i@n)j;=i_BCNz3(w4rQPA8_}2_QYl0UH^n`_rXB|t0a<+E0X}r-u@b!16x=vN1 z(aQKk1&}Xw>YI_;oIqCX!Jwyex`He z&X^EvL>5luXmcPj*|7iJAq)SdDCGcUN{dp%mLiHXD>oH zJVr-_6Q`5Q>1$yS{iZIfF+;S_#8NlfU?kMt@-cCXphtANwXDSBFFjE>!AL0pi#}6tyNLXhGC)^c-Zg*VZWKmlV@Q4^7?ENc+3IXD<4DW#QWK zc(<`F+LGyl;)zA>>ymjaqTCJL`BrP4!o)q^OR2-q&Eq%I72O{BrSiSVpviGJ;Vh>d zG&dBs5_l(#q}8&E6uzZ5+I!|+r(>JH-{~#2o%Q|F^?uYPuDI*(v>WWTzmc-v!^Pe- zc<1|_<5z@E8ttcor=ewP%jCINES3sKkn7FfN@RALOdWL^-Ljs(+WFg(Vj^J^fYs8S zT_h->tP>l*KAsgYq*PlKVrfH(j2s<;QHZQ4gv-~RiNKi#KLU}~G2HX7*W`G2`}SjJ zqQ3NR*Ue4s^6|$g_E7t zv)<;TWA5>(WA%KS#p7J^ehQN-#k}h2>Nb~a{v>s}=&QcpRIHuFJ?0J!m7TlxyJfNk zs)M|OBeNA+{lC=b(fkaLcCW|E*R!4)_WX?Sx>-6s{WWI8mU0PiQsjb0*Ov$F?!>|( z=H_m^roNnumP$kNb9vS9px~QblPFhQO(QDAjf$}X4y1m3(SlA-O~NGTVbf%Pr+ML; zVn0!Mj+K~D0tBR*0U{eHgwaZHq9g+KKU_}dZ0`6y`4H-cPsi<27!>3Z88Gg0x~5>C zm<+@_uoCW#WZ6!@x;J&Y6aNQ(B}pj-{4Q6kbJ+C*q2u^(?k=XlCkw;o3;DJF|L7$@ zBjPBw`z$3<>%m{aa!>DobHvYVawJcK68}qSeXgS=h{4NU&J}iqfp!(bYu5!j1}+TO zCLi~4f|-a!gQR5^2&vLYR*J%M$tU4e?FhD8MnOI4s7O8yG9V^3(R6k<%dx=|+4;kV zXX|F(Uk|2#%pQ>WT7o0fyROAvrgEXIZarN0$z%{pe@yMq1gT z<#9XROgf$1wf-u>-q7iA*AD+>*F(y`^5`=-4(b!@4!zbj6&RkDOGBFqce7G4PeGwB z5?*_`3C&rR$r~Apv2!FIF)y4ea}3%u-F0x8oTNZ1Vx`+sY2ocbF*gK_#b&Odk1#8yTlus ztE-MUI^T1*Zr-$zp1yY~4Pc*lM=FnN@{`?co(jg*YKa4k7u!SDLHe2&+azqxa= z7azUrRpGBLZu5Qn#nN^pAOHYDwELVy>u8c-X2%>ibqGS(=`AL;3W5-9iVWmC<^{JP z2YyfDV$YA$OXr_+vse$Ng6;=53Tn8s?6{i4QUs-!njcPr&f>psuFl0h_A!aQ zbWEq#cxYyUlb6JiQBEFJ1<4F2KA*jn@^EK~9(AJI*@XACeX&<+0$Z-s50Q~|Yb zQEKLflCaV}keMzmQbCm)Wky5s`ot)l-mkhCCnO(tBc=zss>F(e7+Q*DgYTL~&lZxq z9*K|pT@7?D1)S(eRpUvWMq+{!D-v0l;&dQU5_|`oj4;x-mr9MdBWtN4YF0=YGj(c> zDl1g!Nwwi;A6n$-N9)gk>_xoNHafxt+H^zmhsZ0!sYl?7FcYZgt&S z0LBhqOdaM2m_~4g$eq_7YDf!&&GA^}nV9pc=8YQ+Jg|<(T2aZdf+Wf5NW!tzXNr;| zUQP?o9dpCU{kJ^z>awtJ)i&Y6YVsw1;%0Jp#oiY6rbaF^gghpBu4}R&=gMQM7Jb`q zu?-0HPiV)SnY!&GHa%+H-d0u-SJ{q{3 zD~a@-mdI*oj2nJG)GoXPPjv;_kRPYjPV3p4Kl`Ozn8}XBh%GCn+|lyPvIvgy46=zt zc0Jk@dq1}uaQ{lSG70jQ#ho~2pcaKj&Tb;2BAl3NOGzmq&}-#clBYQ^bCU{MB_czy zxeb$AsM?>A{jcYLgY{lW?%vyv;%xOxp-HnTFo!o7#OZU){wx#O$)cF&G+koYaO{r2PMN359Ol!?^_~-$DO+?1N@(Df=ddTpE&$fz7y>7I_k6oCvEp+kEbS zrP}D?(@ks!IH5wg_&s*3OE29uKs5}DLf!1Qi^ZDk?(=ijHubK1i2HBe;6QtnAt5@= z95aSpAZ!pA`A&1hvycisMXA5ZEhG}c;Sf;DLgR5AFlz(}m$Vi!$<>1}PH^=rUw1Gg zK&|uNlj#rrYH{#G;Fk}=WcZdkSJZ-(DG-Nyx76_Zrwdzj<$j;VlwVU&8kN(4kJ^C z3ONxzV25(bu?Em>(BT&h8jcbPmL*zcuj8J3L80BwV(zX)b)bwJF6Rf!!7jSnA5ecR z+T91}55v@~p19eM2S(1j6%iOAV-46jvv!gd)q*DmYA;43l*J?FDkB$?(F7ZVi52nu z*|)}(wpKPttN0$Vf_6g8g4{v&eaL~rLhfomxe=n_%NfPXJA6p)wVSSb@|$YdW^aAN zvej0U7g}w}T@K~tff3Ci;h=$OA3GI!5=-NE1o0@zNg_%581?aquOxRzwjMjP`us-$ z(NConAXQPM5FA3|pX&Lg3TyO^+W(V_PHaSwr6DHSeO$xwoH-^NImw~ykisraS2~uv zbWdl)JRX}f7XXmavq|kd^=cc5UbDs@$Iknxh58SJ1pBXb$srb&$03-ximfQDts^aU zCmJNigaj4jpX6|1d>+eXN+ImNo{nMaKaW?=d8z&t#K|Z+fZv(-E97tR;pGpK7+1@e zCPC~Wwp^`z!fGb8!h()cnib85>*m5ZWshy=Trv9+2clWYxv|_6NMR5% z60C_t1+6xi(oCSadY8a|@^d&G9emI>km^&?(|WNUDVQQ7WX4(xYVKBPA%?niB(=>9 zOOiRhq&X~az5W=l)zTW@$zy}uuxSnrSue6I4G75u`QJ3Idd71PmVs~WlG%~Geq$cduXvJ6=q{2(aqjVva*kX8W!U*e4JG6e7QrfCl5CH1 zq;5wpvx`YDnM)ieiY!xDP26jq)Ha-Hl0&}Rv?w`7TSf;S=cV+U&B&5G_tr<53euHw zY(7boW6oWkAR(?ERk^w4p}Z=$+{5>#KC6kug3G|)T>u?Zj*KG+Jgck`wsBk~un zV2qSxo&P{nhnEHdCq*m;<6+OTAp^=20UMtjc?O^ikX+wGB=i_EMP0kYWZeh_lFBxR zp^qeq(1{_+MA1X5&#>}7*504)Ca;b;!xDm_L>1{Z|mKyW;c zg4(LuLyqXwyy*5%uLm; zD^_>}A%=C5QLvrmgbl5CpuAOIU4+I>$kP&sDwz1^iylsy595C$XW-7bfc`@2JvSew ze}L`K$tT_Sdbo7R*NWJHxFpdd?F?G7M3I9w`LNwP`IBo-bDt+Yh8V85o>7iyXsDo{}6*cw%mIfnBwg{irdVZ`7^aWYJqm_7bId7IJ--$&kM?rJ*12@i5rA@(*e zhtZdmN3&nQ)0V6!1{{gB_{syL%=PH55V1EI+qYj`obitxy6E4D_t^3q&dFleTH{l9 zM+4=ZtfqY=-%EE;NrXt}9y(;Yj;9uW!ZY>p>t_ij)-O|CQGCkmG>#jw0d-#|2F(Vu zEK0j7YE23Wy&j^fv?|nB3cos#{KbgIj4VkaFiW~tG?oqwh`<)9(!XlwwAdV@{%p$MZZr_Ng5f-Y%9>KR_dq}^l{G1 zS*ELobCdxRJXePaNc3C0&J+70Zt#>z(B~7WM2R0U$DGujY0hxkWrx4I?PJb`D%olI zPqk++`TVU{na1WVR=BoCt}pOrTveQJU9F&-t#=wdkIJN*RjU4$CnnpygM`8n*H@9o z?d9iYc>3YgmbKgrU7pMt#G_uUp*P(9_g;Rn{xw-?!9x`%H|= z{YgNQ0Fn`sm`MCeR%k2FucE0j1wOMdn@Tetz5|BsqO!)ZrJZq`hl7nC`K8-z{nWQ^ z+v@bPxSh0WKDodj_J6m_^XKG^$ACd zfOEtf6%TS2IiSJH2L8C1N0aBockJr4$97u0?y^TqCR*00yf=b?Ti%2@RpmrH_%~In zoPh`;8PRA5Mc>P6jdWnE+PvjxX3tBCzr!-yNWUG+_HCAQd{}DlT70mvj5>sKnXvJ_CR`V zWdQ$$kkw9PHe8teRAszp7?6&bs_nB}^zF3PJ7Telz?o0i@aRleg2ZT88h>SHWo1v9 z@8d<7^*vn_aht^W-T`xtnMuWj;&XE2Jf40iRNET(6VJEuklwNeO}RL0;WKE|<2xf{ z+hKbnmj^*1t5-4~U+Vm2{ce(OplL<NiuwyBIq`|Pvy1xlJenJB>#6ViXib@cH@BwZZcwK4RLGv8$*hu% zm)mUV+sD*9W}YVJah4s;%8G5Zp*(VCCQ8znbfz3vx|ZxUwwX92_%W-JlX6` zRJ9I5v8yOD)tose=;|F&-{=LV{e8UocXWU?V zWqQb^s9iiJui7x46ID|bL?mFc_1`(q5?BnLauT^^dBrTrX*QL{{}eU2h%lZtyU8le zKEgZS$=-1DS$3l3mYknHYTjAkXNW>N*CH9kDQJ17AJw)&Hj`k8@0~SV2>6jk@#dRa z4XtvFmTkbV0v@57R^&!`t0TEeBiw+@OVG#`t zm(!f^-2mA)3dCoc$-u9XGqsu7Tk)|u?{Rlka^~&{Z0MuG%Zgh)o4{e3YYExKg>sEK z0$o0&HCo%gW>PAfqjwtXh@0Bpz86b{ZM*{Mrek5oQxw={*iEZ0h8S*VPlu$Mv89Bu zuc25TX`-z$eulxkS;>RBj2nyjD_63*G}w1o*N6MwHJI(#8NEUqZ;WeY47({=CWg3a zOIYObtgY8HHj;%jrx~`2w!R}r274Eip(?G@39oV$tvR%F{a@g^lP`Fkb7NnjA$*&! z)$(~&V2t*T`R3hwL^mjm$nbC{UVh2@4hL>YVX~U6;>;!6Xe0nwGzUmS-t?8DV{3K! zwDESs?|tc!&oIQ=Bl!27`jfRE=9ccFWLihY%;BZsP`NCfbH%3c^h_e^&QS$ zT>^`74k8v20dR$%xq!K1w$jt-Vr;)+%WDCb%-`6y+ix;T@tOX6!IgJyqbaMmFKY#M zskpt784(VwNW0QsF=6E;k_Y7*JrLkSzhkhRrfdes+#6r`>ehoqHn$;-xv8qsVstG9 zyDX-K$(iC@=EBh6LWv9{VIXCqNpXzij+^nTfAf6ajIQ5vTFg_tah+2=BF%F_v6=k+ zPL|V8ii%r7f`_FUU6i}L9o4SFdMledI_sy;K-qfA8rUqqX{w{VHh$)+*LEWt1HJ7g za#TTmOm~`_9qi67nV&aB0(nSqd~If6=OH^iZ;X4oR>Kuy-e%?2+}F`Z(X*Xh9~p3^ zyzVtrE5Q)IOR#)8Os~5G%xCJkW5besN8j9(aQly2HXw3?G-eA6I3q457Es5#93?~P z6BqSZsHVUzkD4v%Fy?M;dR<=xiw`W(9oSzz&>F}JNdj>$_uF(IiLF931r<~+77pa> za29SEpI#iM6oq1~tfuVSiW_GCS`}%KwGCEk+wv%id^o4Y;-tLR6KS+>p{3TCX|fTb zAja%DDQ?nC;7sKaj72W)(W03nQ*w#ee}v%f`My^gzLTB*$Hvj*R&3L*DChbPK!GjN_+tzuc~e)rbpkSd|n z`%h$TWU07_8J@YgU0n3L^kY3E$8~=R&Ta7k!59^?GYP zof?76_or5pM@E3}7(AAE+owpQg0Agm!bJj&kf*@M7yx>Na_;avw1ah{(ozSR`GWo5 zN5FkDRl0mDvU`r0=6*xzwYDRH01mtoEc=Ss8e!gD%!~G1yh^U+ZLb%qi=E~cp`#(7 zx?x$X#@GeAAe%^{a4T$V6iNk7$hgX$n*PNX+zu@hFy3M0G)_((^Ke5^IE>Y;Pv_n2 z=DTKAxoNh@_1}9-d|hJHT!r3-s38Lm28IzzLe?QjA_-Qeo<-!;n{-TGLfMKA6`E!{ z#UPxi6kS`}%-F^&C%kR#y$SXfekvSSOA<6}BWWjrYs=Om{Jprrf&t&gX7)7miZJ1| zrg6>JF)5=SrgSA~pNvHt8$semeIYL+sIlnpJ|CvCT@*T^%FGM^yuM7vK4)PPs3%z&BVrQ=$r50h&5qxM&mi@y2{TX0Kmi)M_2|+e6X-oB{w42m?6zDX!K_ zC9GDMRAn-Xux$!Q$wNBNyF8u9O8WVLteu&hEoLsimOckJzJz3<>~42si5Tq?$?JZG zKwArYf}?4lWXu_j(`_~G-Hk7g@G*N*`b!uzJGAf0V)@#B9)(RM{h4CjTGFS!?|BU0 zJ&E{Cf{qouMN1Ozi~EC@G2Y6}!yeTUMr0rg`sLCUC=ugIc$s+X zROLZ#mOR>DON(OZ{71$8Rr$oin~Eex*6w|n|(g2RB^mjW9`kxvtnQVoM2 zc2?l(xy{1Unbm`6Kj`Z*;D1oYweS#_Jstbuu|>B#is($OiqH`Lo+SOQK}=pc>}Rd5 z!rpNjx<8`t8tb?-qEU)DyQHSnJy%!6iIW|QEO9S8ZEnpV47iXb@9DNui$pDp4avEoj0gxiK0|(}9 zA4Kr)8jb(il3^@_v_N4QLEAY16^Fe>9+t=DaM}Yw3fx^v(oNn5YjS(gikPQ#X$&Tb zJw&nwNBqv1G5RCJHg?Ui3Kgv7B9?Xt=~?IQS8Pl?ideb#%WA^g9v02J=U^xNB`(P& zi?6lIiK{cgTrdT6bD9}f{5Hpvz_Qz{e)X}oc4emTx0)#b5)#8u_R;`o-p`;4zN8;I zc_0PgJO#gId$}|mKDw3SE;N|^9!N5HZ{`h|0`%)%&js4D;SdJ(hHcuAY72~WSadw} zVX=BcQAOTfbh<2dIiUgwak$8~jxrEbbljPYZNXtJAVL$O@ffzqXOJ_sWLH+h9~n_9 z3^Et2gCYjRgd?B;S||o*a|x-g7R7P!e}v-^cD9(At=JCDjKhc#OkTa};8epMa8E z_4}63JIdFdR0MBNfu6q5U=eCaoInEKsqsib9*c66Wy%RB|X_tm3PxEK6#8)so(sj>Q<4#irCOq-Q>l!R2}&X(0l*6JiAl z4I=m6?dnwK!ZVjFO%d$XI+7Cm&7Yoqfs|((iC99o?FdRWBM=;&#MI){J754(W3PJn zbunlGM#lusG+MvJ$;P>K=+-6!6;+BrFmC|zF`z;a;$;}(F+mA{tHos~l%ZRvvBlPD z*`&ed!(dLX%T*AW04AM81PCMmmJ?zW!Q9ROL;xBHQbI0&#R66o@m1)S5&?=pl-0V@ zCp$Ha#lAAQ;+f^9v9`s82T~HM`rb8_JbBmzD^!q@ln0`u%ERSxC16GbBj|$MRAj&< zt8D_H06x};0Yx(gNpPWUH)65N!zqiUhs4N}9gf1{aZQ=ptUy8%!-PM`b-mAZ3&QI{ z1ISXdaBw=*a}ncdc>Rwbck=g{ZZXF0Tkkvw7;g8Iakq{4o&8?cjt~J58=7!Q$Wl?<$2ClY(p zg|}y^^~4DEph@Yfo`(tkHi2e3$sdWrS>-|A%*-rQF3#4g!T~e{As%u0XpI&TImqam z)(&@VbjxJ=jDV1UNI{y03T!1Ss?*?*2f?ViA3TX(@%Uo{00`;VG51%tD#Jywc#epa zjvS)!AU~3riojU|pqSXhWX8)ESjnn;Xb6FbD+t=2)|ts<(gIrR(?v^maMp@92CO#Lr zio9i45HRn!8s&2gfLPueUR`cdQO>x?j#{uL1(L^*zwVu{b@a(#j8hGRb+%&Qa5#OG zy%{l>wd4v$7kopcY^5Eh#j5GltN_fuC4^{C;&WO zP~bWxb%D8|ZM>C5*ix7}LbOacLBx+7;I5c717IEEQ^nNKNrpYfMxrH&7p$Cnzn_pl zBXGzcLukds+m*~#w<|I>rDPAXa3WvlrtlufoG(JXmw7u-X$2h0{$!0AylY2&+)10**L zl2Uj)e=;TdWk3d$_*d!&@XPILQz0w)ER)mLM+uh3!}l_N!>~J^V5aM}2TQ{BqoWhm>@go_mx=Lb!L!Bl z#*}G3X(;)*UpacC*oK&2LiM1j#ZONu&$5R33B?*~x1f3p@kLwIo^Or&)Rf(bbIE~( zU=zsnD@RHzrMftxmCh|D{0Kr#Z7#I5cC7r&-X9d=vaWIDF|<-%FBk$Hv9_?eFQq(Vtz zZ#AQdv>C4|iv50FT#N-*0acaH=L%pu1S~)RUbB{FOxR&k3hsHfN!`2@E*j3_rc)gM zY@%?J5U&UWsFOQH=xpVG9Rpp((^>PmZ0evS26MT=UVB(UtiixTRwSf?0bY*y>y~!H zJ7o)y$#mR-2umh@%L2mv&oA=g&g}1=c6k6h5RQHE3`S1*Cy`dIXOU{H0G+zAN7Ky& zf_H~mOH$%9L#d>}pI~vMFa`F?nU+Hhi0sv4FlX9y$PUzIaRV=yL;*VXA+?t&qCwGl zbKW=;K3>e)e3uynWCR%oVs|l;*kzD?TWB@$RDCI7t2kTdxmLXuPS!$zifu|qs9b(N zqZsjwNC{7_EFEGsjzmInoN$gX>xMbgP_T!I2qtTIh&%%m4CNfi#1-;xPGqW%Z)E zp#`GeZuXut6N|&77tAuto+V_x2tcKc$UCbG4hnTs`??r7Tv>q9E4Wv?E-j_rsp<$Q zqJt9tyo4pytju=K830v{uiD!wjl(pwCNPSC0}~2l-!C}ZQzYZ-D%K7Q87~M2!NHdd z*3!+xvxWpnM-;|5;Bf=c#$o0EY*IuDz=daAWx&Pi-HmFQ8VDdcK?w(|<`wAh2hcvb zb~#KwIczHH-W8@73x&E&%#!Ah_P~&YAaF|t#|wqVV-N`;zTMsyy5Z=N1Ms*9srtq; zlMC*3#j6ZX0tyZefFZ(jYM2J+5n+C|)nYFgcz4V%YYBqGbghg?0dBJ04q~10#6}Yr zX`yNxpxAr!P_sqmFks*Uj zr}_};Paa9pv_BP6YfFIVpGRa_xJ;pO=en|tPz<8P(0oI1qChZ*(KAT~km*(N`xmWN zyIofZ1n}rj$}YY0C(oDWQKP^$q!H`f|AnZA8k0YNEF0Drk1q(N(LbjM^D5ye@<{ga z7_WML6O@zwzZ|5J9Cn{RTs!i?#^{huULWK1%dn9rsy1~l%PM2>o2FcBXZ=z=;WyxZ zOf%~c5gnbLkK9C_MG}2dYfj3GO&fd&UA*t1qVIv~{a?0~0*Ry^u6U$s9Y{{$pPM@M z&%0YB_)S-8Q#|_KELsjI3IHJfJ~2E(N~4N(GE0n#f-~Z{&9fXy9 zr9!2vo_N*&whe9_J#BA1vRh%LM>rv&{32~us`F{qaQu4ho7$hn7z526U5f!<22`+{ z8w_|&SRL|gcA^0YMo!W&+bqSEa$ud7w|mX$rcnuy01bvQ))mnJ3NUNg+09K8U$NGw zlYq@^CiG}J%J*^C4E?uRfg|?AH*WhaAv3!BbX7C*3*0;G4gi+BmR_y}oDnj)G)dXD z>y2tvdf4Kxu*imb!-u%+PtADr2m!7yIX17j4E%!iLKtuz@qn007Kc+AW93 zU+q%(Tw=h#Jm3-EtPGr-ZQBuw#NvJKXjnQd!d})d&kt}C+{|gt`BI^d)7OU zQ4lsP)Iy`5ks$Q`YT`**lGtFtK~; z4+s@aL%%qm_P^ZFQZ-$R>9Pq{_P-yd{5Kn+75rPTY5n@Ue#7YD07gK$zZ^XHLEr!Y zCZ~g6raC+T05$xpYtGO5?K-yzi!QZOwA<`pBzTEnpp>?2m)sFdKx4Nu{z`Ym7D0qb zfTU3BJghakB^QUL^lkfkK72WwyZbf)T@hzLtq=M7A6*3K5XOF@5cFr^H=6b3{d&1q zOHtAu$FBeCY>2wKuVY#DKiB+}e}KOF_qOeRSE2ujqDSto8`-@0Vde$I0%3fW>A@LP zRPHeU!t~HWXg(C6!X}Dsv{yM3h78F)@{j$v6vZ+e)FFyW@;w`Kra;)s+f%UOv6sGO z7OUHql$_l*^19mOWHw&TdcKu{$m9D35S+3<(n}vlH8O71l7Gp2Xq|G+gQCq;R7_U& z71r+-2R@a&Q)_Y%aCiPA431&;8%OHGM`_@@Q#$#}E`J@{=iTV>w3)pQ|0_qR>DG4n zUk&>@#s0N3z`S5^au>X}I|YEmO6GXfxtY2QE=R*L4a}$OXk6)I=a|l^9lC8$Tgs~a zpE6Wz*6WaHL=TyNv&ZS7Y!#2wIEoDOcZo8~P3w7zT_9eD-16h;9=T*?zRvk0U2U1- zFiKWup)ft2?y28w>BR5LE01d>qX5XPQ#rQ&JBJJ*unR!D0=eiAHq(Hv?7$G6K?S^X z)vX<%>`VkGm_VSb`*>dWprg3Y%kaIy;BYTKC_n^z%I?0KHGhu;M8JDTb3%Y3w1>OV z!Vdz6dh7(_&*n|+{#GE!S_`X%*Qc9>%?v$$g08Im21FOG0U^?nE7&`5WxKR#rzy|x zJGEm6S!780A2WQ1#kPEhz7O8kRze`xfz=6hX2JOPQrRd5=jAcJDzibW65*ACTY;=l z>{KyO4QWUK7^aX23E=V$JrYSIDFlByX1R@{!xvAI+&G?jb9`MHtL63bu)^^{GEPZ% zcH)WUqmB`$^D*&&K5rgmfvBCb|5R`w7%2xBPn2}%h^(hx8x?1S_qW@6#x0!Qb9eJ4 z?{xTGn;q6qIg80-_-|n$BW`jMLROJ&jzJ2ww(gA#k0t*9S$Ml@H540e$NBwanO&{Z z01_bb>t7)V025W)@I?V0q*1SY?__wpVNQ3X3<{^AIySw*0O0oyz9J3ACXUaCIk1pW zErIAGF$f1UFvzk9r|^3WI$Xo?jdNll^`OW-$G_hGL%RpAHM!XJN4e&=}l;z!Q|z84x#vYY;hOEqQHkw zFf9>EP%&cg3e3d=Kb#xC7AY7l$}x~C@F=Y0tdwC63a7_LA0sz!10BzK@C?|GzvJnF zHep(1v$-csV#e5mbM7A*ER9=9?EJG(Tkmi^Gl&NyAbHV57I0(=9E%OKeddmk$#EG~ zf=a;_b_tnUIW_I|Klr$_t$ z-EVi&aC;T^7kAARkMBg;3XNXg0>gxv#@8s6vSKG7?X&d27oec6$uMv>=Lw66dv!w= zc#7T8x~t>xPemuZH9$yZL3lmV;ZR*)Io_Hr0C}<2Vw_@cI=w~|gaTyXklyF(B*iBH zG&YB&^KIMtCu!;OXwzgxTN%7kD;NUCCcJY&yU@;%?pa<6Xy_B&TVRfzHhfS1$MFdTj=_vz%|bdkGzBG|3Eu%H zyh&;IW*Q6;P~ALzPL`F2H}$`J4Qt%f{0p=@!^03yLVRd%`6j&1*tyGpC=>u%6*=DS zFVXP8)PLLGfbF@DfBYuzNll-S4}=YC-bL2d=)QE>{E|+$S>0Fh?VZ|Zcghm5OQ0-D zULyYedDa(-iziqe2uSCpAJjagvo>(4KlV}e-SUUZqA64nj2Z>t%9Y^Da3vo3^CWx; zE6ZN%n~uNT(~O~7EK?;HK7ZonW}Y&Z9iEZ{g>HsPLf4^tVv#s5h68bq{kK7AoNk_sbOAjR4*_~ zrx-J%D6iVL_dBbIkX)eIB%=kR?1N^3Us!dt-+}Gm!qsb?G>g(8*p3$5sM(U+=Grul zQquafB5QG?GUM1pQ7yMP3@Oo2OwLvESR|hSd9zN@?HQyN6c8y+_NFx3qCNHSS_d8t zU|m@P8Aj&CB3TxLZh|q_uWc2fG~vRCQLq|^CS6J(H*1o&sWpoAQpw3eQ=Y|(h_?OG zpgG8{?-o_SCrl{?d`gMS&xsa^lrC85HNu;AlswURsFD!77>Ttw1} z>xF_tbySpRpi8uD7zKBftE2j@u&B_bMCfQ8vWn+K19QI823N-2v+ryZ0yDyrxh=;b zx^WMl{F51b8Ex0WO~MrcD8X7H^B@O31Hi!p;3*Gh@M`aRoDP>4ow2PUa(q51I=rqB zOFvV0liIw8Nb}KOxC$36?$+9wulBs<;g$mFjLOPj2-(%|8Hm~5U8PYA+g2MVm4@T9 zE69kDM1-9as`|Nv_)TYfR}s-Fy;Z?hpMejZ&%o35Qmf1+kGp;k1yu)@`_^`jt(Hem zcdGEZp6$2JlKQ+ z01;~51j?Z_?1^j~E9ek-*@*4%!RFsz+typSmlwKh+%mwU)16C~pv>+SZo;<@mc!MA zY@A-0kBw26%IB=%q>URJLugH;n{6O$&}H~J6XShXgl7ueCbwIj&QqYs;d2_Fliy(b z4JP@kxFp^QdHk-)Y%#GDh#1C095^6|hD1VopJ`h(W$J6{b(h$NO?_qNhJ(OZ6Gj>4mJ*i<1wzhSovBGa(9~MP0`+sChMesX&;4{ zfiK_QI(IX!N)feq&0!&9t*l*bw_I37dihq^JHr}Rf>E98u!`ZKb7-{Y+b>ERH@)o*Pn3}^=am5ka)3!JAs{|l_} zy*u%=dkPFK3}NVCF1rk^6x*iYs)?6PX-L;LekGZ_WH9qk@gL_knLvid#g^QLCc|ih zNl1+)$y(AbTA`DcR2kZ|F@7Ey0IXMt@2{|>=z`@mv^MXq5fd*(7Y*M)# zE2b-)Z~_~~M%~wuehxvWv6lVkx}6?mr4&Y*=cP}od$hieMYvQpW^G|QY>DFJP)`LX zO(K7L9BH!ahu1?|98sPQW^kRB^XhK+$VQaeoQIRHRzjkRD5CTe!CuZWSK_4pN8k8B z54$U`5`{`iUmyJ)_ZRKGHHD~aJ8|^oj`^98HZ~6?1<6Q*5$Jtv`9;D2 zcmqY76&dnIVnfZtkCz#6%)MoH&_1GDm`; zB(S>WD^ABMu*w-R1(^)#anhBANmU?J#23pPUvckq#>#!FXM&j-KgB0f%zt;#6Q|SJ zh3MX~8Z_L$V#)_iW`3UwO`oJyFk@y-L7n!KC79;+I$Y<<>8oe!+-0zOygiWM8+8DP6Q;w5H46 zmJ8-dq*>3xSIut^3F9;y3hpLuzC-}lf`)`GG$vg}?#DUD^}8B(ahRZxG#q&@H9Q&2 z6!;-Ci8_+oRE8=`q`nI|APUJ6M%1{*uo&7+-MeiUtzom3h!Ms$cG1H}udjDPNwF*D zFFk<`TW5>;Bh>ywB1g;DOX1Bf`6bP3N^a`kzFAubMEop{01U8`4-#GP%dB8>eNa#x zmVajF7uDIYVn~9PI7u9=nA{<0eCHOLefGrR-I^Qof>le3cANLprqJq4+wBX;KoI~h0kjvrg68dAlTkS6GsNtAXuiGr5N!at_7Va82>=WZqTKUxAp-~}29pXoEN{pU zv0H4K@C(3@0wM$&%?B&74S}!ana0=-u+~;{|MR7@8=Q9l0MVu~g9evmgifJ6+DnL! zhKES~9wP9&6PJp`JLIB?1TZ+_m~K#|G{^2>Fv9E&bQ6TjiZDgT9@%J1p@pTNME_z1%=J?6!t)Xnzb#}}8CL7iZ*Oy%SZ zf5R%lhE+o#LC{g8`B@>Ft-Nr%30!tN8D6=zHo3^O?ylOt!f_?`0S7N7H#US32o7j(a(GRa?%hUtC=JHNgN<(n+xmrs|G@*BkQ~7dlprHC`9; zJl4I0_q=@$K2I90rGK#^qKcoZ!@TrSz;DNG@IeJ%?c3Ma^TvLdXt=-QD);>eg>fPSR z=673K@SJ}eb|@&j1py~qZiFFbYRa|qUJyWcgaD9*cttO7005c$vpzK@1>rmE?b=&& z&a~lp_STpLVBK+myy1N9el=CKXO)Tl`QJ^T1n=9{wupzOh&8aFY~J`QT1YAAB5?>p zW-L0yKW&#kp5QxgMD^=BRtG}%~YsECh?6#9qpd`=^-?texH_2C3%o`@W12)I4< zTJQ{ZpGijj?ct>8E$gp&a+7s6cX(Tk1i;^xf{n{e54*{76OK`*)b? z1TW8no75v*{1hU88`PN~BHi_U{rcVPHagw&R+1Mjqv`+J*Kz74VD3CFT?kv&M@EDL z5w_|2uVM$>R8QwZ5N_H)8x7Z=APQK{SYaRa@&93%L2M?2|91qX@I3!dEdH85=km!& zpe*$=M>4uQ`cB{djMuL3RmYNwkz&sYUiyGmC{&?N>FG*KI7K3rP=7aJ&WuTQrT6bT zpXzZIsCQ;zW_(}5_Kg|OU5NSLn$B`WSpM=$rD&|x143;!+9+#~t?Dd3wXE>Zt%3LD z#*G@~h};i@*Ax&tJht!d-5$`S=3+_=1tCw>n+fOr&lO(~$o$ zw9aZU)_XmA>+p99NP0qgC7sgGfzXw`vnRa2g2`9-q!RkL0l-X-af=uHo~I)NtBFpP z&saD#zV!}5&gd6%5t|kcGvzn5xFQpiv@jpC-f+AhjO08GUt(%IkN%$(pw)C){@yL! z=PBWks;*yZq_;f&KA-pYzE-ZF)$gGdDe<4rD*x=oxIsF~p)q7f{cUJ{%UIp11xMX8HhljN<-C?VZ1x?0CK^*U zOqJ`JuPKRaZK%*D{Hi4*?l;P+0`oxw*qA*(TV`?1=M7;9%P~ItjS5HX&;;%P&&OA}ElsMq)UY2^_+m?}^Ja@C>RpP33<uh}4i`q`4^;;>1;h6-Y@L6U9dXdKuQHmLm$4|#TFB(WxQ&Mh8m=B!fxGFw52T1$_FgLg}h+vGAk9CbI!sf)_KBZdc}zonfWsmAnE%! zgftAmt^H?WRt$f_;G%J%NV|-tO@}PQM))_FdG@nwV&Jupl@^OdGG22{nmx{g-c>dI zVdhekU=V~aJYW#efP{t>W*Mq>G0d-&`vNz!(##pi=Alk#e5x`~M^OcQAd zyZ-a6^s}4abIyjsiP#|pIPfQ7*z&Iiatd}Nhb!>z)Wp-A!=iIgqpC~hhtO#upl}HIm&xpS4pXbKC05YScB%0UzUs7pVb^+t4H zR;jx1R?YcW8rpSv5mR|QCZ=mkU#pgP&hU${S~1Lpz7f>N>ah!u6zzD2Q}92tKgx6q zO0~BM?g|Mh8eQfh?$9t*>QWg95Jl@GAZTzJP^`gV%R=*K~TZ9;+900uCK4fNh~Bh9ogD z1y{P`?4=d~1>_#t-`r)_W}s?>pCgsxpbQ)u4Yo}Zn?b41MUC?ZVKism9<2hqzut57 zq`a0F<1QK@t4&&J&pismZ4IE3O&hjU+v*UK)W)i=L|51b4JbL@yC#GI%HWx4AVcDF z9Ew=XV@W)|2HM7aBf~ku{sPyo3^X*xl4C|gL^P1x6T&~kOOs%R(kcx&a=L#Pa8P7l zSz6vRcXgr4q+C^2G7yyYef84Z>wZPMiyteQjLsp+*YXG6a5Nj1%>Kn!$}SJ~*DF=l zIW_1W1M9$;0oXzTX;oQ*rcn;E0OOp!&GG3Db=8TtpGVxe`UOfN_}S3lc5;7>)pOg~ zT#MrJ!L2VOL3f`7s=Y6z^$PZ7r#x`E%-;}f_lx;Y`4$vcRAaWlW?JM5qrQ{=-|06f z=}bZFCt5{N)GJqR$7Sy}`#Ru6Hrn;73in(q+%Audfyw}i<46|a2I-+7n)`k58!2(p!; z^&IC%Sz%n>Mo%ZlNg$%DCI;G4@hq=hIfE_q@;n*9%0k1z?7Z0}sLqs`QCftD z@csOXCCTY6n;Lc8Bcq;%9)1!+T%EkG4qiNJ9UeyJz!gV|YLE*dq>ylJB#@WNXaOXD zb|jGu5HFb01=zF(?T8KshD8kbO@8*iB_NS`p}o5WeFyyPJ8Sk@ebwd9!0R~m{8mn? zS9N3)o{{#`&fFjJo~=BZr=O^+R%FhIyQV0m0fVeIg)$G$zGmLOGHJd>Y*z~E`1sn z4?u3>-jo{QB#a#(2qjwtMQse`VU3zX8)>x9T307BWXY41r4bXy?SFstI}y8&CSZYr6U;7T12$Aq6=22D2j@;YJ_bo$)wt-VZ_TU7Mw(x zki&8UiY!@TR=-*E`R*RI!r%s)Tr>$LG>`!a3LF9fq=;f61&chPXf_Bh^>I(Vpfr7M zc0rlzRb6Ok27$00jLl0q`cf)(CSSCF^P;x(=@Hmsi4!AMQyuEwyBB*d9GJ(_myzwlb zYzm-jE3ot9RbqEI+CRM-W&^rJ5LMszr2~MOALcvXlRbKMYef{2TrIq%2p@-hB$Yeq)RYqn9YElH5U5xwun7}hfxT0>!8pK)R5E^~|A z3z*K8jGAIJd~&bahBNoPcGtmGeH!Gq*-5qcT9;m9WLT&<_hJ`#j#tSfijkp@k>qw6 z2RxqlnM&h(^1|f!C1q7K#Q>3X?Ud7I3l!Q8UcdX6p=*5cwup<30n{C7JJy{wJWqb5 zF3`k>l$VVFOhIG_gh(LBfJDR?2@ZY$+T+5Mp2m$u9Q4RL`*jc7P_=JBHRG{jd)A*< z{4Y8My83$1^n!o|V1R_SXh5q&Eo65(glGHMn}vk%3Sj#mi+jurBx@s zZR#kiyZ9cZBD%>k%QqH&9)f|e0GT2BFr`2w9YkFE(E(7)IR*C6 zrTk@S(wK6iek9HWNs>R1L4xq+kp2eMn1MXjAEgN8o%w&>T+B%Q_3%16HXW^xi{&0$^9}%63jmrs)X%iO zRGtXAoqQc61oG)~9A`(C9I)#LpB(_`N7@x-pIp+B!#KE+u-ySDj%X*q25w*he*j&u z3g=f!Ys?_1l^C@UdeFd($T6!<^LN!+cyK@uQDgHlu9s2w{vG9K2qEAEvux#GS7SDN z`I8?8{2X+E@$h}wlp(#iHvw+hs-0^&-Y7x@p%W0x%1lUqh#9%eH~QS!WC-wP(9qWA z_y^)|G8;Eor#CrI7(L;DG1mhug+XR)5j5nG@xX!L^=*C&)gU=wDU3^POQ1UaZ~B6!@$UeHbK_f$UN92@ z4`;8Hz6av9{6UF=7#0G-08xAc7EBLd5C_9z4W)!ijERYUu%_WuT}&o$z!%{)Ko+5q z_^>b(mzESRUef+Eo;fCzoe;cKK?6qy3>#X)$#56JdN=a5<*EoUQtiL4U>@giO-Nyy zy3pEMw{z~8J~!=Y2m~U+>9e+PI)OXo&_D<2unj-u8RV3(K02`rJ|vv{x<%v&8aN|0 zYjAX}BB|ndPlwhrE6Ix!%d!gE;EaHN}Zm+i^t*ZQ_1MOTb1w) z^!{h@V<$Aq8MHbL=QdJN?dkrrZO88&0ci5}YwN?~=r6fV^ylM{(Pp=K-eYIO88(fi zku@p_w@8`Yza$A&rDsh{x{5ioQ(OlnjmG2J;p_vD5P&yaFaqS-#_R|lVFhm`s&p8H zgEVQ#g{qHmsyQM7S`NU_oZI}YsGlRd-w4bg6o^3@9{Ogqhk6B=0d6Oy!_^`AK*P7b zb8>SV>>Iiec5(s1LFB!>S5$ewpve>7zT!-eR18L4coMjjv*oB@40`g|+r!2-8RS@q z?+12j<^apB3nlu9ncL@BRfT>XnqayVzzakj0hl}k=%job+(g>4o_NMRnmCVidfJUY zw}-929v5-5VlEcX$IIIA;z{U1luJ`apLsvj7o+q3v%9>zyT$;_fG zpJE{L**LAo#{_@BoPRrmzjQLCun(I^ph*Cl*cn(g4tvc{)4X?13P;iur`An4`zR2g z!2$}l1|lpL15ic5kvI{kfRD7@Vl1~v2lKtsW(gVCFsiJH>*&^*IGZh_0y4_c5o;YR z0aa432Sh?91WvUGy1@A|$UIeuX&lR|!a2&FA0#`SI*zZA~9yGEw zV-%Qx)$aRSwIRJ_?4uVD2vM29ix!U9@j(uN{0PN&y5NcjQAed>R66VQ#Hi7bXT3(O zHJ*3;YM~XC(kK2<*(;UYKTNM};)BMHtVn8tr1rsfbzy<2{*3rDGCB*ilTuzkp;IJ? z<4H!Dgo7)$MrAiK;8XR1?e=+M2oOp;G08K9=+p5mP_5xXc7=JXfOvL!H~u7J5z(1U z8Wov9uuaU=stKJNcEE0?D%7Td2c2%<3EapklfXHn)US%b47fy|y-j1lfN`j3qy%v0 z16>}C9D-KPYNQ#E0A>Ji_u>E?5ZC}g$`C*RE+fCRS~3Va>jqftR@+E(A_wr6+SS2hS{-*2tu`T7c5 zYBE}dVZeBj^Hu-^q*xJ6=1~h23+v@lE)tkdWe}^UnO@i-6<*YVI19z#iL^xR>_E*9 zR+>k`q>K%!&qyy*ifekeEU^Vbk^oK!ICKTiT(aSlyhtV`7iBq=ZE80Uf4fHFI=UVU z`Lp$Uu-2GUs!5r z#cmY_iZ~ev2>?V$BnSc=U;q}t&5D?$gIif(Oqs|9HSFkzIrH-JzjZW{CP(1~r(uJDr%9trf}Rmx8^1rR=r_Gr54N#>q0@~D9^Tc;Jkx;jUkxl&Ng z&wh2aH$vM6`;_u|BQmp&_Q`H{WH8)~2TmdbU9Q>NUbb-2Q|^Qy5+r+1Il3%?9f%70 zS|K9HuB;64Akbu`e4~~}B ztMnEf^I94+c4u(g)N0{!xnKDIGft6CwKh`3*RIQX3>5jOX4+DZr=a-|y6zq$NV+`* zUP?>jU`n-siasET)aZzzgMP`+chvMr5a_~yLn|;CDY<7I9#udKR%pcmQuU|deh2|T zi}U$OZI`>JSlGXh^_#ceGD+1julaZfi`P**I?c9xxIf=`Mf=DBTLh? ze%U0kRH#j`C{E(6p2^OwZut{ctET>TJQiRR-XwD81MGE7ryeS-eL_pPkiZB_L~*RQ zSltELHY%%U4+DEb{(2JNJ(Y}L-&iq{)87moYI~uYPa|a8;q7>9yZEghm(P>^u)16* zIh;+8+=~dzuz{xAtlJ^;o}RQD#7%?LDW)VAf(2|naSYRpt8kd-Ts&B_zato_ObGOnL9u^gf~gslMPtvonEvOpTWvMfl(9f^OCRhFf33f`FGr zd&$a)8Y2+Sm5bvtRr$I+1JBQ$!JIrJy)aD4hIL2sKcSk}cSgkiWX~)19GR8aevTm5 z)n~0BQX^HeQqyhuGUd1H_thR%T!z^}RTKgwes8$w_7_-$sVkeiXD!Vm&4=825FXyR zDJq?&iwn+<{k6yWnr#M|4N3;2l?c8+<>A$T&a=hyt=H~YSnk!IK*_KGyBEOmBEwUT z+Q25j0zTAcj)EHZyF`hQm@4_%9~jm%1lY}GL_9F zN`~hpD5xpqYT`+>RV3p0cvafDQg*B2;C^)JE>F;|O4L$aosJ zU_sr`w0&JaW|GQ^dKoc7b(&PC>)luZmdNA_a}g0NppjM*N~t7^0!3LOtg4Y@in2*W zimI`UDn(gRDyqr|hTDLMZMdd5yPXbd&K@n+8O5N>&gYH)nfCopb9qj0YfbA%2}fQ? zN8)SE`cQxGXA5sxbhn}F_uG?dX7hN?BPTFrG&Ybl(3!ANY~Mtdbi1^`*Sv;?!(qqf z^p8{pky0b#`E}%ypBuht?p^=BGYzokDCD^#f54q~aqc+?)46gZuH%vv%Pt77Thl=g z)L-Oac~U*r+c!k2g0rQfAE|IGRnO-!ZyUbb&pZA$e9a~kuT`O7G_;*%oe`L)Rl(?} zP->zW;gxMP-ufVV>d-?!K5iCZRM{I6$QYx|u?I^0_p%%E-7hUJ-}aN#t4T|WRZh3LvFL0zG$~3fG3Dnn2k7dIwgaz zR-;+LZxRu1NLkOo*efQMy1R!7t>af36eJRHK`jh?g^F{^C=vjG0z&~5qbA3lej)pt-u)y;5!6Ty+qHtc(L9r>sT-kPI;1nbd`u4?O zj5MxQ-bO(=yR|w6~M4Tn?=1Ypf=#j-JACbCXp}p|r{%hG8LV-gwbG^f+*A0Z}syoZIF*ZH+YlGvCrEQnY02oJcm0VdL{G@!Wm)7z z^M1nZ!W{1wK~4dbYiP>C@g^83Qb$;4y2GAV0|H>3ClVY;A_8(n`>qVR5dd1j*$4oc zLWLM0yLio@&Fn2?#H>@%vMHb>ipWLffjTG5(gm9oH(C&pNDGuIiBuC!9ScR_!Cb2* zgct>FS$mM1Fm!E82bcCdN4TCpzSt>b<9LsIs%^4{%}d7&i|f35%=EG4FnDm|0LXf&Bp zlqU|`Aak5e#x{Yfr$Z`td#tjH{Z{Jk>h-zj5&)Z5&1)#61Z0>+5dtc~ zA_2o<=MOa(HfExuNf(`sw9!GFo6M5r7Lm~?x>ABQ#3i{ zgG$2*F${ENW>tEim6nR`0JA-MZdQ?^6^V?6DYog7l%Z0PjagpEGGTgbF1O8KS!k|S z!Y8R>RxGO*WrcK3C?O*G8iw2?P!-xCMbJZ&(lXngdW25?)%Le$6^k173Jb`!va|{( zMTm&)&LN89h^UCKY1wu>K7!$^vcA(PmNUQe_qU*OcS}sWoFH)cdIXJK_ismez~6^( zEiLCLlNJ%HpETBcr#(bU#RCoOdlJsu@J)7Su5dd$W>%+}*EcR!_F9|66%^JqJ3t6_m4wvI}tSZT%(=tM4athvk`F#Bo<4;5O_4` zIwHvSADG9t^;Vk$1s9hJeNDy&MalCBHpaD)+htp& z51oNu({*mC59LT9O5G#~zz8G(O?ql}x~Gx#Kx&DNLGq+1%|XWa8V4-15VM4p0z_`# zN+bj}ubJAXQCu2|2qFey&o@2Bl3}B1O00#|q9iME*vg8Qg``^9C6#PRA@t6W;J})9 zC50^eu%D2mUS+_?cPob;dUiflqaG}KN$oB~@*Yc>)G+MOqu6cWAaSK)Ig_M7=Oc{r zGEboa21Ju7c)6}I-XpkUq@Zj_Cfyt_&%@upVbtnJZn8*3BJ?EcV8;aO6)c8#5nC}E zmL#^rCO3&TF43$IBr5K&He>KE!vrJ{BcS1h*igzttqK>8h1WJvk=Y{1C@US36)XZ8 zu?CejsbP@16Ax6$yJ3R@3i`5u(G(TePFM~xy3Qb1ZNO%Tgww*q-XL)4oim+OT#iLa zWgb~VV{Q?SO03ERi<*@OD$sEq)oeu1X~7Yy8{RPB2Kdbxfh49>-Avw`DN;ivB?*iq z)VW#fVoZrustAgr*k_3sfQeieZerk(TT_Gy-)8FN3Q8f=xwl01ZCqhNp_9sXjJL)w za%Xe1K!a{D#b}gMy$h~N281Y#I1pJ^j`E6$6$Q6~10=MoSP>c)ZFEYyMhKD01|Lb7 zrps*=*5Sf7Ef5Hd-Z~Cqq`kGA-;M383Gr*LbFIQTB_6gD1ZdKi14*(iG9q7OE~6Jm z_R=865K>86t)?c5;*h1u+0uY)bc|psl5y1$3kWi|G-3yIg$g?dOMPWnqC?ZLcP*&56m?vscqRXekgiL5e8dqwDfyscl$Yh?Qnx0YiI8!)- zQOfe-`W^2!+PJ#HZxO4VW+E)gFcC*8pfsVFw<(=Fl#K~R&7kCj43J6&BMdic%X8ife7WRcUD3Pco@dly~mfQdhmRpSz|Yv;N+dR0KlD6|C~x52TyyF!||j<~lmG1T)iVCyd{r3v*%& zHOnMO=^Seof_m!_c|?J;ZETQA-BG0C*g3*%TqB{urdJW!bfT!q#!Jg?%nJk^VSzHG zSj-kTovO+Rq!LIp19oY!Zk32?10@CJq1h1fMjS9PFk%Zd$3$6G-S3(Vm?T6PJ-LVo z$S!K-T#2e>*tB;+7n36pprCxdPULTg)tTcOZ?6mI0#2u~yW&SR40Ro3AiQf!lon-? z2P0$5$;qRFx@DVcbEPF$yA`F%f_H(46j*-Wq)CyfGz4};Tp~rW|FN^j?`EuWb7p0s#bVNE-cy64Oh0Ecq>84a(Ym_3O~B=BwI*|*O#nbKSiVvr8|Inimy zM8>5ZjkSnGZ2~mcXmW*6@~^WJWkSaq(xk40yPIhPZm=ZS@y537B3SNNn^=%+NnOlR ztyqsi=ClwjZ3+q#xx@lUa$}W66=IEi3!B{@yn;G15Xn7Sq|_l3n!Y$9NZ$#iuHs!{ zD*{1iR242NMUynw5 z=iVMiP)pPHJm9sbU#_6<_1bn|4$bq&0-;X*{r~isgdCy;1ev+vR;H;A`B! z!)X>1USGHD`o8EB@UQ4Jt`INb;egE;R2o*Pj3;L;wj|?1Uu$P|mlwmFuAX0W3<81i zkc?GHm}HI1uNQbMd3pMq< zbgW-XAKc=e^s;{`^o80dc%UkGZC{%4ca;=)e>IgJ8Shso);@~N7}cmjGSX{=YMGYp zswibMIyr(mO;@sZ3Gr&e2?DJmx&w>x4iTr(^0U_YMOOnMBC}z;t>*M^1`in20jeAW zRFhU8Jyrzimk|xpL=s3Wvfa^8BB9KQ;*h!pvBeV#Ho05Iv_++OS~Y4k2*?I{%w&$PaMk2bA-}nP zrdxv@`1rn8JLihqN))f9e8)t|i^L_ZxT>gvQG(KLf^-rka~EhC135l^z5EzRmoCF}Hjf(9AC>V+{@Gau^nHbLE(pB$^$YwUQNbhN`T!w%Fijx}F zYL$DT7+s8YsAMutsWN0u=R!>|CNhHr$hL|QiOt+niC>FIW#BB;unUnGsa&QjW~%!x z`yS$!WEUf0U73+)ip9LndfA8XusC-VyU3&_muR>z(Fvg~bx(k_2}GkJLF6?OP_(VB zm}oJ4R6TNJoN8Qj+n-ID#w##60C6_*T&apQ!h%IZLVI~ZqfRyoB-p%d#*H=C%ILw* z)z5w`Sy=&QFiM8awq)MS3=P%Atelp|dgD;*u-CDtufy_Vz;o#5rH8!s>L&jC(`f&o zM0qF-5(y;ge`43Oyj-_fZ`*BNwIeF1L@|tpMXugJ8F}ix{#He8J~?@M%lFuwEWT%z z2?VH-%@zH6XuvgNjDJU=b%-+sK$t((0$K2G!oiS zz}OQE71JkOIstK6LpGlPJwU?0cLVanJidP~RX^vcOSN2bVq7vx=Ae&_m*qp7^nW6x zu|pF=S5xzbcH9=0G^_^A;yZ7&Jl3~<@xY&@K5e?OG3%Gl|0C1R3d2?3?$!2J!Eo{E zHWELZqEnOt$aEaciLIsnJt?P|*4iPJCzTsc#YKoJ2~>juw1{B_vmTq`i_|zVI+warc#7s3K=1zFB^kvq4O4b)XmX6>Pa?hZGk8B=idBqz_^3UG!=@9?+cEFo!R?~x~PHb z+^a&Ix0kQ{mX$L#`)Nw@2u-y@8GDl!ofngrCvilAHofGf-9%?0du$rnQ-(HN!%#yi z%ZU!v253h{M|Z|`olRpl>$0z1zl+vsy_L=0@+9k2V?ob7DxeiTQ0S#&5F@PwhJx_;0$79Y~m zzQ2Y4OBbVIm(GCyH#^J^)FcO#g17VV*w6117*>K)l%Nm%;rUfD;?ud}kHf7^nf)pJ z18CxX-A4q6??^1VLR@>^#a*+1IzhK-ISN7@AqFz)N83sH4?C}`1%?nF(dWzHhDG?U zml)E|3c)uYmwsC3u7-y7-`e2)uk6h9`1{AJ+LXSd_oKO>zY^C@r0Nh*@RpR5`Xw}Q z`R*?$MT{t89Y4$pFy6n6_z$%_2q)*5GR;Z#oVTmmQp)}Qgqy-)2ydta;G)$pbM=I%@Q++g=p3vX5-@nGw`37lAbcl zJ;eK_6bN^j+VTz+S6(NZ`zul}NR(eFKcfI!NB}Qn+yKi%OET8mRcKPge6hw3E{C3A zQeDSGQIKSKABytsEOumOaizLwin4`f?7vPVUIhTyC9CUemh08Fb$iHQv#ihGb#BAb zcg#Agh1B&I@))y1G9OJZbktpg2NX~!f#LvA2cTs6xRdsV|1qa?DA!Qw*79bJ$-fsN zYx1x2Is8k+#ymLN=6AaJeu3zf&EmvnNQ;L^pHZQYi2u##3oCq9DhYJ4&(Hgfd<@?(_OZ?Vu5=CrCNbZRRiOC!y z{WKV-+K6IwoynDPa4tSY_xd7B9&U&DtK*vmTmyV^A$qw8yA7(4SQp4m&`^%L5tD`& z0IP!qT^DPrJ9^PPw*dIi!~-V0{{9JxJ$}8&btN!DXlk8QsK`;cb&uQ+I^lD6v|7(T z^SHA2QTLRn66a^@Aa|&E%ZdjiQ-iWnB!R^89tw;H9*$LzZY=2G7A9|}A&F1}nHZ=O zCWoUAfyGcim;iJ?D9;WE|^aC^LNEYJe5UOeIGDqbeQ@B<|ed-Cs-H$S~4Uq^er;BouJ zBEK(93(9VH661192V70Dr*I?*-b!v{Qh>A8_vA)nyM4G!1gc7D!;|HcaHZJ}5#B@S5087x*3ho>Tx!H;Rd7h;@3Vs=y*r6 z&HER}z3r(-lh;m6qKIypk;n7|qQ8~l;_^R_jjjC^E>uktif1Z_6!NQ!IMy(t9XCi{ z)A827CVS~ex$Z=%7g2IZiGFEyTG+|AC-gFKY?XY6YE)*MF)(gFdu-kZkFj;zYvhlLMy?0w^qaPye%c@%%@9dk+ z;x$3E-xiVxf5{{76U$Hx+)+t;Haz@% zea_I2)eKM3oxg&7Ce|0rfX_n8>Tm|0sWQwr8x1&G>W{f5yTJYMzXl-=zC}txesBO0po->nl zFQJnMk@F#Y=T=~|7IloxJE|gm1X7MJz1|6rW&Yphx>hA1ji1&ub^bmv^Rwj1;-;1& z=AV!8GWP5~+`+lv`u`ky#w(FP*`G7*zRimPNALWMT?|iBmJuKRyCNWQBlAlte|^eK z-|8#TM#YPwu?6EtwqSNe(MEn{FVMJ*7sJZ~@7#o_P4lf84Lh8wMTk5C0rY z{$0!%m@uR}w#;r9|J?gOjlO;P({O+cAxXrT&xWS=d(LHl1@uy=`K-g^$gG=rRl#Y# z6Y)Ye0Ndn?w_oZ1Y-9W1uHXFM_s(@8b!QJ}$IrVSc}K)&9gy!t0yN7ie_lmU4v_DA&S|F>!BDZ`hiWta8Xdp3g0Cew>}TgEoOD?ut9 zLofZupHd6HM~3YV<#vPb|fCJ-mkFi@X-Uu>@G2F zosef@SSAo{d*cxt{ExKxUIE+P z-~B=oRc+0bWVmA~RN}w%rcX|@BJkG?1uGk=Qi!QxO;9n7NhqnMck@&+v@;er)@TYL}9n;g<573o!7foaHFkkM8UMU4ciTz4v5$;3e< zM};*37%Cc>daGkaazDqOXF`znepl4=gPQep1Iyc66Xa~8%Bq0{DQ+wa56V3Rz6p;= ztBr{11bsis0U+Las4?b`Xv5pG_0ZMBjc41pJ_ed`>WFc^;7w0VMGoL5yO#N8N;L@x zgO7Mf2ma(?WIxG1&Mu^dwr)*%hc&{0?>N^njZ$8XwJ)sY8$|lv(OM_Y@*G^P)kVG6%y^vrUIwIoVvw7OVu24XNJ%WBH%A7U5qRy7`F|Ht zzbQ@us?t{0JTt0>k2|@o5>^HnFH1L!@3PS*L(kCSx@po!{eS3b2Q)x7}&b?Cjf zwf5~4CvW&XuuY73Bh3taA}aIk|Mqw+bCqZCkH6!pk=%vtJ(;(m!CrmSLxIR3Oft*K>uJ=LiJF~tAd5#<5f#e%+jhx>jVl2(N2)8?qwmZi>Ac(>Y(R73~ zh&DE0AumIx$=jzQL2Ec^jd9jorKb!;3>sgq)&nNS+&07rH$9pwj+Kt@3K5bg8E_5# z)8PRlEIpEV=#FOlAg+9ZuNJ_Kno_jgNxHdhPLVgAR0+D}H0LNgTt=}3WZt67gkiv8 zk)%Kw>QSxp8Xp8Mh}7O@F*OQcy_pkJAg~o8CyLQgq>x$X�B}#`6el6OUI0McOXyHf*57(>b?xzMj)^E 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

Md{{uN~@%Lu1}WBUbL3 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

b+OKD6r(QV> z`~4!(jxd~wb*ai~f(j#A{=H5xyY_;^rWm2j^cF%860=oT%@#<9EcUEn|AbJes?o8+ znZxJG9#>l_&CmN#G%RJ_sM2z@gDGQ>3PgsiNZ*9fth_T^{3?J0gAGq9eF$NQ%@e+? zL^S4h$8#W&!C0Z=RjG$tDBEF?va8ww{tU8x*F^;Ru-zl++f7ub=a9Tf_F=rT=kjNG zg5_J!J`vF=K}>unwk%Sb_OD~MhoCG}XZZ4$=ljzG!#{8`2Qt}Ffq`>1{k7+8bXKY` z3ty+WzYhP_ubayqleswm)ilr&cCdG4)0y`*&=bW`DP$^Ex|)0FegUW1<0-Fm?3lioUImakZywil@e@o-P zOoQy%Fsj8Th_r$!#%ttw;%EKyr*Zl5n;@3A1gAHP3Ls`w5=8LC$8L&B%@zm?akRl> zd$YwYfiOL2pww;dWY1rF@5icYv$Whe4HU=+#-MJ-vPjQPN0O;d-jtI~bq3rLXQhA; zQr?Y`PKG_N0$iMKv@eC0x{~Fns8KJTtsc+zF&!7a`)6eiQOGI3;GDSl<2)5hDR>(K zUT(frYUxchaEFvMT?&yz7@i2~ED`Vn5FVvEtB(R0dg$SFhpdsG?<#JFdy@(3`<|6o zStIUWTVp)Pg~>6=XG6~0g5Gy)A|4-iB3}SrMcVx3r6Q(QAMJXdcQ2Nh0^U5s7Z(#h zZ+X-By?S+z`D<(}W1x4{X?pLG>u1A0WAFEcOqK#Lf=>Jn`=V;?enNZMZu?`r@m=wK zICSQ{t_n;0`i3;;6qCU$;kO(K1p4P~O*n3Vsh~Yb(K*Aso}2*Hq~1bZI)8y#_GO zG5s$0F_;4W*|t!~x7Y+MHfE@S7oVWDH0E; zF0FZ2Jef&NXL2ig(8w-V?6`E5S8B|v{@jM!%Zs#M0GfLW`mza3#rm^g17JKyzhhrkMd=11?a0PZaaulV_VU~ zr`hiyVU^A^K+kJ@fZio#M#|UXgvi0uF-lvghb?9Z=GJ>be@$o(7q8@6%%6$&e&^BM zUDxjej(kaR$BnsYO0%&;|5BX4-Z<8mUXn4LsU9tXs2BRH@#esdjT8IM=|kmCde7HP z^2F6`Gm3coLWM|t;#4_U^do9rD=7?&qy6hG-bvRT=_i(q^3&T4p;gXNb00mix}RJe zw7bsVFvALx?pP|A?@^0>E9CTq6-)zDa+eXW9F{U6&lRX1nMxt&Oshqz&PxS#$XXJ& z=%NQiOTrFPkD$PthVbiS<7`|z)kA)}wP2U8uZuz3-ROyMNXsoB5WMl6&T-Z(5s~nW z1+C02*SJb8(svUp86@d!Ue>u<|CYKCOyB)BXeHFFU*vj^D&3qBGLvZoecDKc_90s6 zbOFtRjbJf^2KA$D1s&lyw(ZE?t3%zb2#pBq!V_6s=1P-8@Je&jP-}<;X=~5H_ams; zm#;ijOull4WJ$lxPQ5frfiPwftycwkHUbtf3#5A`+R7%D#u%7v2t&Ja0o0>C3FYPY z+YbaH3qes%)aDm^I}RN__bR`B3yM9qq{-s@Rxth);dXGqGT9-8jjCSS50jr%6JMtH zl!gPzAFgIFa-9)(vz0SOf>(lgzE3->sGuWy#Y~>BlgQ-(Grs^#HIyNs_s)M}dhk3MsH?K~=Z9#yZUR*e)jT{Oz`6c*JV=LB!$5b_3}(Hec&cA63d5Ui#rV}!7`#|aB`;pfeP*$tFLAY~ zQd}*QONXut;};OK|Hp6U;7}!)Df2SMePZh43M`ILrN^}UkvZJmjJHKHd!Wzj+paG4{7p9W1uET#=Yd%I)IusFIuM<) zvd}p89HmZ|_brU%Ez>fV3#>mME%>Y#ecNxphWX^r?9?Ke5=V&>1z0m5S8FllsqPag=BbZF6zVpeSYs!MKQ0BSl26e^Cr0~jgD==2_Dtm``BDSK!zc4jL1g@5 z0Lqr+^7Vn%t=11O%S(P(6Q=bDB5HnfKy!BN+9q^g8GgJ3XjiD(xYjWIWgzk8=ZqoS^QXdo>Y2?m99_t8 z1KOwI;_b3^;3rV}_JE6z+)JZ3nYVrJJ)_jO3c540&@jSPhu=#6bp&BuxbwBE(8{CJ zopCMKJa^dhhSW75?J{#2`qL|G$+$bV6Oukd%6rIV0k6M$y$Be4KJQyyN=@PiUu%~q(s{Ppx!GPrW;Hnucg_Hvvud9X~KpHK?q#yf)t6NM> z9_?QVC}|Lfl}PxOXeBPym3MI{k)4c%vd+$RLiE8|#b7wD2_-5{*z$*`A$foAKsX0p zeKh3E2PSh_+F<4zCFD?ni+NFE@`62D$`Fo%dvzMmTm4_!jmL9g>`dw;2Tbb$8Q&Xz zxw8F6i4hFmR6p2LIGHpIzcldVP&1ZANO{pcDlkZ+<<{eXm0qsgq@u#1l{?nMBqOj4 zpYnPj%ABv zXzp6c;tr?ReVxK+)#SQdmL$t}n3$do$^f%ey0Lo2ZQM09C}Qm=550DGOKkq z))cbx{X-y>P{j~Mt()c;8zroqR3hKHQ|K+er-7j5XGg~RiVA+S=v5boobq^n2L$6l zeCq7{;xnj7tCey0UhKCZ9g6*{b#}x2i(f#x)!<0yG7tYZK<2nL?iF&z)7ZUymk=_x zJZ?ZsN#<@2cl>iaTH^fk1}<-Q3Z_KVLo#v{>yguio6Sk2oFu@~e8|Jzh=x>haS8s_ zg;HH|6+BI4p;(!R-EHJ1d3akkcpnu znf+jn20qQ91_=|xOShkFF0i9igP^3xnZ?5CC<7`Ia!%eAWPcUeE0FzZ^Y(iu@}V9( zucvs0l<9u2^@Xi$K4|hnHRI5tCq7L?)7hdDRS^?Q!oz@23Hx*Oj>4(0+yu|_U5;}- z|MJrN)VN)ge7uEL;%#3T;z_FAC1x>{`%dKjHINEr17JWc`c`!3M|$6dd=Y8-F%V=I zBePXx)n9)1YaC>jQkl&qP0dx8)L@zQSn@L|mf8IaN2{1UdU}FPRP4#PbAcl{sl^+g z;g6sME($~n0gtP)&6lfm&kZAa{mp7bxi%eHk7UHC-3B_h%uVl!tx+VV6H0c}viv_{ z#5+F`tNxU=I5H-t%u-{JqCbjx854@1un722Kf<26-tgAzcb^u`b+Z5>_+5`a;ru%P z2#KJ>L~Z)~eTaA=REw|?y#{Xs$IU~gI|gW5D{qOxBowH0Z+G(|E*?+phcN2$tHV9|$D<=dU|#bkO}{ZUu}HZZH(g1%*z+oLm-< zHZZAqgrmW%%7cH{&`G!q&_0W(hn%7&hLhWni_yWN-A1a!ApGv7P%vTHB2gfBQ`t{s zpigb>tNl9gYRQ~jp=F)Wowt4oP$Uk%WR$4A;RkF`w=@{X^6pZC=Kq+XA@XnwE$QT}mY^?9N5T}{4*SV8 z#}2xoz~8bsebGv!Yd&}?l<)?v5Tj9uBmV#0%UgQkfjGym^?HaKJ|=?SRiE1{XAWgV*i%QjT=uat z7@A)={B0)ZTxYMh`F^m31%ly063(MHuwaFPYQ1@5C5Y627EeC!X%XXN#9eX3lc7^| z_I&(xOq_Ky?B#Ci(0Q}|$OYjbd*O2}a{<{ib&~PVW|Hskp7I3YzZW7}60|2TERc>T zET<0(+n+>2LvDqCgujh0-kviz$65Axw38uiD&z>RxaRKTvnovwO&U2&vlv2)+@Me) zPffiJQt_?Y1>n`pH(F-zW!C3y8#47af8&%Lc&4WrZu_%hC&_O9s|$Ixh0~m$3ddOW zkKcox*m$e+DZY(9@)~!xF_p3lD`Z41DKtGPkBb=jwtYic_mPpb6?Z~O=#JOnx&;8j zVuP27v&+E$x~qr~PhDR0dDH>^|1%Yt@YBjGghflpd+ogYDs{xY@YcSZ{h2Oyw$jy+#%q z?L9z&B7EwtJKZ7F`dImkhh*r_=HlxGfdn3s7u-;2jNOp~3Uyg!rivM#U77dFa`lmU zaJ>gouupi606y~EKS@2e(Y2uWGCUlnSl(Q4b8Xd8_pTiSRJOCmHYmp=p&l3 z4o`&z>+d~3jXJzF|$TvXJ(aJt{4qUZ7#GJa*~up;^WnPwX7=POcd7#Qd{dp4$+r6PF`4M zGuYsSX8YRWP3s`r+1{%#%zQBy*DGhnk}f;i(9{KF5}UHJcxZWPI4QF5$H2=X+TxGK zWL>g!5u&Jh0l5el+p;;8Dl(dO9ae`r9hW^b)XwE*YR7b$f8-oK!iKjaZ}+%ATgxlQ z;9qtx%kl6#)@=+KgLP~h{Qa#I17Y+4N+~fY7aalvV%FP}TR6sarMd6*`t_9MWW2t)3iyvMmZBufdwnxt`-A!I=B>%JGwM39nWKC;B zAu{YYZ!{Gz2Zc9w0-Cm*0C=8oCnvGXX_ZRilw~sXvy-i6;am)~N@UU8cYpeKCJaZt zt1W-D;pIpOShObgx^yDd$BB>`xq&#M5Umc1#4D<^T*uAng{gW0f4bw(y8!w33iq>f?Fj{B zXs6v;*ac-p(?_=GfbO2v5%w?RYpTCDZ{s>&>4cQw`>S{#R{tnJrn?mAJo$Gm8<(LU zsIPlJ&pacCoyj^JKbq{ZgLl0>?tV$8XM&NdZwT5IA$iKT7siCsqSUfIr1Czg5+CM8 zj=-CB@i_NCGL|6e$3J-$4%k>_HED(5nR#hMj9UMB+ zzRInOtQbUA`hNc?4HRUO8V!Kg)11W8@yf!UKhZdr?#yWrZEgAPv`P|ceK$S7?8roC z*Fv^(Ru$i~bthk>1Txy!Y*f0FGo1(^5$K^fg2y(AFmY4NJQ#ZBW?srwc~@e*ZHf4G zg8L`VjMkycPfQLLnbW{YDH($#1$`UyjoASdUs;RmDHidd zWQEF2lWyu5LbBis1;G=R4Bc-mcf-@i;PG^ZIBbll*R_)CwY{cLaWW77N4YO6()xqb zp0vI_^v-cwWboVMke1~nYTwsI{CSo|-|qpnpD3yTiUu0ENnCf{J~kHyCH@_B(90=S3ojne-YlI&%8aJ81`S zRbfwe9>F%G2;`%Yj6nI>o|?PtSI~k8<-Z9mdb5H+X$X{BQqEFbo++o;di>gS!f5U7 zzkMxtwKZY=qkr{oVF@){C(=~izT5T`-xT9dFJ7ooyyMoX?aLzm zI3PUkzvi#>1#2|IYO2=oiPV8*X(81OVmLPJp(uO#DiJ=`SVEfO5oby0<;IH{zVk#N z*5mEh}$vei=?eu#*Vk4U6eEiRj+c(bPh_A<(sH-sT+_K|P4lrKYK}v(^E)LUS z^%luKOz*VJuw#P;es9phjI#if8ofv($&ZrEHu9>~%;HTUkXn}&yi)t5ZVtxh?l;Cr z3;sv({@$mf&bL`&Xy^Cu*O$-9N6y+*a0s$Pgy&MHQSNz>`Xdd=d*&VfBblTx%pL3M zT0n=zNLXZs?mM(Aw+d67Y}N za8ZzDYkSpRFW9_IGZ)yWXrtTa9(HD0<J}nX_dTbGwyjRf zo$WE_*v4kWru?-(?F#w%Ze6kG3(k#)Ffy<*Xk=R*5X5pq^2TX@n-Z3<=4RC5E|cEK zw!F~(O6#WdUVr>{4+>mwo3$K>`Y5HI+~ht<@a^YQXj&4i3Epgy_?%^(JHR9qQqRAZ zesP1y)oBj@QHR_6HkbNJb=t0PnZh4a)RTAXOSSx;fdgEqP(InJ_mQE&3}P;i;-E#m z*lf!Zs>LXgdz2*+-^Wf24TF>|14ST1NF@mJ-LQ`pNwFwlajDl7)gdR{&fF#ic^wf3 zF0@QMu&Tv_TdjE>>p2`|+?=s*U{X5GD5oN2tdg;WKZ8Mf>E)78AYJfhfU|xPz2uSZ zmvMNbc47BQUL7BlorQQuO_DVwRvOJ-uY^sN7n$z29Ds># zn{*D<@}~`1Y%OQW!Jq0MbtoO!h9G5{$djqD-!If{%<7zAa+61%NYAqFnl8E=FQt52};-mfy$9a!Af%3lW+MW)q4( zLX=G=MPVJP{0``V-eSyq~A<8dZQ}6h1mRbG=vk9?XwPoBjr=*=p7w8&`!)M z6}WSb#GRmQxv8IagM81zjvq>1#AeY_E7EG^l1Z}E#v*~BHE(`nDIpKFT{h(o1`I6?sOfiJh zM7EjVdQRCtG^k2%(-$VdYlpBKv8zcpiI`I%Du?2?E^Km8lk~WEVX!~yLqhg%?$->Z zMu&vo-D?M%{M*uw6ckJgc$pr!WRiBFvBk*ZqOJn){PEVA-L0WpVagx!(Sw7n!qj@~ zrDD0VOXZnD>p~NaYO9P{@(`WZT65#u0LIlX17)?zdF3{8 zRKHs`bE)Ec*~IO*u!p6f1~b-UsZnZB`J_Y98-FG&R9|bX>8fB$=Njg!6H9da;lZn$ z8w=5p!$oFD`6nr67#~@%o3qaT$@MnxA(SVyp#x_`);Vfda}SW!U7G=^jYeA<#&wF> zM-vs2IwYA7$GVua!sR`=02Ig(G7q(tsbR2A|}|D*JdrDrYG!UOGMy|=Y?)7lOb zVj@bOVj@bN82)Fo>fWJ(ot5jTK=(8b${Mpciu&uYC`=9eBwfasQbj$=uGC{JI-9E( ztQi3v<|bdKo_9P_sh^e4<1i7k^WkxKxr$ZF7(lQOjeUTq`==C91gtKZ(kg zlW9rFacsJPotejB;hGyp6&f9C2nV;4dsWWQ$7pxoR5qP|FV zQEsK`OEF%f^_)cjh{OTH({fC%d0zD4XkI6oHdO8?^xDsGrTQf`Mc&aNkZ11oT==}? zgZ;c7CaDbih^Gj}&^9iKAF)0jG#Z(f2tQzj)dMhtvjpM>Gf zv{_CqN|T~{D{v!gN{Wg&m%(y1?c#uFqif{{><}?Q4BK=gO?9c$wst8^=?O?Q$3(SC z6;e)`a~Z?LgTw98@}ermQLH#bH$#TnOHe*Ude+Il-57(q(sCAX!A-AaZ_8V5-SmOw z7wHE&QrhV%dlgBFtpnn=tAzS%|4qd)hky_ggB?F{e$tMp=@#^Xlhd4g8gBn$^XcPn z$lGgU4n#9;=QJL}5?`fZ#Nnna%8Qxf>6D(Vw$!1!7l`H)#kj_wbi4G|iWn2oeHWV= zLkUgwznGYtRWKF5CMo-*oDs`}tdBs#!zW>ypkpyC&hw~Y=b4F7M5Yqce9JM&h~Yc# zn2uUzq*k5mjJL85y~xSrvWBE2U;Ex(g&*bK*|N*<)e_~RxsUIX~Pv-q9 zR4%AnQt{vCWR^t-T!AEwuPLp|*@S(sy zl-4*yR9T|gO_OcCpLDasB)n~Bc5ECw};A@t=s~D1#_PW%=(LGxG|W zZjTC7FukM6(M4&8f=F~r$e?pkLgld~ery>hdn+cc>mGg+{aTI5<|z^$nzUSKLhi_K z6t_{^`otJ(n8^`^j32n>n8n+Lx`aJ0MF;4EhnP@HQp+OTiFTAV{{X>3*< zBV!O{q^IsZc^p2MOXe^KrF5&8026Uy5JmTJBBp%uQazLcWAarH<|dHTgwgO^;n)z@ z0)WAlLXb68%h4b!v_jxJ5tM>&RwS{wz6gGsHFs{Q7u`?2c$5^qhJD;Toj5^{Yk>%a ze%9o<)cT?M8F5JK(NL13=`OIRK49GEQ+g3&;HD%HXqEKD4h>r4^5<%=6<~3YVGq_VZJV-T0QX}oLg69!>T|&H^lWU^Yjm*X+npO z?`|@?kb^O@6&+!)l2`enh z>vO?Nk7c~^%`i?bN;J{IWt$D(lycH59Z7Pc8!T*6mLvZ{Og=auuWS z(7b_S@O~Rwr0fGwsrZIgX(XMPkdg^pRoCPtWU;D)M{|7%nz`qhkMge81ndnQ>8mFt>G8Oga#_RRwm#W%5 zZGKenX>*V-dE;laoGk$nxxQ)5&*i`h5q3bMPqIj2`9}UF@JI=tB9N6!mim>kBIB z5Ps95fJog6NO1=2)h2SQ*=*yk*A)S7D35e?n=+~pwaSzh$=VgyUQIp;NLMysYWI+hnflS$NF>PW2=ZH%zCwDr9Bk1z+z+B~cye#h}pcA(Ph`byLG2fRg z#d?8D+_9HRa$b=mf?bMQ!E%FJzpp&Eefd|=A?!3ov?24M+;o#^{B4aEr#08-U>Y8c z{OwJa`Zz1UcJg1!Yw+2Q*VjiSjRukFeRLo=-bX4&?S8)2uSYkm=BmtmZx7qG5&X(BMSKt_?i8Cjb(FNDn{vQS0Yt+Q&QgBa(cJA)CuwTRB+u zs|lDq58EAI0O+9g^Xd6Be7>X$Mv4U}QiUj?XrxEeK%SNXQ6OM3iLeGL{1&=pjL#38 z%@DY5sx#8z{_VSqDYl6RWIud8r~b2XG64qN8#V`R79%s?moll-ll;H0{Y1HZ1f~C@ zL;y+|@R-!gBY)~Ou9%UIJfYow{p6^tkM6r}M{8F8+>amn`VoCE*mhN8_Dk|$)pMfh zUEZBx*F2O48QBwrrF$#cjQO=Z^U8P9)zt0i|6~@7$LRJqxlpXJDnJRYDOe6PBXPcy zL5K%S&QyIUsO3P^WWT;9!Aj=EUf$)quQutyP-myfYr7vG8YBLGmoF+&no=R+i9-b+ zC!(WF)ITzA2h5+bf&L2cRc>+5wt4#3;fO9-`S?eu{qJ_}#`{PASc(1rY03(;G&-1U zs4?X5O1OXX3Gb~{kmX*RGu@S%wn9Lg5CYp^9sBghJjtZ4+r+U*)6VUE>D{M`k5ft| zRiDAPl9$FwqHI1=fAcvM6y_u>=SuM|g;tg0-6}mL6FKoDdJ{6BjGiQ&MKg~pf19eF z=dOTtvU{E}%71T&?3V96jPzvdaV~Rl%IIxn)mPfn$ zF&^ZTsMZOHc5QlN_lyMi27^ZrgT#u*$9s96X%8s<2fY2G9Ue};q3xc{MdG=ReSZIFB1`DO&4{fZr5*mD6};o&q-i$e>E>S_t{IzMwiLtj_^r?B#C^hLd|pqMhY>3z9>olbFy3P>*haG5_lL&ej5;dVTs`j2z;K9aj5 z2$pPS28+Nlmd7Tr2q^@RB6Vi6auh@;SG{pFN)64?5)k2hg}Da@zCX|854wdu_k|$z zU)R^Qd@aPtW~T6dr*gLz7Qf8hH9+9+usu4cCd8^wSq1Odd@yxMFGhdoE581K^I(B{ z?`iq^5H?_C$rUuvn@Nh9BMH0BCC*?XFF=3jOktd$8W4ne@EyOG?c3pcgARowUtLpS zz?+TSHI<_x`H4Rx?h;GoS%ozd-DeM9-fZ^XipB;k@X1e+2kop~`est@NEt)hgiI?@F< z5X;qj*R1erVZBh*gfT?{5Q5(KP@)?0QkjVjd|0Fu$Dp$YaUhgpC_c<2Ligo{oy=9v zoN22vzO0C+ng)&UsyS)UDCvK{u|2-5#Q)F7c@>@})P{FhPhmo$8VXzpm8W~i>Y+t< zkdQ2FN)komhu-xOP!5Wm`=R(oKvZhv$N--J_; zJkrgMJW&uixhyTGs>@0s2h+Wjx{PZ^+`D2dRu+&-tfCiRQ9#4eEEDtAPdupX+KT=| zy??J{f7R(_io23M6A?UIhjPZei^EF4#$bwUNnc$@B3b2LcH*?q?Lwf}yY%v`57NvG zYQayQi>R!9m{eltCFiw2WXKpcf~I!7oK4cAqN`6i3E&&JuWceeI!dKlXhxh#$zjTs zJ3)Z0EBjY>>R54Sjc~f`hvOFf_>I!?%WI zSjVULoO)Nm_a)od9#5K27=TVmVAG>FrwaXwxn?Aj{lVFd`e#w8m z-avcZxm}Fc!H?b!wZItsfA7b4yI8CjY$Zk8hCt^LG>#29G^;hIDP5^1nv29jb!7|{m9N`RQ?5Ku*EXjKBeY?Vle4KxTLw9Bwi zdrz(Hk6+kbb8*W1t`m^8<}L^x^Sk!;u&+Ry6IG{-fF@484%JqAeEK-D&)WDEvlH$m z)I6W{i@V)ncft;vADp+W!31wBOz>C8Xqw$$Tk>AP(C5!|zoInf-T7^9(Fl0hZ~q|) zooCtrG+hM}^Qh~(?9Tz$!aHw+?JH#NN@m}k?N^oRacD6IaGg~yfzH$^CQP6u?UWSV z`SPdX|L^DEXkD|iIa4yz_r+4gJEZM|E+&f32debEZiXiv(P%XZ8%;Rj!kxGBU^gQdnf^J!c5AW}Jz)9pa02gOq1h5b> zjIR2g2CvP%ozYs>fCh3U4Y$2@+vC1X1-U@h69eB6tbq{#%+7nL&J0OPdMd6gedCXE@(|Eu-J%&|O;Jdnnbh17YfSUfM?e+UO*{^TPP>j%QJRVWoTnE`Kdi z%MfMn_KobD5ZVVO;s%f=G$E#uZHXunsajg36%lHdiV+o58ft|qs+6h}p`@V^K|xfc zXsc?d8AOu2%$M;G%evK(94yH9*>W+N?%+p8h<$K0jUZx1l~8JsDFqNkR92H?JE|oq zk@DKap;6)>bE>gG$pnyqfusa92w=p9B@aeodH?J)d!Gz&j>F_GtZCh^9%`coAN-t@ z9&*0stLkx27lZVixM}-i`2d0cjshP=aL_Vs1-tx9O#H#y|0sykQ}2^FSnfLJ*#ubZ;@zv98Uwg zALah;94CI>h5cjkUf96y>`=JsUD@Ag8&b~cNg@=VxJzK5^IFw0&58ILI#Nz9VAnmI`9F6%mxgFOxDJZvCALnh z)j5R1WKHv9_l^l$16#pAZnDngrgOK3IHU?7luzyk`%CpJrvlhu3WH`?kfX|-$d(bFsNFW=*CrS{dyB#frkESL?73t;0? z(!x&@er3{-&wQq6tq>r^|9xKSy06wg!Dk_Oj&X+muHt*8pUEM5C0C!AQ79Br;-N65 zg0fHKXHg@TsnXAN!qn!tybIi|)eRJbtjlllntKm!5VZ0dJsG*Xm1jzVB9HGU<@Z=D z+h??%F35dsjeI5@)8Nw4QTj>rR~l7XK~Jz^_nd3ncJiIOA73X~5AV+f^$_qmPG9n8 zFXOHM!S>6H?v9zY^N+nl$#l@kDJl1f@;BjyXjPm$tH0a36TeRqw*u(UXWsd}ZZ}(4 z-e@;1((*@fWjh|el4Ryua+68snGc@DY4kD_sy{1!UM~2q5|^@0%I0(JZVUBk>3d9d zT`c<3IGPeVArop7+@TtC>U-QDbe#*C)Xv>3eZpI6e-Eyf{G|N$sK3NWKRu`~yiR`W zGoQXr4*ASzU&lx#X<&$=rzx&vy0P&Nw_N_bj6M>HGXHl^*<(r>=PTOWQj}31{$k?C zM~ak6sEvoc{8Kub#V_@{8bK+N8=^UtaJ50muT@tdVr{XjB|rljR8r!0foh<~VKgVU zASM0Zh^uGK`?|b>k5;F=`?v-W>{xTB6;JXp)`@*RRJDy=9G7phtzP#j!w@(_{XC?w zw-%Z$7ZSUuqi0yH^g5;PY+kbWKZDw{=`)PY+|*aOP?J~>yNE7TO~QRVD_%=44oNV; z|GhrH0_o9Zg2>%DzGhvHuIF!T?!f%sGkQ`|-2{kl!2e|!k3qu_Cr{l6F8ufse*7Hp%rKNt;x>aGB$ z!Y8-(?zguDy+aZk0lqWAmseF-+JAG+ftvUCz5U0CFK~8#FNyO_Z?N2X^7xyR zyF}(}-XXM-!5mgcSY)Wfe zJXhU9#Yc6hdKA^wciCT4_A8M*npYg%ClnE2H1GrhuUcQI{X5G|eGo2q82r{MxrB*1 z+HjO0q6n0lKmh`Gz?f*DC4-s`SpVm&&kCBb-p1%q>}aw3>%=wl%U|HBb-G4gbN07b z!4r*nNW62{2$+5n`Yk-I&&lR*!)Rwj{ce|s4)s**Y_D#}D$J+E%k6dEJ$@1Mhm*qm zA8)GR2u|q!M>U4n7%j%aU1MYh`OQ|U=cS>C%2c$u` zleT8&?dXa^l%NU;H)0ws|3JjX?z`4#jWe+(n%1HCKf~3AW`I4SRT}j15P?b}^0kub z8dR=v?!C@>^3LS@8K;{*vppS8vgkAGrlYnvrt0R4TWXB=Ji)Ci1Uva**~ex;)DHwx zy^={-070ccIVw^Jt21ALP*RDPKDiRqvqp&rB?ehgglEV2)#>+kKmY0Oi~Ha9gJApA zE)0kI*U&_d4#4n4T*s9GV1t1&(K#F}w4T@f(RR8!9edIGUJf$e}pX296Oh4r3YUj7PG8vU6&|3X29We>#9K zA9ARE#!&UsKr-OgV6>(vfK56rG9s};Saw$WGxmsCNB+TiqJ|)O!!j$k9P=O$3k*bBGRN?s1>2y@*^8B?qulaGSGjJ2mG_mF-Bg*kGb zqM^BpG9dI(LO|%?kU~VUN=$GIcV7)}S)SPPzKutni~f#Hf9PMgOWij0o!yL|$EE2% zrnQ!J8Bxo9sQiwS^Q0ba{6bJH79_EcCY*~fvoEwtO*Xj0-DZ0S)}bV}i3k}HnDSow zUT5yB+1o5fS;hOZ%bd0Ov(nOnaS&lSy{6!rY-8Hw!7AbpsmqGDJ%cF<6$l3otmz^o zoIZ<}(a?PbMi=Dh=Vk4$*=3c*B>fuPt;^UhwK2U~SE|P)rE=8U%dH}blEFbAwo=O+ zrry6(P&I<8JM=>|cBcr@LwK2&1GFA4fe8|->%<;Z=1PQDt95YZ%f zTdmT2aRep`Q3=tAR!~?rJnpsd=GiLYtjW9|^QJ@b$l!lAd-bYn>+{0y72vt0=Jc1| zvLB8O?+K*T!`vCc+gHLpaSgG0M8Y^S+sqgG0-XL(k`-e!axCV3MCfa#Zcuu- zm-v|{zE-`Q(F}%%|Hh9TSPS&5(ecZ?>$xy03}0GFm0cH9Yg-Z$L}#%^kEYkDU1Qz) zo-E=(c1$)8MWWQG{9C-5tn!Ud^pG+Y{QvCpOAsg6Vk+7zI@t_*6KPUV%GIlMa(6~v z41Vi(M9GNIK-b=?1;x-YTUwVD(wJE&3B-2{cpg>CT6+L_&JFD5OPrYx=h zW8QS$MT)D%@9@~PXijdtK_x*MD6D<;D|;KScw-Ejk=5`GLcV(Prg?^EgX6GKLJb5& z5I;|>FhDWQBkT8*>aR*Vqxp4h?$6b4Y?5jid`3kEq^|>VCOOy4>MiYZ(f4xjexN+ITUnBo$-j!;j>a z!jz^-lMKin*6lY7HHPAAt0=U|ZYdQ@{$HYzd~Q=4+F7%4g`k#b?P#p>r$nEgkRbwB z@(Eb#M)lC|t;-~Sx`tA>wT~a(`7$qmM^S@sqCZkctZ*RiMiyq#>*&J-k~r$JYf24e z(9(C;!}EO}S6{!z4oJ&G@DtkBfG5&{cDTIL>Dn}>kW8A)#8Zp6oq?E+#5Fo{da1#K zOH^j;G0~QFziFmj`aYGf#qVR(?0g(89g>h^c3zHK z#HeyNH}a4-gx11FpFOYI`S*IAF)h2Q_vG&FBHI$cL=co16&kam#&uC($AdeY1?px)74G>4tC9>KT4OkjTZ+9qNBvczu1uU(SS8 z<;WeII(MYKzVnyj@%>)MPxhuhWr`PJG{L~{jU-5iJk4u0$i+q&LS1kjtagbJA{=o+QYwP>nw~)6sKH;AlF$;sl>3v#ksl!IQw>Fo!3En6T;;07RJ#62hs4i&g+mo&SSe zx^r>J*(WVCo*1o6O26@T(Dh--!!E(XJo~%G`fvK5Ratu3sc;Q- zY6a#zx;V3v5h%BF8en*LD1*f2Mk|AuQBaN|76;S4bg|ygUZV!aksphBuIwUh-g=XO z+7Vay`zhiZR9$)|Ax)Z)N4fsQew*(Ei;@1!eXU;!3#8L_|LFx- zq{r}~K$rc69L$+H^RqWfdag`G>detaQJ8ZRPE0f=Y9u+PivBBt$`DFLOuitcc)p2B*7?{l>$pMX=s@-ZuX7; zYE{jk-WTfNDKZh#BG9R)1&D>ART9!)4(y7MrTcG3`Je6ox%WT)`>#9J`z`CsBmQ6Y zeyNU~m2I{-JijG_P>O5T>-eI#M$yl(@Zp!c?|e(#CZ_mu`?C_vZ(5PrA~suw|! zOOds<;u%9cB$p^`ZPRFY1G!T&Pw~sZ!NffEFWB^Jf>^TWW9;}&lTYrdysM$=x^tt_ zLk)}SH<*2GG?WoUrPOsab)_)E6oCXAs1)Ql5EO#J2+Ul$22cosm6f4rO(?KvSj!Y) zp$^}kHcn!ygcG8oPPjp&2@*x&3&v_@2y8QEB2a{hFeReexml(V!-Pax7)Zp4240y{ z7}Ggvu%fA|M?@{WLA%NR)G3ekkZVv?LSFp(1w ziraT~5N_?ex|M~p>`21y?l5GSxdyJAkx^8{7E+*>h+5(k4Yu5Z;jAVxBN|*nQa6ZM zbj&17Na78!#w9q#gJeWH=CNdO%WBZQw;Nb;h7&Fsk7dg8nC5JCyoCe4cgcREexJqS zGixhPlriXcoPU?$ELHOu&ny-}Bn__hY1<~qO)jLLiw^3@VKe9YUN>R&{fz8O#CxfC z+1@q-Y1tm{Zp$tAPWO9~)vf33H@LaisL$o;|MpX%(WB$+WtxIgh$4uH(@LFuKJhWS z_K%{*+kcnW|L@8i{(1xJd>rp}onw2`gHQYtup>ySwEfCPgld#ltCo>OS{&!-wyG;l zQnlJ9&B{<|uNt4A*wik3E)0 z@nlNy$Y={;#rqLDwT{KLJE3%1?X;E66%(D(Ff@QHi1vAR<8IJ) z-knJ6zsSSRebYL(^B75^2S$f5JsYP>68RT}l?Ex2|Cg9RGbzh_~DjjfWF%1W6n}XsF3% z-!!#qrHZk+Jfj$jxxIos3>%wK45N|*D1epXJ~T;d4-J^GL{maSdMLIxy`339gnvSE zM!@wEM?jX^E0KFmNq{g_u232qR;U6J8YN;E+-(-rp*%q#5J<|wLyr;($C!%dnBn)K zdckj4J^I4YfwS@Tx0%QJ+#d2NqNNJ=x`l)6CxJb;$0f+Dx8v;XZ=?=OA;Vu_k4JR* z;P+d%Dnlkv?UbM(V#KRn(m%f9yZ?58$FZA_$B>2!v6krB=v1URco6x$DzTNCa=I_4 zPcL*xvo1!pvu|o`TP@K=8PZbGN>D9TB8J3~s3k)*E~>Lu=UFQ42!;py)sRSU5{gZr%@Y2ugH%@M~jdPjxJ9K!uk~k5iNao;+nSF9i zjh`*$?09IhWa^?JYkft3sxGb4M4Mj)1VJF3eQrgL-&yb%lWlZ%!c60W0G&15Sa1Wp zyNZT`2ED=VclMG1d}g7lxdl{nu6JIb843srisF7SKya9f1uyb%lzM(&y)QIL%Z6F( zGmwtiKh1h9X*A6SLg74zs=#5{Of1ewj_#9^0xDFO`@j1fcCXW)269?7KxfU-TU%s# z9|k4v2M)6pO)K2bS!?~jM^93ndiCyL!K75u;G4W*69!VfF>?0ax(S~F8k@qlNE#cP zVAw3IYFCh!g6G${ zddk-7x8UxT((Ar6(i}v3i5N*uGr*@H!GOO@=Wik_k5hVu7Ts&@ia#m8us; z9pTc5I%e=iRi9mJU3kqP!2msR*ERiEOO;4!Me0q{ui z`FFo8&^<|Al+ueW*<*w`-`peZ-aVksjnQhlvk~zfwKoWG?UVGsLY+>EESst8goV3yQLq z{v$#NfMnXb)O4u?CWR41Ef8O*|I0|W{1DWI#Rg2Ron%L0K2q+12P6m}S4O6w z(gYY*PX0RW=reSLXfLQt)5*;XLpPem}C!!ep^*ggbmO zFeR&Zd;R!cRNAvFo8Z+*G63=kGH}osC~9EOK6Ou>;682YmAlC2+&|K@zUc_QWr zc}eLjdV{q1_S&|PI|v?cN)Ua&d$DidnmiPGZx~ea_KS6-GYg>c;-slokqN{*2MHpC zlx@67-Yuph0`+rtw|4sv+D!; z?<@pOMjl+>D%UVT`t^4jI)Ux$0;ySq!E#O6?iJnY)4eP#g3r3mPFZY%Rgq)gm6fhV z5gLg`Z1N_qSmA>O>(QRO+_Y{g$#~DEfl|mRC!|T7m`nxz{}#lPPNM2v?p!*m-2U4c zj&@ogi?TL6`5;$wx5aZ<#1W~6k4hGq>T-r}*{1i3*)6(unW3qj(1A&jp=VxI&N!P} zU1tPoH7akxGD)@XO-5Ec`j+C{S(ZGuB7t&F-x;$lkC>3j0a4LmtyC6Zr z3Jr)fQw@zsVZe5FIuWK7w>7r>yP0fvygqLoEt9_{{hxtbk+(k`DMDV5#|2!lB%5K% zqYirogg;S&wGK*qRji=q+d^M~XUOwB{LQ$Y^hS^egQ6S⋘Q(xln{Qgr3DtDM1R9 zb(xU_l9~jRI}J>TD3gUw!dO^LTtlSloR|jb8ygd5Q@e11Ilp?kf1|^)k9Wqpx6aJl z9#3ZTJWkA%foGpe78;vDDj2gM*fP!am?V!Nj5U6p7;;s*NNf!m7()a|Ho>b@xh^d7 zpawvKHC3cK@632Q{&4j7wD57xu#{GFGXcjPDs}N+{Mpn zY(voCrwma*sR>(=c8Ag*z%dqG=>7D>$yUA_1P|59|NB$7t0K;ozTG4Cr^{e{v9>a? z|EgR5r!f(Q_9rA}xdvnNW@iZ;(|19?-~MgpJ23I?WHM-?5Af&nnEZ?{{Jg&7%#rLn ze$$^tN55{--1ZGZblo9#4d zT?pWh?7-juy#1WJ%(`n0Im$oPB0PkVKJ)lEHuK59)A886X=8T?i5T=!a}o!AL4PZX z4lY`4Wa@Kc4qq#g|qVMf$go@B3rWRBHUVZQfX0su&SK8d;FuK3(Vi1UJty5(VP;(WO+-4K+d0kb zHQMZ);!;lhUR5f-W{!XvqptjBMP^+zjp;O>>W_Y{<^xd>-jUP0J$`e2%VX1@;-9=u z#IfcGQb9hz!GWzh>eM;iuYZyp5X4#yhqVrJ`04bws$xz(4m#KlCVAoL1RA|uI(~B%d0 z8U!_;%(`d6XW;*eq|pT<1Rk8fJ=an3a1ycPBexTHe0qevr&5;U?Ok6Wo&7)GKf;W; z?Glp^$M!2m{0^c@S@L}SY|O(j!w%x)h=0}-&CtW6m9T5`lGU{MSL$!p9daJO=%O{L z`>sQk%k=8f>W|YktHocxJ*&E0hL938=7yVb8?;kUKP&FReH`{bv*FqHb1M6+VT=tS ziCr zqE{<@od!lOgD2}hmf8Dh|K;jubcUq@K-{~b_vh;x6n~WS)T8)Dx(HCU_nQui{duqW z5JVhJMh(9N#@Av^wM)vcQQ8fTMeL?DCBr041!hIE=3r6D{IhTE;&TOMjOJVs30b8S zq}oWTR%hrMv>g@|Swymo`5$i*43t)1=0%|WI*!O$N)TH6zI(_9uA3y=jvPkP7ApQZH%1BDti(yV7wR1=y!K5!ycc0)GwrC+F z0BH-H5R6iEgc~KF(5b0xkyo|pg9^Z#89_HIF+!ayQb{Cdzc1Dz_*M!q+RK6%m4^{u z;+d0brA%y)qYj`&gQQ|B%aJiH5p(^rv{uWU{{Cx%ueW!B2VBD$NPpXRdhem~?_?*1 zLI1@8?F^Woj}c-<>kQ`a?+(&eEa>E%ta1NFe(b@Uf2e=Zcq|z}BV(5M|Mgo%gx(lR z>9SHWyTm9>q5&pRLhW1mD%UJwV26cfWQHKd8$uH3cDt*g7yi{l5RI(4w#do5U3xkG zoYW}f0BQaV9zi*792vC%K1RuvE= z#1?)LjKZ(~6aR^Wp&yWH5I03=m?pj3bbCm5^+^6>jGJc*rs$Gn+8Q*V_JSqKXn(Gv zxiBaZcHERgD>=?2VzBQD@*B0w21wx623r(V5)DL){_x(6=}gQ5X6?Bk*^v?y5-^bz zStKzL5oo0?N^HqZX)(a&A%T!?FpVT_lY7=nNRfu$kwH)9<1$V#h5vZ1i>(VXBAItj zQZ7W3lmxQXu`(UX7()zVWH~pwsg?|(fBfSyMVn<}Dbt2&FX@pc0MN1&ph%0geAVtC z+EP(MAkkUE6BLq#6(;tBp^3;LLV^t;Cg0UpdBhlmmNCXfIhZRgN<&l=O4-W8MJy4B zy9Vp?VU{B5`)jVZtPzcC_fJ{5*7uEOG+Gu}6t2Ym6lof0X+dTJcDslQzo(MiAEKq$qJS} zZ3s9Zkd29~RtJh`gOi7A{*|~PNlX@{;V8lafy-AW@Zv5F%n}(0hVKp$FIOh2k!qZ( zyiF9Q?b=~kN*E|!eRP|j7HNNR*+W{PHM@D3*>+MR8GBeQ+0hp?5g?j2M%Y;-vSMYb zlEWcTQDX`UO@`f@Lg0r{o6DPECM(;2GwQ;s^UM&~3W zl3X`Q0@9;w$^prWsg57jmlnkwA-0ZGBw*C3GF%{uN~LH)GL)o1AR?my{eyzQxg-f~ ziy~Fa#87RiGUNJDReRb4(-71R2njfFO7|_;$`DxsZ!R%R6GKN%1kw;f%{GNs{qZ=Z zi?$h(Fn^la8Y-MAyjYaV{`$>p|C_z9YL$kdgtGK)h$laMo>5e6(F%((37auW@d6@^ z8pTS#mqPVTkSKxk-ljI8cUMRRf1xz>Ea**0Vi-Z*T*9=CpfVK~CWw(svh=`LM9?sh z!Mo9`<)Cd4mhI#lW#8u^-WkD*R0N=+*;*?^tq^TqAKnm*luFTrP)%IkM#NDKeAoCP zg9&VMM$m*9VU|NHO_QRD6ha`Yu*RuUvNUOkf7^uwAN#3{oa51A^r(y`!7A!?NK6pR zSl1EyViCd>beXmeWeO*ZuuVowwFP2ODFkdVr8|(|8hRWXPeop5Lqvv-a+6wU!y;5B z82^_S(rnI1F@zjS5rl}z%uU%*Mt&wSLT^Z8GDInp7RwZE5P>NgsAi1+79@x!OCs=v zCfN+w8$xFpo5Gx^j232F4A~ZHso@Z=gDoy_YbnwL|MZI5mE?Mox;6ZnEH2>0|-)p!p>X5;L zMm{UN&XA3gq9ni>lu98HJW#WlcHR^irtY<4B2p(f3`H^-F^k?778}D8g@qFsICFBM zC8-Hih^VnKG3UgRWhp3w{(-zgOBm+u`7Z8)zFbDK`5Av_gLlDx9Cx`LDpP2&IR;}Av=|8r+oK~}6Y zXeuKSXfdq7{_N`Dvvd)Hpu^PUy%3noy$vbi5=IJb4B4EOK3KDoRGd6-XkkmycTe`G4V?i`F)#DQ4;7nOR6NMk>Tp@deE}jucJehsuv!YWOFjBb?kYL%$82M`E(vY3pR7@qQn1bMlzq4-Y zfe6w}gO*&JOtB_uOI&I;3MAU{f+ZpdQ1wb890Et(EYYQSUnhh_)djH=F=Cj}vO5U< zG1%t`6cfN=E{C->p;UFku(@W%Aw=QcHN6dOA1z`Z3(ffSI5Va?^*VOWo;TS&Vfu+A|Y8W;W1{?imoTOAF^`}vxIO}IKA zup$Vm!h4%JST^EC&EgP|PHlTqfgycG)!-M3n47OYFIQp85XJQ_IJ#hzL?-P?44fB_ z&%3-9je}>t(FA~e<&8fF0;a=5x7|1qy1Vj(k}nOJEfBuCQvbxglL@6Yf2$6x&z^`F(~BkSdT{V`QhOq_Y*#&il| zEN^@hke1i!p?wdauER^3x*VwmgkERS@ODLNG_9?0WAi2NC4X8q2>}}a%NaIF&fNYa z#igp?l9hdl15F#XaVI_JmH#(3mL6M7&No`dN=|B$3UXl;iW3tmXYcBC7hD&JtFuTY z2=I`t{XS*?qN|Sx5`Q+LP&v}x&6{v?hToyf9!H_q=9^arI-lFZ?QRRWu(hm;zvyPC z71{@Lp-Q}qP#6=F*bkmnFyPamtf`f;S{NO8>SL6_pkss=CdG^?k4-1^y>|2#(K|ZD zJr#Q)Fuc zM<0uJ4I-bYkxiy{{okhce61AN{S8P~XSZ@=Ce#|u6s1}tisbg3N;nIQZY}EVon&FR z&)uo?rsS(tRcWu=2YY`l$zSE<@D*Ld zTlGBFOzApaX+oRsepm$DHzIG`W7qnOqV5@b+u#mAq==kkjk=L2WYt(kBv%MVb^3o@ zJnQHA0Ub<{z;6*f8IOKon_%H5nnvCK#O;CoAp278c zi2QUK*?fvEP*-S6{u*2)Sc1athCZz7Crq0LWWiBPoSF!(!627N@^-;Ag z&(_hyz4hX_Ho~pu$!V#nb@UNyAKoKO>H}<$g=e;tVgR zuc~%S0coDY<9>|a$JPGZI*Tsu=WzP3Mkt}q@b@0h6tB|{fOt0$1O`_m@iAcBhm>Zy z3YH4N0D}@+O*@AX?7bg{Vzo+_q-u2enrez(lks~3VQ$F?rK=-HRm~4+fu8f4ZIy8& zF_&Cu2`QZyv`)sSet;Ye3@;HdF)K_H0Rmc9*CKiT^!QUUMwjnC>B7vpM9yc3&+cN)GaQ zSKQ(+OSvr(*n}y5Qh9{B^>BqfEF}n!m|!B)M=lXeE%B}uUXb03QG36)?%u1gU5H-;gC=tt~j6qYcl9srdXC1(_y#)044wey9{|~3N2XhcH zv-?pVt&{jLYdJi-i=FORT+QutSvqEEFCuN|Am@JcPyTDm5s^6L;~D4ZiWzyby@{vO zN1%z-PZ9VvyNW*B;+@yvoPk@pW-DdBPYdJi{N= zxfJs=E|n6Nzo3d%=s8a3hg@NTVj0L{`=){X?+8D+!REc6IJrIm{ZT!m;3Mz^9`-Uxmh;gtiN;T<_;4r^VK=f}z1=Ab&|r-Y$1$`#D^6A!Up<5By5VZUqUPwU%Q zU@1LWC5e$}Usy^e5tPmNDHFciWRZuj(CfZ7y@lUj(RqA14eh>G34}`{D?_ye5ff0~ z8C40$fj~474;DuNL4(_137T29Cx2krrLxG7wVGNco8l&iJevYt5uSE3Qm*&qY!*zC z1YaJ|pu?%Nu2={g4hnBjfokF+!I}B zPdzisg;BUW9`En{6uFu!(vrHjm%0 z+vv2%<6*KUZ5j#$m6J|6QlR!_Og{ecjbCu@G^I^3%&rhH(WIjUAlF6@E)O9n?yt=w z+Z`~hyZ?UmHsQHji0U|wBt(SDgv^_s6)xRl^s^CS2gF){6lT2T#OM!yK5Qa zLX8pnHnVv@4hI&hX)PQIghN*7q(#vsCn)?BJKxI2F+U?%>*vE^K2=)g2V~uhoiu7< z^8@YXU;EtE(RdEX6som=o$FVLbS7~Z*5+^fS(A_-y$P_R$_QDEHCE{_Uifz3OO<)cnSLbTIg<={hWO zIGmf~DbCJuv!89W_mT#e31>YF+y%VZ=yBU2qkehqu4YaH|G$P&=>Szgs=ok0Xeks1 zh9F?V+5~sC7c#l?C+OW?Q+%Q%^q0|dcNNArRca}UXwO@wLl`AkX*9%21e75x85Q)j z1yidi%toWcL4JJ4775VcTy!z6 zs$KQ=XAxC$jnkayvOdzW8)?32s*3q5YCzjBBPMq8RLa{us>*#EQ#z;H#i+!NlAhyCL%<+Eb<;sf0aFx z-$bvbLq{m$-Le_@P55KO<*t$D2<=J$(+?pW_VI9TJeT6*T6rQ;TIbDUZM>1_R@|sv!C8Gg zmFljyoprzyH~JdBs2FH~X8c+XTgCh;Oze;~vF2QM?+;LNYkasRlZ>lei_t{4*yDJe zGgf+E;W0B8-2m)mK$31&)N=xGoYAphhk>Q}#B;uW%bli&FJSyyw|!vo-?f#C zcFBI&c()9>qxWDQ&!GJm-}}q|57KARKB4u8rrdki>H9TF1ZMv$F#vsGy?WE`86#;^ z|0}A6H@$~;C;yEn{(j;g0=!ylJ8SNsl;ZJR5518D94Vm>6ABHl?>*#X&0Sjrfz#We zaP!Uvb{ckI!V9!9Qh?-<_;9P`gIz-AcYFUYRF8M+Q5=T(!zxp z!-z8X2r8em;MJ;m2c|EIYMMR{Nk{<%MDa{lHmNlu&j}ynUuNTT{P|>1BFKL>7fShU zkm>Aiu9h-00kvC*ANrbA^8BgIb)5M6g#+Qgeigo#WkcC(YU3cq8kvrI0wPrGuiWgc zU7KWQq(*A~uChAy0BQ5RyU;l!iKyckF}kY`L_x6GX2g9|ard2*ndt?iE&Yi`b<_QM zk_q)f&~Qi2=g@li)=1R!JE(osq^{yga*7@3Z7X6QVa7DRD(dHBh^bV#Wa(F!)dXPb zcRFV*Wqp~(`xHi(Ye4irYvoVa%x`#_sZzO^8?S5r3V?nTUBYozmnGkZ|_Y8`!wM#r@D!fUPRq2ly3Wk}l@ zs;)g)nWQvpNka%_jwUr-#0Sp$A0wRq#>)3ht0olet&Nkm789Xqn`C0FedV(or&oD) z3hnQ`(J6HFnDL4KkCwwYzbm+boe;het6YNTvSvOp&NP%c43pVf$W-b)4rUJ>86!zB zgbD_!^}uCIV-j~|#+YYZO##j1W<}(%D*GOuv!+e($A%*ZV^uj?PRMze&X~f0PmuGe zus?ORZ!&3PB4XWh)zPMr(5pNbE_c5TqfEpK$IxXPLe74ScRw;xeuE8pU#33t`(`2T^F{0vtCNXTc7UOZnj65$x7@9KBdtQU%jV@wX zQd}Ug`xG6{*uMpxYXfa-O3m)V->TwbwaSRVB+IBGB$a%EszjA|%}X^%KtHD|x~Q|I z`ZClRPi+as%A-VJ-;a^~4$g?bX6Wz2x&+^&Yq*CJma;|8-^hJ$wQ>Lpmcr38q+I5i z)k_q*#Y<5ZHJQNN<}Teh8ZMsgD#g~)&JWgi{eF15tl~&p)JJT0F|xZm=p&pyo=&mO zwBLZ+4g{su7P-8uO09URs!E!o7L}Zaz^MuHtQ>$%=1}Z%z0(Jm;JZ^7Odbds)ls#a z7Y0bF4ar-aqiuD{=hq2X@_3o1Kt-}jp$6$HNsO*WRnUQL$sak)lMO0Kr3#IuOQbx@ zSc=6aB0%n_U&nmLc8wjf9IYX}M^0~Zj9(D&i5INhoKvfjNH;hW#TZuSl^JSX)u$z6 zDy5`)_P$P2z!;dkV@EL*ltjk~PErNxhUZ*PN)e>2)=Jg}GdHYAoZJe^#Z0vlW(h$_ zN@2-Ff)Ql4*jr#loz$9uhGr%^`OeW9%f534W+Q{-Yf!BFI=5O;8Xl?W`|ItB#;-d9 zSnOj-o;>dcxhqCO9i-tUjEE1v8OK`Z0+ioLuDoKaM#X$>9A`x6c5#Zk?7vpr^w&7e zD^8V~Jv5-)=Qz%B(5D8nmFptd<;zmB!nu$b*V5fN8AyuQ?&NH)W{s35uK1C2L^KC< z-wJy>IU)Y36xW-MTr=*U+0vP{$jWRqYwX!?uj}EdJ&vem);DCtt6o<*eCkqY&{$@i^QM~U z9Gm9CqiOc-S^W$g^0~VVd1z$Tv7+8PTRF!ldbF)C4a?{38;HiJgmmrBSG4IwTS;3F9*Z7R}0tE~;KC;elCQ@V(`QfHLr+~GW! zUkAQ}-ZZ=_@$y=^Xt`qdS1?KYOsL?lsgS&8S$GaKwlh<$+(ci&VbNLQ9CTI`Ul~?GsLe5;Tpqr-G|}3mwNPE7OqLU?5#`}Oyru_{tcX$FwF4Q zWv{@|)3VZNzx;pmBkAD4+0|1Hs5cJzptqA4`@~MfD#m%hO~b-!)3n2-XCKzWJ@zI~ zZ!kDa{3X`Cw^snN+)&)bKg`Cak}lbTqBNYTt$D;E-B~~y4`f3G^E78c)_n>e*pNOg zE-#FYvs%3j7e9gpi2p|g$Y$r>v>Qf_KI#p-JKd~Wd3)p|A)ULu>0xiwKpgAvzWgIj z@L02SLAqssodJx))U;yyj;2AY#gC)SKww_MU7AO0W#CA!<3YJ)G{(h?@;}Gy^LknD zb+YF($Kdv|>;05=cHmuJG=7a7e4Wp!l0Qoh<1-hm4|e?jg9ywrx;uNRV}z5UPZ+@n zKky0xUo?rc=kPmFno<0AREfTJ;iI5&!$`go9BV-oG5Ya3oaskQN1UT!f^ ze_y}LzVa}RGE__{gtc3X@pkmhy1i^@be<$?bU>;7{O1&|;c4?weNruS&l<2Y!<1TOD+ z=U1s=b5{J>%b8YCLKdKwRSn_PKSmH`6{*4X@99(%&0huajj0VbyZ=y+{m7C9>ql%Q zVnQHE1e3B~zBZE}+g{jk5v)i0P_J2H?IL5T)Sx}ot3N_s7x3J**p(8+=$pH?7Ni%3?YBTR=z*XM>K`5L$qzhGVz5|y^c#hIPWgqv-IAOF+2 zVHoSf?C}2M5HYH=DXpPoqI5u=3nBkD^#Tp9g7HchJdCoec&K-JC2QOwN-HMNYA+0! z*P&D)Cq}G9=*jsJe13ITrb3-dBv9641DsZ-2_RJVRSZKiro_oH!J-WaD3t2=au}$@?<*SL z4Fi_WP4=%OvyJ$&T>R3%*C+{sUeCwX-s2FyJD%hn4T48(Ci@yD`C*K z&K`*--k6tFM|f`qF@K6t-Xy?E4a3Al>6Z`@w)bOF2}e62rT-2itnO|}t@Lk-zd6(X$7pDbp3^4+5Mkezig;`rXZ5F;%;RhL; zr4t=DgQYqY(o=avPxH0C#?m<7Y1d3Uf=B-ZUrv{M7zJ;KjuTtN?Fvqf%bD`(b-L28 z6+AYlA+VJ6N`ER%Eu1nLBbJu$Hy7jpRl&WbOA z%Cy8H_@IkU^ARROk;N#AG<4o*(F*M*F0NvlQVy-aHwE5PxJyKfOI;ORYIA-hk+#sm zB}*EFFyx79Eqg^-!GsFZ`#c>?)^H*cIm#%W7>nj@c_KyYzi{-N8`=huz|37$<%YO9 zrAQ;95y1eVVDP+aDoD~`C>brIDLgnPoC;G05>_L5d@)U5IAF}?WnS}vC}7l>cp`#| z4mEaElx1lsNhq0Gn2Z&c8E{D0!3@FFh$Pd1R89z@$Tx@#+=)an1_U8_xtqkI(pUv1t>KT2s%K$ zBTB{)s!~HZ1p-7QY@tO>;2=k7gUT-M)FqQjn9Q#rxr*Z~kXlf;hVy==uSGr&X@!{D z^u~%N@f-`dy(N`;Rfyz%fM!O-Yp6YeS{rDtHbZ zMQc+RBPA_5aeAs(j8syuGA<5Eov*g@6r>@Wi^xW)R1*x|1yA(q;m)z4?;Ue@ZU+;z z*pnJCxHb)Hx5ehej$%7Ai^C#m!^5a5h@-MFgXflg)_bI8b>D7nnz7a2IY zi^M|>zQ>60JKYG9hM62GO=2DhzO*Nnodorq@hhz*wX%VBSP-c-Jr$(2ma$lc_*t+atexr1YpCgisTqCu5Y3@od{ z!F3i{LE@(}FK@{0TI(#6$AX)j((Kz41@LpFMO1%1W#UC%GiiUhi)v#9V4_gMbF&#WNteCXQi+XB z0?bC6Oez{)iDb>!Dyw49WB&`lGFI8dU`WBI7J7S0nUJJ9FmScdRGlH#BA{OJBBqJW z)bLZz^;b%BiJS?I7{XIHh@X2@MtZcq<3O%Xh-f1x;nbcLRF=Mpyx+M&@mLkEI zpka9Dajv@Slx#*=ftZRoX&a9*-3(d~GE0d>sgpfvrMq;M8#ax21Q3@1ZNf05KgckB3!e$_1d)HMof`Xw9 z8V~XGhABuU`(r`1>iAeD?`f`!n5v*nv3vFD+@wb5Z0VB&wCHPk44dUBh$0j&qtfKF za`|Rr4yhAdoW*L`tA^NPf^N2Jr@#RgKiV2pyJ z4IISi?rx|WtGPFIS7=0sLs_fCs}R!R4)K(e7tCu&)npJMeqm>5!Ha^H7VSppB4~so zT%e3PBXwK|5@}ZKLg4n&O)Q(1jbQ@}mf2=vF$!8xVH=5odYp^iu9aExX!4pA4rL6N zc9%xAH@+JXW#VN1$41Tcyg*jIQ$~wqu`>wF#}{`unc(j+ctD~!)QO7mkpp;^O{f+` zrD)Z2CMHNC31k|D2q;abv?yuTD{I!!VBv?H)`(*2ZjuI2V)wkt%?9S>QVS=0yTZD? z)uibV?{=moRAz%SLT?T#q?(?i7s8T*h=AH!?Y0qVF@))+3nVm8*-WR({aBXW#TEJRTe8A;7I&R}nzLWGeg&0<}Y^V4l- zAe*F!!!;K*DNfKTR?EO>kU^E4H>5*R%Pid))iGQqu`f4LM&_zp!98V8T0R10-DDwmi&a z6RTK_n@N*Fx+gz8s$q@}c zNFqUnqQi=Y!d)HK;c0QV58GadG!>!P-LR7X_(YkBdbgg1%9qtQ;omhH>7k8UxrZwy zw1vXL#p9(#PZu2sVzroXR71>6AW2x#C&p&+FpXVFFc)j~ga&%=uw;wjQ!hvky8h}f zvK-jXsA}svGbj{B3!bFL(&&^aLllP2%!3P(M29I5O`dNVGgOJt z!K!YJB$_WQif6P;j)#1$OySCTH2Kcavj(+d?93C2iIk2~!NA)yn3D80T2gS2Tw3gi z)&vqELJVs3g$pMQ#-d@08aLA#d3UOicf-6$$!#ZoZX}!D@dx<$M}$08@p#{j>@Z^S zQL2h1MPdU4+}aqN7D?ra*S#35XofEGR+?0WvCfD_UR6$UlZYzl=wmcAn3}#@VxZ27 zUtI)6=AjH2YVxRpvfzg^n7xk^SXd$OsLa?s43;2`(hP{!5qG4cDq|ST&T5^sa4AOh z3M9mhqh@B)D%_pyZyGK0Xg-v;z5?2KXEBMX^Kq?Q&C2EXF|TTpaCq(=OU7?_L3e-W zT4hbPxQie4o2ru0hmNSyINbvq0?3mH@YVh$lP1-^Q7#L~XP4hS$3X?AR%wqIKDx5gLnNYB%37+y3m2h*8^g}k!fVWzlc5v+N z#kIV(pc~2}I^}Y5Iq;WrbfC4`;mo!~LSePCy9k&^fNj=}8qqYA=20XNMyAln(S@A3 zFtofo9Og^Bf09-&OlMTFJ=(=ahS^}qYWUSf?{qHc)bPT@e9qB$S6P9a3eiKYaX67y zZLmTxLb_U{ZPaKzOER!^BN?RZOb~IzJ0ppw3T42;M1?z9+c5(au5Zb934U42Bt%dR`munm?vxmO`0?w zA|mWEu(6GG(V`BIiMyj+=-QTOq)54o&Sqk| z90R5qaxV#<7^#L`;62Uin*?q`;V3e8u^7BDikw_t;@}yGij+i>k{Zn3aBEAf0fAMl z;&gXp{!_n&YZLH+oK-JrMRhUOyVzO9R^)M!X z7Z@7lDk)Ob#S};i1}_l`K~ja(La|qoc^Yr&#w}Mj1~RRVS5-Hty-g|L+qrioRIOzI za8>4YP%dc6PXS^Ap$1F@biGZYmV6UBdsOth)Q1s7LxzI`QXMGoY?##!%le!(xr?z4 zToZ&ooV`&v3<+0(5=4;jsc?=2VQGGeM=K4nIm0VUs3LE8Dhn4dQVV>#6+CjHC1hOJ z{g~T16|x#L#< zQ!ZWMyP{@RF$6)WgGw!VURESBZir7cGY3;>jAst>5d%kXsS^fYxxBrndyNRH$fgQX z%Pv}$`tn>5UF4`5q+;q@jFC-!-B5!v^p~8p<(|VLFDR8v;IkS{8|Lhid2+?U(x_-c z%9>%gZiq$%C&65~KGm^>gD@`ft=>&Du|!}(s#%H@-e#DU@K1k5HG6_&>(g+v;X^z4 zsBqz>*out}ba112fJqd}6DXE&C%O?!;2@SYfU%HQ4PRqkrNTp)S1hzJs4P~wmuBZ7 zBpqGU6vkR#R)`VcWS{HSLwmGUbavkEtz z+KQIJ6&;8{q_+*;tD+5v9V;l<&4zny#)(83j9*^XX}z356f{V%SPlVWcA+3*99Xim z^HAXq1zDp?=BGc6~pK~Tj;F@6TuFhv=q#_h6#KwK78HZV{mj1>ow z4yHmv34#VxI7ooOP6PpS1W1O_1cXA)B5#Y0NRk?9&JehzY!PM%!HAH+V2UW;E#G3; zCe|S=-9R=63)@Xj(iT)}14E|DgWWfMFgkF%c1%ejB0^jxk-1s5ZpuV+ZN0ZeD54n< zB_B8d zOWdf5cWNX(hGm1n1*tZ2;Gh3@8 zX)w_sWu*0m6I7n&!5ac?rQ2Y8(Iyb0tsNdk%pR;cP&U(K?N*2!!Yew zY!1_eS~5|RP-~KlL~1o!3xYaK6Jdt5+P67M=@KS~HtUHtwCTvA0S!|QBPKe6NTqI* zX39kB*e2@8BoU`t7hw`Y($z9tGdxD&F$i0B8!d?3tYa5Km?dIk6^9UrvMoWOM35nf zOOZN6t+X_z5L(JXjNoe8t7uV5D?%3B)o~YDFkNK~UK0#!19xTBjJvyPNT#wyZz+}n z5;G$tgNE8xgo7dk6dFxJhY7?YL=+}qlPzVEm}T8JBDIr)3zk@1TZ=MCqP#T2S&4+G zi5Ax2lI7CK$jK7yk+SoVFqlZwAeKWsVy_UE%L}_~lC6OyTW(mz;lc}q!;6t_5oRvL zw+&oKk`bj6?Ykw*Bp{mF#nPn97mTFHNs`>fve?T-l-!CV8F#rH$OIn3P~eaV@r^iFm;qZtcXtM2NMG%ZYh8HF#u9H-UzU zFDMx}STGbZbuSFGMqz?B(Hq1q6fu+_(77QomDG$_)up2#OKMz%gsq7yJVM&Zxh2Sq zQV|xfI2gAVMi7LGMcaf#Oqk}G+$338gxtIs-QBzy#UwQ~V@;XeYm*ZSkhbpF$d=WsI^! zTuFw~#9-ZoM)I-Kt`%tFq#&5PAu?+Th{BvL*=r!Ec{bHRnqCpj-W;6JhM#NHpOpPIXXKv2`D@eUt z61_a|cd&RVu$g7~SAKF%r|Yl7rZ=R1Yp~es(n|LCxR!>jPw?lr#*4~y>?Ca&4L=Vz z9!5-VDY0vOpv0mR96o!{i|y(u;MsxgeqYX>W}+?{jOKeX?as-O9GlE{P!<8PT|_i~ z#}{xzJGk#<1OL9#QsEf`T$iYXaqQ4-d^){GMKT{iLhopN*um$wsusaN5v#^Xs1W=F z5<5fEDl|V2+{w1F^&eZ+*_i`R5)s2n8$&c1|69IXOy6(ftcoj=f8V9l$g7}&^EVZ^ z5iRYpi~?|$)75 zNi%<-cvPyetg8BYYYFP@1q?=dGb!o2A%mP;yM8D1MQE6BJnodd2z{;c9qdgQ5fm~{ z2_N{W7)$>!Kaqb|_?z*PheZ>9f+4BMkz<_OVD#6h;g_bcK-e_f5WzIP)o=r%x#lFk zuTMUF{0~d}9-#Hd8)wJ)uR_b2nMP%0Ol-`W!G|_h9K3Fl%!k=DN74cWkx3k&?9gTi zf=ipb2qKJ~q?DGr3tXH`OhXJsEX(%u&CkE!@m|aK->jwKp_KR zuUM-NsMq@|-G0CM+dnRS%8Sq8UhdP+si8;+{yL!yub*XD*|&pzOKLG9LNpeF1`%AG zImhj@=$sZ2^Ja@qyuCWnZNf`%lb-y>K~7;}S#+Qd1(UGL=Hp#Fut8=50CwMq zP$MBiNkZdJJ`-Ui19HZMBYl+k*1_M?T4d(a@X3Z<=M7jf_PTt^eRsgsdQAu*YH3*r z@tVoBP{L6z_R6bhs-;GPl9T?E>-gT!drr>%fHlC9&i*gb)L&g-=s~gRECvw= zt|*NxLQ8a))mRU+5F~0br*GuVwzS()$R^C93N+TKkuwN^M1?6;?F-8w1;*~W?ZACm zrF4iYAmcL{@2!~jUo&A2A#-@!;!esTUX5vcj7%t4JQ+}DC~+{5P+tp z7p{z5UxicW*Ozt>$Xh>STP+Ms8~W{(=_ANkT?c~8aowYQSp~;$;6a~=yU3oC6ROAf ze20$Lp60VBAF1d$@WIP+S;=i0V!2zXqna}d?}q^J#uZMQiS$v+8WyG^`F~EcUA65m zXJJj(6gQYSNVxEUyLQ!ar9)YEL|1GjINhecsnX~QpaLX z(}^wCSt_+y%7XrnR!C6V5P(Pvv(1ORs}%vr&MrUs(VeZzx9l$Kpvo?3Vp017OW5z2 znp(=OQj?oSSvP=mutL{Q=rpxsP=O+ZFtt{?P@u~sK-Sq+h51T+o5r^#R_VA?>Dz3x z478>ww-UXM7^FBvz;TWf2<1;L?tjR!FV0%iO`G#Syw8JQ;C+tjkB{SCXue*D4)5H^ z&2q0uasLCm%C^lx0tjIYq}ZVG=LP{15XFzpKbifl$N!A5Nq)Y?0cX4Ue(Q-{%`IM} z0lK;`&;X(Wp+VoXLXhUbAI0_W{lJ_`G3LA=76q~h6iC1eIT8Nvst`bWK5pGV9P>8v zNAEwGQ1nCS-n`@5RGA0=R)ZvhN%ll`UKp&THMsqlVJ-f~&`h(IA|RsZic5s=^jLko z;J^LM?!Tr%xm%}Q4H;})RM}!GiZVcI2#5=YKB_(BN_bMBR zkqji*GU6$t0Z3&9B#BiBCb4!Ndz_T~-LL+6N$zv>Ty5?Rw99qdc&SeOjZ&x!S~yXW zHo?Fwf*j$}$a+7s$o*m0_-Lm;_69j9AHJhHR$RX#x?xG_1Nk z?5=3jduB9IsRoc6g|?$dkIQYq71TQ|@0n^?RDdn_E>x~NOD`VHwt~N2nZ#w6@bT23 z?%DvTKnvJ{;Q#<8z!L+!e2DX!Kg9C(ajo-aby}5eBh2i$&9F`1yz+%)^%!zT-Tg7} zztz6c&(+wE`_y0F`${i~LLQnVn+9rF%p6Rm^`y+RjJPjCXRk$rATy73Q7lN-YT6CE zz3gz%A(AU?TPICg43un;C<2bDvtmxr&cY;%l+j2M1njG)FbR-C8#>c^RcXS$(Gfr< zSWd@FW?~?NZOo>blEyX&NP)vN_UmdWcTlRSv9rW$0N{R{yBhYSdcUO#v;NduyZsSz z#KmQtDTr}IK%l`ecDDUa9P5Vi`Yfq#oTY=dJFvNC2TYpAo>QT9K*Sf{Jk zW6a_-g*qiM!hyEiIs1qunRG~jx>||T$QIpoFftnEXG%g%kHzbZ=`=lN!-2C9#%ICG zmLRmE<1y(F)->qTo_Na*rpU6q=X7U7iL{C4R~0esD4J{1St^p5${xyhwPssu{&Z%v3@mS?K{F}6CCaNmBKfe>#s5~i>+W`Y7wnPRGh`#No!nNAMX&3kgn!`` zL;(?AQnHjXp}q(`HPSAE`Bpe(b(Wl8U>iEp(})2;Kt>J`PQEjj!@eGD2klqN2?4|I zynW4@isWQnngdV}5EmX&m;@I*+ZsV(lALY3wXq!-czw#^KTxxDk4ud4H`cGAU34`e zB4U3*;}W%;a{OB^kJX>YbE$dmm%`;(QC`Qz%SXv1dn~@M1`&KRPQnM-I&uHosnSFK z_vv};7O#`}*Tq8!ek)NC`ym3NQWZlK+yd#a*=DFDfS2Staf3eIHzSBqCUGf8`y>1Z z*8v->&gmnOxQ80=(8~YsWmU3+J0olB{dQCob?dVHwzu&|a2&g(aspz-06)KZbGTARC+c ztilZirqKOS$MrcT+zL)3jRD!WOIbF7uwIvmnMwCJptL9F&gvdd=+il~gL>>=Gw0EjuGmx(VtIBJ(n`G7C$MiLefhzj7;1$8ju7JhY$FDLY@7HhNV$Nd?ikPv|) zPx}S{4@>`--|O@p&J)*YJnk`*^^?YyMR6q;A)L7>N+KaPRWFmZ@HDp{8_dSwCCN_8 zUp0!;9r%*}--WgB`o9qQa$k#ry5sL1)l9yQ&u;%Mh-N$W729e2h(4POWa1OTwY>)f z>YwzswuS$PGp7CiI^*Ck#dpmV9Er@b_k!}zKtZjbwIh2LZsiX6|3Ve9fz@vB#|2pT z2KA8r&C?Ko!(_|~2xWvV%nLfrrYP^9(7gHztG3CHJbLLpGLquGSI~xnC`z`%&5pV` z1yJAVy6{$R8Q1X!*$svm?q0=JpzfM2%`&_Bc-P>qmqddTWtw1hWM5a8N1P}v0l=^W zPxB8XRz$Et+JZ6TcYi1rPISQnO%goCqml>G^7w@(HOMKXDO6QPg$1NaS_%?@suHOce~-bvEMxMUGI4HHVt_)Q zU%k3Lu8dHZ`uZQJID!zA$jl-EA%bp^gt1OqEf|x&?WHYVyjh4BqU*$?#k>C zAfkNQgIf{^)xYuj-Hfs5-h)=wSp0Tv?eVqZ#&M)3O^X{breera)EeYtCbuJ$sAZsv zh)gI;QpmHHN5HSO9!H#~|TY=4RSzEQf z)mrXZvme^eyPJ!{IBrp9|GpMQZ6m7EPwFsC)0OeOMz2suQ~OJReJD&tH#u>7lC>oM8En<__ zPEAyEm!Tbc+(9WwCk@G+ePO{tfVV9Fetb>3m#w7>5m}#F)`6?2HxAQA_xmF$QESgt?V;pp;r} zvdevlZ1br=b9`sltMcv?{8@2QQcG6%wx9az(N~M4bm4OsZ&sxWQu8|5dv;+661g!r zeu#4f5lR@J*NRQ6@(f(HHcrg{h|?dE7jML-py|uYw=(&)HKq zfzH#ugR1%4C)2MNYnn9od?{}hCPzf$r{ixnO4IH+Rm9@k2HF2|&B%wp^Um*O$*^o+%T?P>7JUQoq*4^Ae(v(ZrrNF=AJKU>18Z^Jw`E`5e1de>a zqcTRLDb}T>Mo&YvQ0oPl?W*Jb@Yz!^;=RykoikCNSbm>|$9qJ)YOI~oD2{q!`sen-$@_Y^Ib2RLhjO){&jW!ZHre`@VyjSsq-~- z^UWPb>gw;}=H;KN(Yo%d&0}yr6uslyWZ1|WV9u|>r#W?djLgi@UKJ{=$CWfJVTG>I zHsQdZe-?wKl_(=yTat-A$YBJG1Tt|9t7Qt4)^vZvz%}D{%c1O7Q*n^SZ7)_s^DN5Z zV4+=vzz^a>m4!q*Dq*r~{4ZNs7PRF!IX2PEPKR65=nC4v_M;*_+8BYJ=|SYg8JEIyWRro!j!azbQz*FXA{M zhDS<;Q(#L;8~o-IDeZH6sq5@qHAya}lPLD8QkCtE7UewQ1QN1e&^!=WTlv=|=e4Xw z`8g-PRuL^eH2vmjLw5c}a4ev!OApw+A1ex{jPBX}8DderxMdYuB%!Y!P)qr;U7dV- zXQcRb!s~nG4nO+S35<%{oy1BT>$OPk58$ED6vRKF)eF|{QNsy0qXA=?8SLZ3-9&hh z&PT*|X%wNh4V48B(dj8>mk6>Df;WPetZqF0B(_pw<$_C=%OGfMxrQ-Bq$z*5|L&ux z{-5|@@5;MBZ^v6dE_yUxvhmpBFhVH~xKkKl1kxWZO_>1*J<%Uc_;yag42fw7E097ZkwW|?T-o3&UFNVS0>1I&4Yg*^@Bk9K4zs`F-&X#TOk zxIT{k36HIKR}R))6EciTTdTJT_>-Wqmr#_NW2vEqL>KP#vw(pGEoA|Qio;r3h*;54 zsv<`XR2m~yN4@a+ysF&eXMP=^NkyDvtWP@Y(m zQMJOx_TtSF3d&%hVey75s_byc@k5SSf(i#f1V9lGNdr3)U5Y6h&Uyt>fTlm`lbU& zgpV1iGlvHCa^adSBJMHNQgKmfqi0ax>IK?g9HNsuwo)35-FkB z84W?T&H-?lI7VTD2?o2DtYwl=g9b5*YS)Yyn1$7$H{lU#jiCi8NR9~HE;5FaHHP7o zB2v~2wHH$|A(T07j&&4;GH9|>y+Kn9>bQ!Sm#|j?`=LP7Jc$Z5FU%*>O;)bUdreK( zeBX1;`R;F`k%D_=D(hCgp&_7WE>3X` zZV*eMvh+L@h6oV~=2Bea3?lN?xr))8I0nR>J4(n#?+sr^!|OdawA$_chTmJm&cA+Z zweoceLO}!(Vk9Jph=?%959j=D20T;g`aNY{`W`dYKWB*yFDw+a;!9gsJpPCD73ML9 zf+kEr9Z9m^7cj)|5AbS_D5@!1#kmFAmTS*GyNG@QGw|M*{D1Nuk~+S)R4Uz&rfHmEX9kzEzcu!=#pa$1WF+yZYEh zoJxZIT6kN<`ZwR;*4KsD%CFKxN502v?DFZHb$*^u`?qvg8@bPmEIurh!CQwu#h*sZTLSCG82_Lru`GA z)68mm%an=d+D>Itc2l<_kN*cQj82-7Ms3jt7l?L4MZTQT#inVh|3E=`^>yu6Oj429idO5K!#o zp~T$`t@1KKwg(Q6oOKGdmJ-6Kg{lnw3CNsK$%^TUAKVV#{t6c-N4YQp?O?!~FtDZN zCQt(q0S2G>VGZuW0tr&!F$`c0iCGLVVd*SR>!?4y+CV}R5uC&0j?Q0uTKiG<;l~wI zWoP5dKchbu2Vsn+fl@_84+P^(WHMge%Okk~5RedCI{kR3XCX;6CkCajUM(3|bg*-W zFif<_;%{gIDk{+vIz@iHa)5=tclpHt@Ayha)TP+YLbIzDI{pSvvxoQe4RV4EJPlX1 z!Z>(bLl55o&pCFuNL{qBQd^P3(VZc5EoqgO4>iunK3uVzy6g49ZYLWGU|F`cbFsL4 zxBZ=-aLVCt-O$_kw*(nSL=^1KJxAZJXw+yU=G4kM6`I3{~ri5?f_0%zWf&6JANzeo282-C|anQNFOuf0AL}4K>1`oc1^JrgnvEI@f>azoO7S@ob#O|?Z>Z&&wy=3d|0 zZm+%oAoSOK>C6A^3%E=K(@0G=17m44lN%723A7D1kkUgMOieZ}^DgW?oZ#W=5oOH%;0wm*x1f4HBO@&)6L4TCg9(tvppEi9qY0ttf> zeHLY4t(1&U3etJl0dPn*2E`y7ND^WgAnr#)_%p9{WojT2ILI4G$%z?@ahWPHe1}PmQe44R^eK33?Hg}g(lO368S|~<{&Ntz zog2ip$^9G`n)4B7_o`4H@JWM7;$O+2VM%cPHJ9DKn`Y!g3`oC|l zT(vezOP$^&_9L&{l;>t=G!mX_O^-^5Z8lWi=54p(iIK%hDo=Y zHDYah2C)e^kNVhW(>FIlw51BSY&RnNa%z(R!uu@+&r2gt+Z1eT+c-J z-|%~-PK~jK3Rc$4OJTFbE315a~^WKPwzzDurC7k zB+XB246spjD&YL-XsxxM@>7?-ny&tyQAgcHnr(@IWZMSz+7eB`Oy7bUq|?RuUZ`?^?%lz;`=zd&9?L5nAlJwPxP@gagrOXcJfQ2 z^F^b_F2(zor0>dl`C}^Z>9ChEB&qkTTZ|6;32`!LKqQ^=H;-5*2j+tX1q@7ozsSw z(0p__mRCQ|#`MmWqPJ40JSbec&9K*L5yQnnm`5lo=F5s0Z>GG!`D`gZxqLl+UMT`I z5$Z|UUTkj$)M+$WTTOLe_4-^E6@{vKme*EWPOD41-_sa@{2$ylM|wA(^yTj~EVjUZ zgl_d`d``MRxVsN!KZBeU9x{Qd!<6q?@0wZcw;Eb<21C| zkGcDv*e7-RuTM$)u=R7ks-U;IbGU*R7EDn!ltEHxO({ZR(Rh&q7>pG%4je`}K7213 z(?J&z@E=GVOu7$=fYAv_o1r#lVkTDAYW2U7`5!0$Px-vB_x@}2Kc@dTcWu{BduI}E z_d}yj_il!a=1E|!%JDV^P0kO_(;{mcJ`1<0Y5~q2MuKY#B_kI49_QT0wjS1__s`wr z!3*9>G%+xlNjrv!sm^DOzV(me#MiL-uN3z6!NCVpdN$f1uM(D#wVkSc-Te@PKp+H{ z_t%bZN5XqQOdf8LZWu<@cA~ml&$-WG^s}v%5q9>wd$sf78&BEkRVZ1VK_`^^CFOLZco{TRIzsN ziT=df`(3;_$Hr-UwmYA!m)&0u@NeM#XYdHvRuf>Lg0TwCj2yxxO98E8U9bK5-28NE zcuk;&56TSKDqFx3R$wwEAxxt7EP_VG0DL51uyKSKYm>|Vin)K;=wI=8!{PE@&3=@0 zzxMN%n{aot+=Byf;MRD=M8MQJm=OrLCuSMMa@h!M(Q53Wiq5hKu{KS zH^!L8vp1c2f?rOdma5ZCSBP9=r%R=?(3Mk=#ILEf2O8&SRb5D#Pb|ceQ-KL7T?jG` zAtVg7QnA#n92Y&6&N!zS*0efYLA~RRr6{X*cEj=u%8%UPSVi`hp9OUgR-hq2HKGls5274ps5Hk z!fNrd(B36vg;3d+%&cibh%gP)*y$)?NiK>q3}tIsdUWvG1aKr6NS=_Dk+C5(0YL^r zX%I7= zpQFE=C9ESdFDC)2<`$-Ua|~P_2pY6)ka?S2@q}KE8#)$7GLgozAsSUt#jO!*6pO|6 zz8mBEZkKl)&SszgcKptZ$mr(rA=Ze1kKYT2;5J`kNtwEE%hwY9;IEis)nFA2n9@uKoW7 z=e1Yjv}#V>(`T%|194Sem#>AY(64(sHroa~#tbP1+00tVH8fK95M)UVcA4^LW<_>a zoEjp&8n_0`lpR~4W|qw1AWwJtS#6G=OB_eHIK{@-74~?!pod2CTt;UDr=PHpmwD2V zmQ0`%{G#tH1~)gQpSRz`(?2K2_Yf_%Nd>GI7OyICq`t^V#`k+595r>2M6Xc%rIB_M z&Bzd%uemTX+R|kY&+sPshbG~BO!-(Q(<_5+HymNSlLT6UFY#fDw*w4imdosmT2AQ& zVH?};7W<{sImSl?@yp{AQ4OerCXzO;QQ@;5AHwCEIqwwGv7WnR`qG38 zK#-rI0Ny$jfFB_M58t$#h?wrA6boH9V`!1tKDWW+At-~@|G!XnE~$SZ;ImLacStn|>;r zjxJrWTB}HcB7(a)=rmqM{r)CZR$-c@Ucpsc2}-n84N`+Z3&?09NcS>(*nM{2#nZ2I z5Z`w)CC9bK1%xOWR_Nk{DPPFjksKcwgo+5*FZO;Yh?n*#MIJ>xF9*2p{gv)MJ`7*0 z{3h=@4l^)Ttp+YhIYUjhq9C+oGSJf-X^plyDU5I0_ZW7}Kl^7vp2n-u^(K0SGbq*m zPe&A$}f46H~*4MxAJRu@`Q1 z*98c_cP;`X`(}6jJM|YSqW@FaU-(aJ@eh41POD7|Sbkev;pcnM{z}GvwM~GF%r7p- zoW9~92aTWgrL-JF_=j3`5MMq!Ok4u1@26JM66GBT%H8|*z1hX2TPH<_@l-|N!AOI5H+80Sqi%pIdAjpRM-gSlJ4)5lDD zI~efJA-OcBBs$gYd}q*ndR;c|^$)7bPHm|2_vQ@Q=L5G-DIbVl>d z*gUV25_c;)aRU0gXQ0vS%1sm~2`z*+jJ-`Gj4(wZCx7;NWgKZGF@ey1mv(fW3+8?& zALsh*eD{Y#a`f4v!G4|56N{thyoG5sSh!#*>@806hx|qH>G6K(k8f%qiY6Gi0;EE} zgt&@&Ihd8@`D3~(uw~&RMmu-7X|(o@P3%-$tKBVar0K|r4q#<_5KIzI zmLvkKP_OB$3I(Vr&j|s&R7YLoa}5QF(>V6?kAT~*dL2+msWz8}pxIhlRxC<}smA_F zrJi`eUx&Zwdkrb9Q-gAxq~l==S^?ChKtNI#Df5ErjuAtWDzWh?{|D_ztQ5vc^YZi*U@<3 z5|V)k5W?nQN87X|1NoWXzxUtC?`ko+;qCwUolN_jEN~5!M;cIJG@4qD!h~rPYrk(7 zbIIfAQ+o`2fE~8hxI3!uzc!ZX{IOt>K6c{9B3bydNh2-~prrv4s?C8h& z``Njfd3`2N18dQ0*v5u2f=C!&_dhE|7W;A}`3K1I6%c*7;Ox4PLr3HLsdLlsKeMNe z$2Z}t=9;SrUr^M!v0>Qn%ECTPf;916&-Z@5*XHzl0rpHch5m(4ab2=cNYFHgPC&=M zSM{QC`(AI@C;sUF(d23%VZ$k3@oD?J6Sop?SQ$JM<;JKj^? zm+q+u5!up!B>k?fTtCcG3%9VVy8j@W@{xyA?82E_%)U}6sR(}PdfbUW~ ztZe4!W%^gFQVzg|YL}X>=#|;r9cL&}Uyq_;rHa6Y5f`ngEE!jQOSPWZ!u;=Yjet1! z-2?{J3>~+?*7+?Vvfw`0cbOc$Q@q_!ecgP|@$jfTL>-fr!f-W*!|a{Zxza+Y5IDjR z33nj?lx`>4RdMU1T|>?K8-EIknfz;WBX_iSkVDQm+dZKt`Eqg>CF~eY*!m%A!uWsl6rc^PnxZ~n`-gEis zHMbgi{w{{k)Sflhk!C(*QBxSjncrf!|8v!E9T)yfgt8UKrg~RI;k@i9f{C{dv-74M z_DPEfb-djErz-CM%ZFzN1?-!RZ;wjuMsNRW4Mh3|3{v%d`tXM3O`Dw8gWOY|JRBWY zwJnzxx4EyFv>$eh94lzy_?OAIDx&;_tX?K|M*+>T@5+!L3jQ<3fmTme&nU*ljEsx) ze6Vvacs0_zcK4TBjy;ZBe**gnW^|3|>Adei7U2eR1vj{$B4MqF1UsQfLVf3!VsHAV z97Dye@cRjMTl)Apcs-vXaEWs=m5b4+9s&%tjfC|gzyG6 z<-v!pGhh;pIc-uMDkCRm75OE9M)8q%#n7FbIF2}th&Q=eJ9E=PgTqL|jc=+tUo*#L zEJ+AXrNlLEj9kT~$25jT0LZA}7R@7#;o;ing-Rlk2vS>2xhI{@HxUs!mL+7pgrb#K zS=0L7K9#;^rpZJYbeibvzssbDjb;Cncb}2;UH5bT>u5-u$orKq2(m7^{G-1)jKLuS z#aWeXws3i4>h=k!_mo-BQtv~JP9RjH4KKs88YT!t+{l-yGE zs7nMW`x12)n!lxk)VX>hthEoaTSVF+cRYx|uAXfoX=T9aMhROmsevod6fjW}pY*-y zT{5}T4DC*CchjikA-bgT*0=9_lhGv?Nure36y;_QPh>5*8<98p+2u~L99WIz-5M>C z`5!=+$+BF|dore;>n^Ray=tCt^H zB)DoxK!a(<;d1vUl6Q*k9fW;GtshIr(&Z2Q^i|5{U~ZkdS8%TOcRfM)+T9FHicv*y zf#*H6GD`hXSWhI?b2)E^=GL_~w}vPj@O0VT2cx0NaD)zY^ODZn@><`Wr>Et#zQ6iQ z=70WnuJRiK-OXuLuf)l^*=o%u(v^wZAv2AzCBf`$yw|B&tNT%>7+)us?`Hep+iqFy z1`jI4JT3UU`uFF1>Y;_pMXyTswYllmLaZp(^?%n=+m7)-ksI;jc$(?elh-PuQ^k@h z9=3iX;iGRR_EK^^@iDLVuYRI_OL8}N8F1KX9DTa*+)md=WREFir7FdUjAO>h>6$P^ z)+TNT!|;T=r%$mr5QeZIksCi zq(6U2#Fmz&=O$eYvQoE0$(X*Uxmc!5vaCUiOBeXAQE9S83JwJ-YslP`X{AKsGSX!j zrl;ui+~<8iM0+0&{S+d*htAx!YRGoX=GA?fe-?=ValHjkHYuBf9HU2D>^en!3uN$|_e4YhB}N zTko{O*k6L;c#H9vN3(2xc}Kr1{=ER$j|BbaIKTGS$#yHWwtQnkX(1m+fAp!6!mIbR zscbMD&1}(H$_7V-g4Cn#Nvn=0MQo6g&_Lgcb+m-DERwejTy-L?A^^jrHvT_3i<4Nz zo(bp({NaxgZtZh;3_?Rp&|QTzE7=xX=F-Sqp(J+)HP+5@5)98L2`ouM9Op**1R z&G$cr%6HC2yG>$tn&Pr&f>FngC(Px*=YiDLYj}0FC42A6`${vL?>f`ru9|JS*q8P{ zA!p=P(KL*jbt)v8P}5sJY$oj73tx9U{aHW$}UL z76|5izTZ{M6|98M#Z91n0zC5ji>s;;W2nTX+%!LAA4HrfC~%IQBc1PBE~nU5bAIh$ zDDHJmm8UGhAe<3SFSXVtZ#dg%DiRt*i!0CkFPB0uAJ#&$^irl(RZTOJlB0ncH0o)p zoJJ!~PZ-P+^c_3ij!rRot%Ho}@u|P_x8X8rT}D>d$u8qb{#}CU)n~KxX2Sq+DBGi+ ztUxCU$OG?^N79+(n9&O%GU>i4N@t6!IRg~-Do2z}X{HaEawWnLl297sW;Y{S>B=TJ z>rt9`t~zEH3u(s~&m8gCOvLZP1jOc7K+^l`odjPKq*3O?BgXc;4_js!Z!V zxn}T8D()6%xUmmraSuaTr{THq||a}}*6zSq8sIP|MuZyaH1yBs8MtOZUk6u`M?eKfj> zCR`4Nq{>H9nNlX2aVfQ8Get3&py*1;rNeAan@QIB#>__PR=i@g**M-o{r^%pDhkWg>YJ$T31Vb6wZ1roNcyNa(5wIfy6`@W!PT07P zOO~7I&uv5Ik0{}Z(}KCaym;bP26V0JHp#v2qAPuMdB|B>ZgCKP!iDjD;H8=1>o10z zP{w#H9v_pK--^iQRIIKOGp9I*t_@}KchzyY+F+hC5@=57>Q-wS!Pjjy#ZB_rFFb25&?nQynyql0^7=r4R~Pgg$r*V6&!hnu$cVE`bQo1g=jy z_Gx|(VTrb;^RY}>6vBH`X&mnOHHyBu&hDC#(-+`uu8d&OVL@(cRG`SEF`2Tp(R0;V zwA(tRTUMo;@{{}YZ0(-ROt!Exq_nF z7S$|4PntAL)U261TvUnr2^uAzZ6ia^eWC>MsMH zq&QYa@bxs$3R}e0@lhL>LL1KjWyxAbx2@}2gv~83f3xO32J=80%SHd(<)prA8#sAF z`JTdw2>;%*dL)Ix@jKuFfB+DuMvp(Im^)-&$IZ1b%cHLE>s=ABSUxvsCXpShACB2d z*NgEbpHF+}hxwX5&ZB|eFt#+YNKk>I03kHe1lWdzLxh?T!3}~y#F}6UQ zb)tOu4-G~JOc4?eFM12i!-DZ1ke{JPCTQD=GM)SiI+Nu@6A~yS0uFcBbkntySL~QB z5=s|4;XuEWJ^L@34xxrq%6~PR7FqY(=TA2JH+Ir6dM{Tmb(chu?LB;AGd1(!8_Nt9 zX~dLYuht2rmy zFvViauNS6r6@G3K$!5u;lXaP=b8DY>KUOnT?RV+rnSL)Dv-!HY_<5gU2O*}#@m`-R z(ADJmEA_CZP)bzcN@YW`ng2aU`LBQMWeLu3;^5o=3Y);Fyuag40kSH_#a)QK?&9Fu z6)_bw;(@ep)$}X(zRQyVe9G+n_!jd0`~(z#=NR|77IA5;)ujO_dxN#N1P_3d2`Ph` zV9^5+$diI5!5|nYq5&NsQfL;Ti}B$B4HAwM(FXu!7Jh#zF-VRsB`yX1x_pm6kwM?M z-IQ0}S^9J*2To>K?DV!pU4-~ZTB;-Q-zM6>XEg8P#jd7Q{!6?6e2d^&?xbsp^ey{d zX6p{B#t;hwXO+XEobDBA4V(9=$IkIzr$Ov1*BZHo$VWK+UD|so3{uCL&i>u|hbqW* zGd%w4j*~4(>Gg;B)#3GkhZGhSSe{snP#vlqU{oRC54YR2v7|Gv{fxo zG*XBZjRRFfNHs+QAT&^vqKXS5%A2WnPa>9Ko?=(r1+@ekN~A@hi6p>jjiI!PB>v!o zVGCie-0v2;eoi2y*>9SMEc zp!fkKJ=;wNe!58@&vt-C*t?`-6ouJ|u0-L+QW>^i#rIc_+2=VjptQdIR0eX2LY_jQS^^yj7CN! zoY=Rv8dh#tL$JfW_BJcE`2CHV3M*Q(T8F}5JO-ZSoI66TW6@lyKnEQHWDDaIqQ=p4{y@$>Y4eoFqRBGUV2g_G)!6;@Qzg0Bs^O>c0X-+ zOn>Vye)1aVvOEK5i>#8Oblzoant5-o=13`N*EcUP?wQIued@c{dphEm7 z5aAtzUdg0-wvs+$TXK2$kVmY6{~x`d9G-m-X7bIa!~L<>NZ!|Cul4Srg&QDr$77gRYHro+=)@?vgz?(Aa@C0~!{@NJVphhy*qy4OJ^&Ybc_KfS{lr z+v_{b9#9$@L=dG4MG+N5s%oebsVGqpq)p77Z6*KF-n-0^Bm7f;Zs&L6tq*;Hzuqj) zX8pDt^DaH8r^VtBmcp&_-Z7^v^EGI(`1laZV2rUq1W_)&_gFQwaNWoU!#V_Ro7&5g@+t-kAy(~pw{OH6+l>-S)x^E$1nn^DJs4ql*j%2bWTI8b! z$o2jrt|S6QT$-jJE$CO6eh~M4HE);J%9u|)$DVzo`yW|Y!p1NrW@ct)W@ct)M&C2- z`gy16iRatif202&k@+L`(s$E}vhXGH{|tIQ6>e^KS%~T4JM=GH#Zv*agckSKph-A> zWOtdj+wipu_OiEtI;% zHsT@lALx>t+lLXD`Munhtmw^$1^et2;9p={nJ^$1p>Tb*=Nx0mHR6KagW9X^OES|h znE=9OLgsgA9r2yR+}k`4jhEY+X)9uLie4=vCLjrOccB?)CodSC4rT&IR(>7yL3AERnuCQkJ$* zi5GFWVd!DbB(^#TTs)rD$UheodwW5=6s+_@JT{)v5`>tKlwh#%me*sz0x->youRyqKFeQ2W9 znj((wj^gI{-a9UH#e_&mQ>AyHkwl{+{5Os1DamP}=8|Eu-)OGTpL4rcq_5ESmn>uW z2U=7=^y`M363|@HgMEi()_GeO{%`nAdS&$j6W%mUWTKQm{lz5FpAVIXkNM30+LF6rx=I@Z+{9@5>xD{AKy{~+C1q?{h%DM` z^NjQCNPAkGB$Cikr&F5lw0c&WGUCtDS4Sx}<}bzexC8Kqa}qp};_!}`^6|m->7MHMw|Xv4@9<8P6b^Z!58Lx@-6;`4 zsE0VD=J>7l!7eiwwt&HMRZ#nS%+UllN)21OC) zHA}BBoaLVk>;zjUj+RzRU?64TWd1);l*k!A+LYt!eem8dP?yUW61Jkq-)w^Ju2Cz{ ze7Fz;5y@TF(9v_FuUFfv+2`;vv(>5Lp4O#DZqs34w5A77(O9%+gV7$i3)>?cfKM4+ zLCG9**^WD2f03HK?3HQ_>tX(O2^kZCZ%AHTB&Yf4$(k26Ef#s9v9Y+9-=HK1*!zNr zA}Ssc3(h$8>6!r~2Of69CG7A(f*?EHFT+>q?klr(J%kI$QNQ*s*59|3dG^saB&Fd% z<~8bhSr_9NIs2O>!R24#V;$Eb?^5E>8n7?j=~LFVwu^kK-%4 z0PPkh&XNW3WdchrfG=;#`>$i&?I{xVHsi$T=Olwv#FpXvo|-(i3*G&%b+Gb0FAJRL zS3dY^YVJ!qzCcN{0gR=mr`}G=;J@lCEmw|u>u$2gal=b)&=D$-ReB&dAc7d$OX9*v zhAOwOVFq`@k0PdoHX){l(m;p{K#eqljUufSB`AWURY;>khzKPJv;vJZQqY1O4~ah0 zD;tyD`1UGwSsDz)RQJ7Xd)^fXz3*Gz z_l0Wgm%6X6_ME1_0}qxX!({W5a{oJC=T%pcNyyzr+d19iCJ?lGZCf|bN+E+8@>(FG z)AD3#4^YKb?WFJySH{??u8?TiK1U-xG}e}ktb%HgL4O^CN+KS?C+5O@KmKCyB6vnL zYL)qo65#uJ|L*qzXqgGN{grg|NK3a!s5B%fO(6qqHnS4n_rfmk zz^RsbS@(14ilU6+05ByAQB<@PEmD9jRVzrVR4G6-G%+a9O&sZj1olPgR(^INJYKdv z|2yb@`h*Cj9VI3cAwo|_Lmws{jCuGI63;SN%BQ|Xa=k?g5cCpy9}rJjG#>|g)hcLz zycJiB3nqz8K>qkYc)3Rk0tAGB` z#TL=AHuxWR?|Zs~B!6g784YP3(>k4F`AolDoAozJ#lks@*ud{aN%B(DE$fg~MtTg# z#eSzbq{7Yl8JyH#OIBTB=yvTl*BZ?yYnkEdsZz*lA_3C|?+EHPuj$k5o`gM`aOnEf zBS?)RHSysNl6r>JLWo44+$Ck&A`B$E%UFhyK_%j0dp;Mx1WteaZ}nQ$_>+X+s-4L+ zTy0x7NmCRGnd?5T0aLS8`u|{i_aQ^w7lN15fU$jVN9fUl;qeGdDWH08N(brW!FAVK zs8#j7GyEJMsotRh8=yfJ@s5#HltaODW*$`hkB^AgjDM%4@Hzu$qM52a+&&I6$X`)9 zpZ4P<(5}pz%@FToQ{jJ?;B}ih*II^vRJ(|C#FzX2C@5}-hB1PO?S6jK<;UC1alhl! za$bM9xZ~bM)P9tBu-{Zcc~6kD&|DLh$lkv@r^R}mIUhsKma4R_Pv~;Hh>kX&3yHBs zSIM^4WIDsaqqqv=DqwL3+AGNM{X*P1!H*N-R!NY zu$vY)eKj*#mn^_6UO(&qV!cdpR?mQ_1PKrl00@8(MABd(p)hFb^j)PN(fXQL#@hpF zYzER8Hk(aPgWZUyoVC4gn)1S0hv3ZZduw65Prz7QoXQySOZF8aSgRH0EMHS#kw5jF-ahT1Gf4uB7Dh<`Yx(^E3-J) zKQO~^-&j1Pu1=KoXy-Z3b9?0l2xAz;;;)5nj^XiJ@m_m>F+GhNDp$UJrvH)QPQC@X zA2;Yn5|CD9(-biWeW!pIotK5Dhk$@xmPT zfhmoq0Kp7GEVO`zn*dB0l5GhUpdfS>gF8V!_rBL1H*(L7Ufotz!C*jNK*Rhm=fpzw zFa7*D*nCtlH6!fVqiX^bb*($vKM4=|b6oSETet4B`mY`IJRVV2i%x+pfoW%v<&CN| zFcig_<-ngFw2g7@Q-31n^9%8?KIqPmhUwYy+n)-VbnN(sGLjo0dSx(vEd9&TRPEfa zeIG{oM9!Hg_xwJ?_q=ii%z6IN%*eGLCUA2dD( zS-bGv$=<&QM$YAb1+MhU9road&NvN%Nln`jr+%Z!!w8we0&YOVXzTvX1i(PX0AD%G z0(4##6rQVfCn-_A>#*&WjLmDjY$@;fpOZj@8LnX?d!uahG^F>3(+^)FKauL;;cy=M z;^}8g+28f!XE=5FU0K;S(RoWU;~|n@+x)D(^QWBa=p=0j2-%Chl(|a=mUGPQWp)Tg zEO|E&s&|eax)gC(G9?ZZzVf9l_79@g4{_;##YLJ=qwn(Z8|Uo%Kjrq`d!g?5eKzJj zF70m*q{KT`rap?zX=)0HzX+y0rwnEw^_av^5l4oVL61mCr+g0Tj<^pgFTkG?G{g&7 zaX2eDDrXEim3eRrt%ETyn+XuzB(I1E%{(m5o?@ELunl^I7nDDe-+ra{7$Cz4!on z?=it3AO@O29mi8|!xPp(P|`FmdwA$%Zp1!u2Pm$cbK@q_b1ql5^%_03elOE1)?L3X zoizr|TPI#PD$;UY96^!J!mGTTNTLpZd-`-u?{#}WQ{Fqem6m$kH+sys19?OjCy)i< z$Cp9O9e|oRa>U9nX^%-jQTffgFnU97-e!3joYh=W=-poTzw>c5`1#CdIm81hW@a#1 z6l$WPOw7z_?*E?=+g@JxU5`o2>$n>Wz5m!tsj}CwK*FQKOj$qL_;0HFYckrP{Q4`l3;l1dht;*)>F9jZ zFt1Gr(|n7wmm;X!8(e5-Jxu@BH)$%h&L6XG4Dic;S348L++1w*6S$YwvRecZ6y-=D zkI#~i&xBts2~Qa#_Hg)3Sfc+gLBDvVMPGcw{*0w$KK9_X=A@&G&_dMuc7M`AL22t` zr9sduJ0UOkMjNZlT#HJw^4DXOF3lS+Jn}#rm85#tVM+|q=NeYGu z0NMoF08NbzpiB~LDwsK`{I73g)%>NX)APK*fDEaHnOfD>(*o>%0i6`Us9GWwaEXMvSzIcDmD^_ zZAP^$KNMvSyD9t`ODFjl{U#+L= z&cv~5^i=JieX@>L$6oLz3I!75m$7QS3X)$}2Rd`767V%khKzTxUSd^ln2&9`N5Ko$J8=p|nf@9j;}^N@>hOYlc`rmvIsA zQ%#8;y?_Tl+jwq+JXtaEKYOzJzS~ROVt?1u@A$u$Z7&-v(1^E@LKAHp8vGHW0GgMZv|3lt0E|vO3Xmo1aCjsb9CBcDL8RSE87lo1Ow6>JK`kF%$r`!3_Brv-NntX zW&+3hnUEfHoMSCiNf6OZG|F_fNg(8|e0&e}FI}ZGZ5d-?Y)$BzI)p7Lrk-cF{>#A8 z_Dz5J2#Sba$3*;V{f~jONDJ-*kF01On%;Mz{e8Kf^t2fkEVb_JT#?5fb!TW?(jJp~dS>r2F~0XAq^96*AcC_$%urlPL2 zC)($BhQk*K9n~M_5zPL`pnZd*;O(GjWR8uuc>UL3^*%)6|HXOakF3jwe7BF$GGlEV z%evn7pEDAwSj!of+7B<}%8CmQF~{<3$rMCi8qbiNw-_REWD%iP{Aco6EBmCNSNYld zu-5;dL6=8@AC$w3zkieSvdQT(tnB-jp~3oZ75l#HU-EpswGM_-eX~&B>#nR-kd&Xf zB0Thtzxl)cjyM=o$&h_J{+A3VL2+p2L(+ezx3eWx=slnA?`4cpvOar z#@w@a0nleS|6wz9$f|K+@;n!S%NaEfXv69rg|++-;JrBEcUZOH+q$y&z1KC%xw$Wr zy8xo*Ne#SaB{3lciAeAeJ$LkK@uZC#rQ#f(gG#UP#o2mnwmkpR>=(HXe!_GN_el!& zfB#+nV>`BjQXIHN30V^1z@ShOk0@~n40tuv4`D~JR`s+##xzHV!9XmEmb)QNJe%#S z*ON^Lej7h)F5`wG&mx0sdR@O6`d{^&^1Yvfcz#Q(knA*^5A5aAC`dEzU2pByQ9!>t zK)>3wB_;=y`PUh7E+-fOvCsDWkGc4s2Ls?;+d}J_+G6_BT2C9+h?QCC3Q43V5`n}r zPAZ&umGptPk7?W>lM59}DErFD)~jf@HZm*{xUK4JL$yt)`8&Cv{^k-cJiwk)4N+Q1 zo`1%l==aun_y`p;?DuMrjJYq|NP>=IHh$-ezaslS?f6oN@HJ%ocklF=QOAVD@#DL3 zGE9{q$?mIsuBfKPq?KCKiEkK~rMq8lzu1TLJD~LH5|Q^G0s(W!$Enw*#dpNH?VVl6 zwD*ei0(t;dnW4DbSKUAk!j6t(L&1L2hl2za*niWpvY@@?gIC55kI*z|k73un?AITA z{kk4*HU1amD|&y!{t;q7Qh!?NX#Q3rMcv$0*sK{H*AA(QlY$*pF%(qHu@Zkfao*pL zd)Ix+w?|?fkU4_AT1x$2r-iH4G4ird{5c&vaM0EjKekT;?BY;g=0M5u-0)~n8u5CPm%d)Y~IJox+%R~I?{0`sdnl~!%*v^1)J?}=0%)uq(>al0uUbmRmHkS#oT&$UAmJm* zLu_oX9sG}ozCHyLR`~GDea{&el-7ks`ou;l*t>V~n^jhk!%gvQZ#!wej9JGYCh^t-ck0A za)$#-8?8cZ^RfDU#3KHRdrgM6o4QM;xM@dd{Caf~<`_um(Qhv?XE~a@NLPhCs4eUO zdw?_@EKgtwZ2;_}DjHOWN(=26l1`v^Ts_S-Rn~d101v$%&`!8yjRCW0Hfm?%>I7QIsae$dPnNm^LHxgh(h?A3dP#|0L1%baH$J-9Dou?S?{rDYS+Ve*$pBX zHj+Eul-%9p_@z`u);PL}=leZDo9UkV4#SQ}EuuUwpFcrmujX1Z0$B<$Qooxwaod1{ z9V{G7O^6-b-R|lXl^0U~Pgf)Z6-{<9GmU4VI~*i|I{Yk$E02FYj)6R)Ps5NEVJuKp zox{L3MW;dISr-}X%Kz8Df{=22_GR*r7lY#vph4_ZdoBk{@xPbIX;U`VYNR!3AO|E= zh0a@@yL(WweQnY7D@27Pk8F`(9`u8W&U2jR4jYZmbDdh1Q>v<}s;W;%m-YRQ>yp$R zqf$K=_+)G~Ku>^u!(2ltb+k|#vHGtm!4^~{$TjOq@jc@HMGyEjyy@kj(s#4nPhl^M z%!_aHmaeZknzp#liDLx?&(Zfat1IyZOb}>=u-0GA1~G;=vIMO-DykSyhLs-i4+$MdA+zaEd1xuLp_(Zg->F#~I%WL!W)dFUXh(vJmINRL_O zVPMnh;pTlNEAq9F`wiG=eJW}D>sU{)^5C27xZj2YlK3SKmFZv4dnH`0RJo4n=(4*XN@Kdk zVL7jeYt6WPWS>U}2E#~v&IVYUul~uB8jAR*t=jYC4!4O0w=0KJ~I=mzXq6Ece%a^N}(YK-Z8Z)u%x2g-)yIf!kSmhnu zOJLt6P58bh_(*qK&1Lmsmj79o|Bz<9d$|)~0(mgnyc1dGz}EE`$fq24WzhWFPT9=_ z_DDQ?DzPYq`n>_QVg&680bsf>$l$c^=lSpl^b5~_z6$PzgD;p=7xA+9HjZnG;y zrh~VS^CdHIXeH}py_9Z9sL2@>*g3f7SG!zpLId}m;(OgRBc=CKrNLE8xpU1I+HwL1 zhynNwwH`1DzbTNI^}DQT)%na{+W8vCb0`m)HiGs&A&2@8*G|6qf7@H$p`t!3^^0<8 z65_9!hgrpr@uG43r}AR0^!gR6t~%a73Vf#@gUP%=gTAYip5p&D(>JVEYz}kY^o&4< z^9!y^oElT~9#(+Veq9N7p2Tku07?jiXB>2m{1<|R>lu^4-?7pliZQ>r2otv?Guz%T zl)h}!w=D==90Od*RmCbFeb+yj?h-k}tb@=V{eMceu5s%KPs{Mx?rc0>e}%I`@MJmW z+Q=yX`P-bE({c5vp?BV$FZ5pvA+?NMIXAMr{tPFVT0kz8a^qr%)Dx!5 zbDVA6aht>4=}CR|$gP?3)wi8WxHasIG)DebUEU_%JGt6TG$!L_lFwpUi+)wwhzWzA zmU48idetfOQ~Gc+OXDE|JXTx%hWWPZDIDZ}W7`zRoOc;$n3JPw@_}r5MpXe*=tnAFHf4$Ikjhb zX}@$eKd{r$+UxJsZoa;8X7bl_s!Z5)?FkK>7eB~mG%>-i(c4=V!Hb#Qak!0Bt`uaR<^j^4}pjPiuc)QgUNV3-hNnQaW`fMlyOV^VUFx{$u=1o;gFabT#r-9Zr+WrJ%Q3hS=Z#~&13eND z32p%4j`-0)YbiOMW z+#OH_lvIp(&*>?}+?RnPlLRNifCwh4 zs8E|w2mkr78(P+e1%SXJEBhXI{x?h0D@b`wwQFPYmG-$k7gAhqOU&xE+s)Ad*MW-% zNmnETib6@Nb!R5q2q&B+#{geIpuZ|I^NiJq+_-HlfN?TZ#s1`4*EA1KvctptKibXf zI^OyZMTO&RJ2!pCcOA{b;&RO3nR}YdOLArY!PbUf&#*};>GtJWMKO2@0Fx{!H@xd#DGPM4}6!=62v6; z0Kf<>*xRwu_%ap6*As`uP%S~(LPsT}fl|`YBNtwG`$($i&cxk#n=IyH;Ra;ZUFedx z-(cI|wGk7D?_6siNGoVXniL7C_EGz^G*fUf`ElrRtFMqWi5l{D+`{AtH37WdEPKUA zCjsFao_sC>XI}sM&0i}Jj)H1lq#_r6Mua^+@=J^4x}(yKsG1@Se=2u2I!yc4aMKu4 z`hBSImM?+;qnh;@@cE00^RtspmW5e=vmn+2K_DXZP2q_5p2QFe32#c3?vygzZo4Wx z_q==3Saa4oBtGo)sI47D<2C{ZY#iYb?hG_l4)>>!EQKlz%6~u%fh5x;GJQ109e>sF z1U=Ff>3Z=wk^J*IK&_>h;|=7 z7J|g??BwUqS35Q(gR#juL^4a7os&E5WE#CW)fB#s`mWO=c#qnnfjav<+_m2eLRV7S zv&x{&&Q!uh&rn88UlX+$B5}I?%>As1j?QeRy)>ZXejT5ej^N`m8zpFoM2tZq-~@yZB<{bPi4c z5kT5g2m%ApyIe#@jY8rGOOWfHn_hP zu>0B`%Bx5YGtVU=2h%CPxRFzCBUqe(l3N_o_Ms7u zGEgB*(@bat!P6b{k6zP#l=!^jfNwpASwt_!;5gc=RkT*-{S%5QbOnvj3_gy2lc$dg zJLSpZ{e_*SH~W0)#Rv|Ee1W1w2y>?X@4h6VWH+FI_@Uz-AoAKibL&&i;8z}?!W9q? zY3$dgcHJcq(DV;t$o3-G`G04m}{r0bm{ogNuf`3Wv) zM2*N`L-|c82`xd>s#*mGp8XTjdVWiIaX0FbncyO^^W@*wK4Abu1u34%sWy5pT6zH+ zE5#~0PRU3S8{?#2GB((fJG>-C0!pRBfB^?&5Kd`7{~Z`Pa=ItB7vx5sDp#}fZbnij zd!{i5ym3usg|-oj$@Ufo@JJuFi!DR8g7DykAqZXtwv%h~T*R9?J|;w#haBNE+dIsB zo!)ClW;hw?bbH@vRofd)f*?SMk;$dhJ8Hg|Gk=cJZw zER_@3Z2hA8(sO)iCl>^!pLfteA-X;?(ytg9ThPW}StBMp)7rEsupf(T=Z{qr1<2%{ zb+8Cd9d!j5MuOM{0@W^0!pQb09brKuDEZ(K8$8?=6`~(jIeH&tb4-h9Sm7Ovb^b@e zUHxK3jN_BQt{Zo@)MM)S3FQeAHT;JF~mKM#|xYNpXXSlUs zVyG@z7U{r*G8B>RGy%XaSV;#EiGyvHS}#sm_k)$nuLQi-ImX(Tew?)fl;@IHYxi8{ zwK;VfPKJJ)?>|JNqqV3x+!eJhMXllZbN4~|;#BUg`fyTal zj8xnEZw{A2^Rql$f)qQMh6Wgsrh@Hh;b7#P+%lN+yQ-w%ud#SQ@pz4m9}`0dYRkMZ zed8fqef_o-{MB;<_C^r)Z|gRV=PpC4GK+#OeSo%G+s0&Ul36Y;KAd9-Fi;>V;}j_$ z;hFv7su*$Zq?o2|R6xzkXpGXJ|+Nwq&a%DVd z0E}MvFPyI?r1guoE)psnyqmoJzYXniQiMyrDL7U$TrJeKVq8m6cj{Wp#|1IH;@T8( zT;Smr^rq#ir7PAI+3~JW=e{FpBe95`awR&vdfmO1{C=~Bn8eKlZor{AX_A8qn2zVN z>5>@Qi3E7B-UI3m!e?9TF1Xr&$>dD&H>e+V=)-HmT&<%A;V3YuIs>@J_d+7= zTp$4jv=UM^HSp%D2225`0J39Q?nIZMa&V$rux_z7475#B0D*v(suUkH{N>u+^l@{} zMc-+anEjvA|8O{(>i;4w*w4J%&aVz{dP(#}t1+vvH}2>yJW>!Yf`p1So+R{f zv#vlI9|2eS_j&D!d0aE*CiEV&GQU!6L^*6+dG-bQ@KU-U_Zn&zzg{at0~0aB0kg?w zu%1u-R~%qRHoCwW8$togQjCCbtpQ^hgX@1CmSq)9IcajSZS%FRcGczC?QG}e-b+KN z_;s{`Gv-(q|6h$i79Y(zZ7_AH>538g2**ZowgI=u6Bm@Z22A=tSK>+TjRD@L<$)@+ zgr6GeDP(;g(m?KEQlz%}cR=Bvhfe71vF;saWeBzf49nv)c7K`d;?oy}DgJ5yFF+59q=GqvcNA{X=x|Xu#8=D#&v4(XKe$5l`h7;C=EUT|rZm}f z_Re}}C>!E4Qj%)PaPDgiz#(To2q2+?U{l! zLaHc5@7~`aBz1muT|4JN0f4Y<4=+34J;%JatkrV*u=L@SSEbJR+`6Hg|G8dnHlF)% z{Z(G7vf>bVxDwV$$j%(;W)2h2V3WyhIOh+^v~d*?;G+dtp5X}Qk`dBqM++B0>8ffu z4sz`)8b*6{H^mpUS=j4}HCe{AOK?wdP43F7mMUPi;S!90{W%3-1N+0?n<#huMU+~C zE}agDoS=|7V0EOBbgL)GnoWGuSaK~=%BNwGh$Aqflgw^veUCzvd8W!!Q@W0dzvnzX z)l_=_-uQpj3!P3{v1Nhd(|X`O3axdwP zQV;|qJJb2C9)UmtZ%!3M=-K~x1ToxvFTV-|B>(W=(F$swi(=Fuc@0+VsKDAW2@{eq zc0`w~jd&&|Q;3O4NP?b-K!WxU&uAiZ3XZB<+nQ2KmO6fSp0Qb*>6a@jvC=zdbesOe zTL`J$zzyrTZ<9s(s#QubRVmYk#|cl42(ZBT%Q1%pVgzG9yeTpCLnJUYoT2aE=s9Sx z05K4ePgZuJi~J8_|JRMREhDieDMv8o$qOzt)UxvR(vP{c0u{W==r@rlg@Bly$!rfT zk8V{b#6Mw4G|^qWk|-tR1S`XA_5cINFu)F{!9oEi$as@%2Z9u16!C#K_G?!X z8S9wF{RZ&u9bb}r0C$03p-FO`57^bz)z+wFtnU2}>Bq1@F7-(pI;l2xhM-b;q8{|T zK`?-mNay{AuZ;KWn|m+mzIs*?51RY$SuUvM2} zrQ=~CVKDmbeIWu7)p=A*KuX@9_WU{lKfwT1{a`{6e8b>%vZJ|toV-hLfCVwvE+;%6 ztNg$2e5d1f0Q_~L%K>w27X-%2)Lu?y&1k2Efl$ykT7nq!K6JC*hcRrc$YBSk`0;Ml z++9?TRf+aisB@cM%l7TCK4-e5GFfxOkb>c*Z?lWu2PpprT?j#8to%T5Pm6h+m;(g) zkd6_8x--@|*`%j(|I5? zo5p=vk)oMB~1A*T>`Mc&M;WJmpKl#nDw(3&v6u*Cqs{ z*u(-VMT9^JQl3%S}*2Jq^^syfkw*!$4Q|XEeG^FC<19|;6!?O zNkEzgBrz}Y#JXmrAz;EpF%6jQXqYyXgvhr0B#)rv%5wkXR+Oq}2?Z$Wq!bppWSO|% z|LRELX9!h*ssu+~b237bPZ^?yfT^NoIt69@m`4<(c?mYQi@ zrY@-uTZ_^A*>PC;Hhulg-HOdRV&1lj3AX*KIfky-*?mVk{TYV-%J1Q3^>{zv)x|VM zalePaaI(&nTG?RncdvoM(kaA*n|&R_HrGy>?UaA_<-4DusL@Yz_zvaxBzMl8?Jpf1 zRv`^Cn*Zw($j%9q=o;r!=$id4P?~GheoVz^@$j|S<$mShQrm``cZ{u#F=`&mTXu@L zr$b`duswE;35_Mli%Fi61DN9ZsR6T;0$c+@q}C`#+iygbwjg60W5%)1Oq=wa1`yK8 zxZ~s^@riF&2b&=knAs{I7aq`BoB@9gz!n-5Uvs!yx&%{sksx33b%`V_D^p+R)`SB2 zmbrQrwFtOKLOm3w1_n~)olw5u5W`@=9Y+zywTaxXIfNVKm{GW&s8amXToWAtoV;&{y*>W{4Vo(PNwklY1V4= z6O6&Dhng6LyM+DhH1;`(#T^}lgav{?FG!^jNTmV+qs`NIF>9~0Jxs(DYzPBCL$e@Q zQ~J6o-Lx$IYl7*`D_V~JLR$M@4|uJ)u}}t9w)Q|(aeH3t2A?et6k=Ym+0$0fX?r5o z!C!@773*VIq$oJHg%o09RTKb!YGg?T^oRkQ)xku;VbO<&M`=m|j7Sj@pVG}xBE}8Q zOsBGT8XHNgF&)Gp-QQy6UR_R`3`-kxa^!;Hq+7$a&rMfp8`a;uubQtL_Rk+2)$?vTbN7ou_R+Oi?N_pGzBb4UbK<+*nn3o5PpUv zP{D94MTU`KfEk7hxoK8nsfj~EEe#}0XePk;?F9_@YzuG9VoWo+6-@nOLH~tXqCl{j zQ?Kzh6iD zNFjHw6ce%H`dK^qY`Cnb9=}8J;%{03F4vS~s;|gwZD?)&4p4W=pyAM`y_6AKS>kb> z_7CYOcMi0*5`o|%Ir{|>o_ltDC(-!Om-vkwthi*Ge`{4?jv0K9o&aGBiVVc>Fx;fz zgb&xRxrQ%X$ik?h%LoYLvfe-F$i6aWQ-j$tgGKi%itjj11`Zlf=Ydvq#05!1WtKn&%DqTb-0%CM>ZD07vq|w*q6kacH)M`+W}JBWc}&oTNkA|#L4@p?r5vdRcc3K% zfJB1w{vT5nTMt9#=Q~(%E(+UYxn2ZDOwHdYV)Wt-O|4B?MxuNOXqXI492lEj;#vJp zZpRD1aG9Q3?(D_4UXhyr*%FkOHS4e{$9^_m0Q_gBNgw|(!Qlb~QAcV$dmbm+gi@tW z7T-thu|Cqh>2JS9`SrJ2QE1mD!Ul&?t;2``im>4}A9k8c4NK>k_{$uwclfC8c7=WTa^`MFLz zamEn#@9RBls0ZK@EF`4Bgx~4IXBQ?etoqI#@9I3#Pflt;IAqd`c)WLjkjb-QlYnxj zT9ZNm_@Az5sE}I@MxN84-`Nh919|yp{K^shX@g+!`tNBVB*5ev@7Yx2t@@NAghYpk zj2_@C_PNKvOQ1Gs%)XwrBEf2s3Otk4P+Q9=A6095{3!$%?|V3)z}l!aXv8IN<^c(t~+|<3pk@N$ml&@RFKcKPT=y7JqLEH22)B z{|U(KNDrt=eEm6OBSdSI8V`#oFkCQYy}5 zI?S7AQrAc5cD#1?2{Wy+PK1^BeH_E}?Ddd{qO0cFv93{VD$*h}qtCvY;y#yai`MUE zc%2&=^v|s0Y;0p9(9zvtW0wT*aht@pQwMp7@hoanLt4t@34*&7K$c#dZkhp9tuK~knoNkK`p!kfll!!2J6!^Z->33 z(Y2)=-)Ano%=`4W@e&>GSKVxKc|3{Ti_vlMNaKKWs_} z!Z(AQ%(egX9Ui=!tMQMxVnLiz^hpuSsNbq3){2U_=Q;qtNS4->0H|9>6$IHuf_T1j z=ed7F+MDG4Pq*KA237lqn0E%xr0*BK6O7BRoN?6$(h5U!0^n-FiB5B`K9e!oProrU)aOnrkxQ4ELAAF0l|Dt zd?8H3|2+ZW5gA@vR7||K^pc9TJeMr?0<$EXY z?<47vL(r5zNXHvml>Ge-p5NyReuI8U%HqVqC;gT_c^DBhijSk--y5sh`H(jJ!Q4L6 zq)z|Jd-;kEwUWov-LdE0!L&QOIE89a{OOS@D$r3z_ezXH+eqk|K8Nu2I>~|RSzVy& z9@T~K&8mXqeID%Bv@IOn>bs4sCce*64S65!#ryiRA&Ba%AaF8;006Uy5QHNZAqS+= zP{bj$0`+YO?ycL{%h>4Rnp#zw5QfB-g#(6!dF=v04G2%Lfg~V?fv^$=&@qV+zz}H4 zXX1Pu*3K!~UvIU}vf=^NCw}tZskc52UfwmVnzgaM91f8GrfgcQ0W=eY z*|$O2!<`D|9;EbIF%v`@=dS$>ukrlXVbrA%m-OAWO)Au>vtl3Z3biE~oaHj%mfU^2 z2le{p%$o+@6*p2_saNT|4!S=T&e2!@n+Qz4sr>Rp*#rX5R~aw3N8T6)CpMuLNI;Vy zoMI50Zk)k*$GUsL7(g;(L|S0vLag;5a6MMu`1>Ulh{tY&T*C70(0=%uHS7Iy-QoDd z4)G~4Sn+BAlMry3qc@ux^B?Z8-E$5c?r*NO{i>?VR<$wS?xO8UsnWd31UXThW>?{W zXXPwOV>A8zs%*x8khr00D^1UqpV?>D0KGphon9^c*Y$DDHv3|!A5ZMZ6fV~9`rqy* zSy}5Xnw^cJ`O*l@>eM>_`H{Q1wMPpdF8`)XAvKlRy?OW|<-HUl-cx9=Dr^%)^yh&i zsf7bUAE;cYdUU9ZS3y&Y#_O_RkQ^Zbt-pXLbt#hi^K%w0TGjd+z^mraou5B|$_X>xSopz$ zgEsA*0(sY3+L0&dNPUC><|{(HMZ=&vM_njmj8VvEwiZaov(qLSBLvAx_C4=RSpgC* z)6sj`86=WPBtry(W-aS`*7iIwHUw^SoaY80G@916tq*Aau2@n$RpTtnzujzgeNM2< zt>(o%|BB7d`_56E=UKcscXNd5_zdw1_lZY$FcYA-SZ7Gbq1}Fm3)`$b{1^Ah9KirY zg?`J?sj3RFPzw7r?5?k~M@vFMn5*fa_!Y_%-Nldk;sICAd)^F?2lH61XYbY45QDVC zpX_EA*D}s1@RzoB`_IW!daAQ`#7O)7v!0WEbUMHf_Z(T42qKIvsMgg=kYDFQjCrUO z^biY3#la&pA8WTf{6egNM74({JKU#|QaIou#sZhK2U5y>+VV-Lo~^J28a zWkT49iqeUC$#lYVs6Tk|-~adO5b9`Tlza$K4cHw`2hTgUp6>yV|Az zr{EvYXme8Mve@tg%$9hupZvJRtuIRaPQg5%o0!9?jd}|g_jecSWTy9=|J<21IJhcP z?@M@sRAGeE*0XhqnTr`}g~NNNm6_Ffdk%E_Z{T-o!;g8Q*T`ZTv{0`0O$=%qGI&f- z&n~n4V)bV$sidG=1u%(hr;32ht92V*L)U(ta87*)W$x=s1i2$v*XcbnXy$08^;s>u zB5yuMLvXmzJ|3G2h(<>5`S&M5z=uomm3|&~mh31Fx?n?v>7in&W)cL#N$R68sV7`~ z!?DCI`Q<_fk*XUO3#-$tp^ri~!JE$k`qS1-d}kl(quI85E4frUh~0N3t##c>I<5(O zdBHlxVS)uxPNDfE)#YaN}R7C+fmTKn}>3#WE?SQ;bY- zKRrW+{1~7E!yb!MdCFy`L;YKs%*-vSyhF3q}>S9dTB4{r6In3 zGTN!U#rZk@l>u(9Bb|OZ%h^sDa=ppee>E zh@-GlF5;Zha-DgV7YPIeNFpHB2WW|tHgZu)yeW}}{nk`ul1}cCDTdE3<_WqA(&_Cf z9iF_Fx#ebQl^)29La%*9(P>7!Vr|8~Nuc$j1D2NsN?8ssy5^`7?@$xxGvK<}h}5T3 z&2Cq`UFepwwpO@njy8(}!Wsv6nDC*Hf(tyVPlQ7p;Nv>~Ax(QEBXLkhFja^*wcpn&H(zj+dhz+M#Gg#Q zaR1saF!0HnlFf?dfz4WptD&D-mT!CPl~IU1cvrZZDz>tVSV`BOtp4`TXE|IuwHAXs zpco%pPMAgY_tRd2uf9FA+^G2eUvhd??(VF1fcV}sT)cQj)dbm42gV_2+5Z=%oAk1s zU1HgqeRz1~n#_kcWsFp2ZMG{Zp2)LH#!hUrekLx=)2{!Vlvy5&p8N_d72rTonZ$It zXZ&=4TQN3k{TXs{+Y;UWU|)^;o5R<&oLlL|&L-f;i}T!)q*)G1i~@jVieCWQs8gYc z#|pgC*}D*|Y_anJEuYew^&m2Bzl5Wj?Bjou%F}A*2%4e7)EcG%!5k;L-_uYD&7Xpa zlt>T+w4!|AxB!qh7lvCeL2&9!07B?0i-@A1(zayiM}f^;<$u+1E$FD28?2201Rbb3 zc@a0qfTqB@gMa{3A}IW(KGIyhdq6$q#7HZ-`FYTth)Z$iO0-NMOyyo8aUU977mq$c z2oOUM)FcAOy;3fJ0kMe)8LJL1l2ua;e4avxe7(Zf^c0~wrjp{eTJ){}ua+CyuG7ftI z0QpT+w*z`f_J7!EI9-eM{w%EVjm>f`v$8z@8v9cPkJG${R?|koU)s#*ZJR zwsAd?G3aQXALUAh$&rEQf#zsH@z8;o)k0rEpzQ-9y?kmAD6T-dBbUCCUAR*MFWzRy zOZhmet`~07ElOaC`jCnI>_tQC=W)gJ5@`iGS=sL8#852d{OTr^*L88j+MZ)iP!=eK z*0qxp8n$CH(UCo};>32NWu+V8w`cJd+1|^a6{S>4niT2yi*I0JjVD-(;8daN_ z{2RrM9+Ff!T5Rq&`6Uc@SN`{19huWTYOBUuzUFxp_mu`u!8S};TsLcMm#sS$%wVcY z>+D-3$AOwnPP++$3Ac+{nP=L*e9G|En+Nw~=2rY^sZhsyyF0H3FAs}Nd&eMbP7L)` zcVKZ1ac?=Wut4+-XNuV?4vd~f?duQejQ#1R1KYd+0r`Y__FztgtQHO`I8ztw9j258 z3Tn5WCWzy#ag?zaO_T$at12nE1onl z@x}zikQK7V1jZiI_-tCBjR;Gh#&h$^#suzR@f-<7{f!6+TfsWAnylQ-OpMzs(`W@q z-i4|Y;n}-|)wnT9Z8(zBA$DFJS{E{K-8{U#`R}Q2HiV+CXNnd*YXRSGQ1||Bh3y{) z9IdRVhVKvfx!-I1Pb|dfkoHVqi6&!@XATN;$1c1A04wDGuklXy&U-kteE}8LQd%=6 z&p#r~h8{{ir?y9i5DtjvLQH{PJ`=Q|YJ!OJeHBj}lcamI>8F{wbE%C)%L}FBs!3=Q zld%%y!O+Pvj_iRnD*Bb}6cetgJ%a0{>CEaMpBiLuDZxs_b@_ZT<(iIvp0lDXfnt9F zPgbw^XO+ta)c51DP(U5fnn_JxxFN(_=AcRoGL;Wo239hjmpzcSn?o-3erM zC2)yYM7@;z)U_eggr-XBchxknQeBAQvHz*-Ob(g_Ip1W8OW;yxYSpa>{+#Mis7Mh z{5=vIZJy=w81s?S^xoUUAE(5otQa9O?ORwD8FB77Af)IHGElKf4-$pdc$Fp!ryGTn9SgH_M+gqljKvUzeN6rjy-~Nf3lL78Lxj!d(}= zv2p}+kG3;OM1h96UhVRltv<>NQu3xDaXzx@`O?g>%Gjixeh&6p!9G{W@}mdIU6{u` zEQQP}44zQ<`D$(m?aq3Y&}e3peLRV7BTMoflC_&!lfm5!w%o3O$3+X0GXb4E{(JBy zN>Fuo8C9%H0)zT=i};$ohWHaZc0q(EEu_jXEYcf;q;n-}Bw3)n&R+g1A(K%r#PswM zi4;#YoNp*8*v1{Cxdvt#6sNnfsuf38W%^k7gpG~a%s@;)L&zMp7^!^r z?|H9^?5z*x>`If?8t!7X2@fIHc`hKaNCuB4Xz_#w-9{_u(<}MTx?tpTs4i%6?u&E< z!l_5)3lFo^v<)^Lj^>BhxPX;Il_3l35&Crm@zKIOH$IXz^Dp~%hA(e7F~xp&pT;Hn zF!87k2lT_>YKnmnDm43YPntF{j;H=Y@@2~xBf_5|-62Tcg_xNJK6jFM#30%m-7RF} zp^Y0Vlblh?tzjafsB1VKlUgHK$Ec-U8O>V-~b>md?_x%7#tq7 z)(LLu*58uO>({d}s*M2YU7vJt7Hmg3&t^U~#o5zkVlPnFoW{_z!)c~Ang8tny0LR+ z$F0v|{)^7n*fT%ucl3Zg#HN9m%pfAt0k>-DJzeJypIOKG&lMx^H(fmS{5+^spQ+tV z*kqht8n2S!`;R2a<8`-xw@k^eA2q`6FZi;BgC6;6OIvH3GIePNmJoUE#nYQ_}7(93y$K>w|3Ko^QLAc*?nO?I`E_{E0$ z5Qt=g(Oi6)sO`z~4O!0yzwx_*`w)@$9}hN@zp-kMtnh-lwR>xhgh z3qNw2-yZpf#7Xb&Kn}}=6kgK^#EuXE9~f_+{muQ)HHzyEzlO>{4Fb|H!iZ%!wbMY73lZi+MzEzyxQ~iMXqm=`V9DEG_IKsDK^zNq{l2SK~_we}{aO7d|?jf(KB9k)b zInVI!C{8`|cGtucj=0L;hV~>WA(9uG1KPz5ck|@~ zW;&U`_yGVvs%}77BZ$D;H_HUiMJVP>-5Y_Omy5jhYWfHG`3E3!j=%Yz_A}ODgl?qd zs~AbL%mBmudH%MCkyC$0eY=H~#DbzzIo5ta5RmwRMMkREUp!4wP1?Tzwcqr zT}>tVc01MmtC8^8ls$A)bOdkw+_xU<1E1@1i&f=dB6b@Bu9N1fPrxdRp z=O#2J`lEw1>~OZOT&=x{oWZtz<`S*gN2wJbJA$&Pc;5$4I@f+emN;orjh7XPuDxz_ z3%KIwi`lMl+0kRYMhdUNw1EEu@IW!B$R>~uu=V3$Dj7)bJtUW(5I{r~-w6XIm))IM z-XHY+=&>K4UK$j(;OS0czb6#l=c@XB1qI#Y*JZHbdJa8L9!V{%arYnx-&(b97G?9ys`bPxZA z!Yt?YcRi*0TUMR%!Jc z>=cTiC$3F{Vuq$G&sl%pv%;ahToM7H@?ynA%*T%ICw4nByG9Ik*>%eYq#ouSP7VmU zv3Ho^%{<(5spfA!hk3sLIr7f^pX9RsS;WG19Xt>Ki2RZJ(cz{4d0Ph zp0{VBbN}Ph=9|Q6^qRI5!NJ0_gqA~9)1T*PQpKdTn&{(+m${*<2(*1$!s5?VkFio2 zSTYD1(LCGbe5CbY{m9WC#z}gTqMXUD_mZR7xnz9eQaHza(ML*H**C-gp5#2Jh1f1j z3IIn<;;2D0NPWu(sG7v+-^?c{|vUSZ{8@dr?;m5aW}|Dg?(g=ds-hakX6NBd_pd_5kV$NR z!>f$X(cz(*tVeV8j8-&OJbwCE(*8RuX@g3677Zd0+BYQ^ZoUciL)|M{ z8ZGER-He`sS;HL&4RvMo3&c%&X@LBUR&yn}BBVAcBcCYghSx z%WLoZ2~E~w^9{Jw!>6*fd+|`NyRRbf^?#)Zm9=MG1N>b}p5 z#wlNCzgYmi*ym(5nvFYsBpAHTCem9oB8`U^n%iyqdshd-g$(DKvUQ)om73u_?P(3@ z_h}Xd8WU$JCs#v5NC$scMysN8CVV&AybHz6W0g!f`Kp4DvJ9z}-u}-aKQ&(q9yrzZ zbZ21)bI-X95`3JX`YGsh>-@I(k)16uKe<{joaS-SzP!K)HlR_iTV;A6B@v9`zzV^jS>Y48gwE=Ldn z@_eKMSLWUS!-xa`k`SfI+;&MmyKN)RdV0p}?N=RcGPqFfxqYtW_`l`D<$ib#pX^(& zJQbKefcC6M-cZArZOiMPmbMf=Kcl1{XGB(e0H@$jD*Z}G&H7W+-2E9z+;z8}=EN{! zVjBj~Bw@}3BlML7y2!y-?G+;rvtttSONjxXWllSU^ey&16{Z8(+D#Q?GueN2bLo7XzK5i^GNp#TNqg)2i43-(Rz zeh;y0NQ#Tfm+!5GyST&&eohE`mDle9m*TcXdC$ne-9I;CTD1}lhp3>f!(PRK2SIXx5$)nMmaiSQcrPW=%>8e@{0StJ@EL59NisQ& ze7<%a-;p_98oZQWCvxFFB*K;vSy}m?)tq?Udr%|1JQ&1FD>2zAVJgE)oetH+dh0O5 zdBD5P;%71EM3mD@XB8N(}){?A_PF0kIS!cAs5EZG2!49vi1wno-8 zgJXIjuW6A`8fw4yO+b>ZiP$(nJtm+j{;A{DCyg%4<5f z#z-vm)gpfJCOdu)W~CKWZno?LCzMP!zfs@eF$Ab509% z6L;P?Z{u9yzIeg()3v-%e?Vb~;c!y8L59*Y;p;TIm6&ftlY80}!tRnRTwL3G)}<_|A*;lYWJFQr zrekTHmsXe4V=oOlmf84)O(aw@v%jg|y2Bt-i&!`4>%OOw0DbkVw`p=}$i|rfO^hFD z(=D^vn1@mhK#yc;3;V`2l(qVBcH^eau`% z_@yhylLhNRJyC9NkcT%i>b&%CFacT^1!g!8&!Gr30w16mp#+Ump&sVmzL{jQTGHxp zrHgB8IIB9Wds?4*&)ap<5+SjFg0om!B3#s`B~Hft$&i0brb+(6n^}*U_((wY7#&yz z!;M18M>Q&OyB!1mRhcXIC2X>F=uxq#^x*)dq%3;!KF3x4qgEyVvlgzHa;~#Q#4>3a z;j>yfXq)_RiUhvsR6VMHanjKHX_m2QJvLzAdkcL1gg;s8-RKLMIY1yM$YHp6<(M-q zk|@AnM-K*Y=%WxNazRuX0CX!bAOZ}0UE}k7y<>I^w3X)>iwlZ0R$B#K!U1QP`EWF1 zZq0^h`=X1T4h_TzKWob3azj@fwF8 z`wB*)3s$1n0r{`Dx&psN724Zzv3a7amUy};Y(iZU>|%>ig&_)?pa44?J6^ZQx)2XO zMuLNYC$s_1%grjGNe0fPTmui0rP8Ed6VZfa!S#Lb;qfkRg&=9biNJ?+?yZ!qpwED_y0 zlYeWe={jBw{XA`2HDfJv6`T_g7E9u}BM@KXiR-dR0VGo=AA-V5bXB)Ru!N;wj7qz> zpNFzCn27b|SlP+3Z#4+_!Vp zoQ65{biC(Hv7r^7Llf{Ko>WcCFCPZaBJzwb^3FB+hCMOr4>aLcRK*u1$aM|{ZU9)} z1+}bIEDINsY?6VXM1yne@LJ}@+7&1-rqlP>J{!M#vGm<1#yI-brCnKSZW}XvQweeS z`Z$dIo2;v|=k(}(#9kH^l%qDeyh7~;kh6M-Evy~p=GQ=r12uJTXI8@Is`WHO~rrAlJz!0MBsIPB_{62Q&qLLTgmD)6E%UV z-khZ)5}#bd=>5^EYI<5Ei&lL+_T6LmRcpi8OIUSL>-Dq(c>L(?Vd1W+l{B9Mp<08C|X!o3KWJ6 zM`N%iy3J33yRqRrSm!KXS5@NNQA!o@ zZu$_A1pZcvsQ0dqNz8s4K2_AqAQFTT5dc8SN@l5k(|%zRK&dTr_A$aDU;Nc`zcv-+ zm6t!m^1_wLH_qmBZrmYz@BNqI49w*||5X8chr_gvhrM_GbC~>+ekn$x6xBWXPvUA@ zdWdO3N_FVRr3el7kOFJM9Y>vv7v9@TWQOP<4uWpSOnN_11fZc&4O%yJhnB;>dBb6C zBH-D{-M$wO^WPe(t496?D~_Dl9?3VQ`!`i*_s-=C3$okxsgv4grXDuGHXGc-bYm|O z5$Yx)4rG=we(z#f3EHV?1C>2K-%fDsfMpdsT@*+Qs}in)nxBzP4jPvgp^}IYu65s^ zr6JQlAXJ%^C_>dQC_LX0HvxkIG@~a$ftG|^*6mk~44;B#Zc$2?g+_CWTU{AA?F+HILe%&sB`UjGURZ_ti1DGJ7xEjYo)l(?lFFp<8zH`?tW*iAxh8Ot5^Kn^0 z3v0t(^n{xrMy<7!d-eJRK^5_v>f=iy4x%#^l#nO^;sYF2n9w-_lzau-QDM7-l02-Q z9b(<@d$)*dybu5aAs+4^B8?I#)>or-wr`CB>^(|SUqJgk;ryaN+K{GCSNZ8oMI;Q| znHD(@daI5YSS08F9XLNuZwd4q~Q>8U)><#Lvtvhb4N7g zW^BA!SLgX0MG4l3>SkR9)n(}Eo0Vfyq}M(Uc6A*+969Di`q9dr`@HP89QUT3uioU) zGc~;I+}+(3EuAiivqTvp7jE2soH47zG6aR==Si7m$AVsQuqln`c{G~!>z1a$^YkK2 z-S&i<7~kvW^f6NJ&v`;7z0Qv!Szg`AWir84`hG+g8>@Y)I+Gs^q8iIQD zVM(hTjT1B7&t2(T4c$_`d_rMzlO~C-W~&U4%GZnwJTXbiLNdA^(H)c+0V6Q5FwQWO z&@{-NX$@nHnnlh`md|V8h}Drb1uznf6q!C(0bR+i&97>&5!W+LIDbeVP%IE0j4E%a zG`M}PdzzuTU2bj|{fMnTreWdoX!3i+B^&x7#@rY6+pBs<%+jMcKkW+r4Ocr3VJs*S zcybr}YyUqDnaQL<$bTPUx!~Dqko>vmNgU$?sNzo+Uu*twE_YGiruEED!M(P#%fa$% z&gNgQf6%)I*OY7c3dH3O#N!xGzU$K}mmHow(1ZXc&pVjyZgRc6`wLiFo3E{RIz6|= zk-j)VJ>=&pMq`%vpMOcLu;H!? z1ZtQA?HAeg?W%``8V{r)kzFu(1&~ zp(Y2$K$qX6^FcpD$bO|?%jM{bgUGjgS|3kC>N9xbEChE30kCPBTOZB*riS47mTx7Y zt)C==BE>~J9^z4zNxGFRGupr(9OqB%`c6v7%gED{mRy5=Xd(nPMWU8ecN#*;o(k&vvL71Gq2(;Bi zbA=4pejoG31Qx6(`OAbksqf&lNM=X^*$x`JfG?y@j2)6j{)HxuzsW=UL-D@<@{1q7 zK0&e^oCOZ~$8CI1r~9sf2BE@B`fS6j|MUy>zM;SfUb}{Dl&A27=i&f~C23*yMk3^) z@wL4UU!MB%WZiffKD|GG?A6z|;W=&&a$M&q?*>XZEIephP5qgSjI7oVt-bN zM`51&QE+Dm(eubIc{~ z{`$1}^bW!=2?SrK*S$uHv|BXMF{Zz(ucVkUvfS*|2y&93zE=j` z;Hvn*Jkn^Iyb{5|Y+WcU{Z-{zf^wP5U&7Ti+@R{! z<&uUx<>@B6PZp<{a@6l9PLDC)O*D>gaGg5WVlxqJJt+wzUtx^vQ0G~x(x@2(`Z|16 z!gc7^N*}PWXe;;^QOW2w%xrF4mtVB1TQq41q==A4W&#`Ko<*i!e(GojhO}J{xBhEp zbXp(Pj$e0IoivmLh|_^Psj zM+B#6E>M=NFj|RE*2au-Wz;7G7g9{huA&Td)W2<_6<4ki0uBzA1W8R2L4TZN(h?Cl zW|1B}V&PTMq!3n*6$7KWKvpsat7KvEChc0JBKzG-CGwKVfs$Yc1o=ZG_;lW_eiTSk z=#%#h_PEHNFd7n`LvcwOV(x;WAVgzLIB^eHZ1~&$f>ZHwZu`|H8DtWT4uf8xoap+$ zYlHz1A?5)g5WMQ2I^_k?GO*=#DlwZdjcr}OSovv2r@tcdKgb1tNgaCoP#S{Yld&iibF9EA~g_oPgU+urf z={x(sRreFfhWp;waQZum8@rMc>&zn%en8MLhDVS(!+SfW3?aqaC=QRvpezQqHpJD5 zFo!QlZewpT)4CpF?b{x6q0G{K)(!aorp`hE5<1GKtK!$a;Qi!=3<0lT`^i6wNLB{1 zUtO$s;!Wucz0$zko z{Jz@r{q1jGZuY;KyP-_9PiuR%tAfG_sX8qAebB=6v$}z_iN)WOe~6^sGp?01*GEiA zGmbUPEbkIhDy^QE@~$$8A@i^`AoGeD+s!%VK)lX(I41X}bWIU~6;Sbj)S43NT+nwR zn~A;Q%}A9b>85g~li}!11~jhNX!U2>do`rU%x|0BJN>JxvgmWhrg)&8 zUBJLGr3S{8T6Dbf69Voj=adBxcR}E=hC2;QN`#GJBWg?<**1rpgd*QR$O;h&emn}_ zGUF1q#k!R$&lVXMyU_q0j?YZ!&mlfGT^b!i5}NvWN?#QtO46b!^j_Pp)CNXM_i%&! zPhi@r9<_+7h`-k}=`nH<`6=0@n2~<1@HP=tMQQS!2hQs_S`8XLx^DaEbKX-wanF9P zKJ4}4O7g?}VDU*tgu@m9E75_qGF3$0e}0=qa~Nf-Qal%PN)UF7m08J`BO7!+w2v(w zA^f4-@f9GRRJ#ayE>imj4QCsU#UDFU+{HgFyWA6%TNUEn9BKT;v;NC5UE-{>Y!;ee9J^AoG zDa!`;1Hh7iXn#?zuX*99JB)uSpeFNBp)f-b&JCeK?)+HUe_YKdQwfS3g^2U(!CbQI zb>97jn`19r)9|L_J(mh9l>XN5k%rm$z}517?dm&XQY?R%;q?3ie6m4Ro zRD|X4HeR5OxdvW)YZlb>qZ9jNqsHjxn}FLX>WkZjUUdt+L)rYVG}YX|Pn&fkqVdXWd1qyhFTSQaZZs3kFAjL*^1JJGq^xW!t;+2Vl z62)q(2d5GMsOSUh$3f0Zz(SwYwHxK_%*pP$oBySLuo_zp&ljDsLZzezAN7JmXTaj1 z;8_zR0L$7E3=vt+YjjrS>@5@!;dNLpr{3gmpN4ktBjO>yPieh25(Wt~9Ett>iEXW) zSbNib$?}Zy_VvY!ik@2_*4)|Bss6_+L0>(;RDiMe&in?kc&*GA{5JcC?o_$8JOHI& zGXx;Hd#kT-CXY<>R#HCC8+>0-dF2;UIda&KBYCi}$U!ru)ycr>h0Bv12bX-B`!?(A za&zfMri_U}74jOBc;pA%$(6LWJ&$s}2alHGhI{V`=gmANB%VW}t0os=XL>+r5`0FY ze>tA;gSl)SMJoy^eWyCLAa%BV4sAeb7Y(pU=^jLwH<-}7=T`;S(-_w-NP!d}?q#V{ z(8LfXyL^z+8L;Wexeb(i;>biq0Rkc~Z_k=hu_o5BqFa-uzBa#slJqQ`PAEPyM_^qq z)>up`&q(=l(URiE1dduoJd4hoBero;ALWlRVki_ecS+q7=sm)A$>?J>6$3iD{#xL% zyL;oQPEF`s>=ZUHGVL^uBV0z;Gj2#Va~d`;oP;fRl-_u9$Fs-wFVmLdUECd4c|KN) ztRfbs&k0bECviYmfidPIg9C@dnBI1gFLmYg^ig@bEzwM9E!hcgHEOo~3s7J)f*@hA zCVTP0-wbCYp>HB16j>ER1gEsL`7qOMg83rI6b?$2?0mRY%S~~;0k&rb+QywAm_u_A zmv$3DggHq4(X&D_-@+AfDYM-_?c`35e|rbf?N1P4s8JXLgv;>qtPj{7q;_OA{0&BZ z?tL$pB?*MU`GcfC@ge&@gfa>z*ugCMWhdEYi4*f+Lz*-m_(qt{>p_MzE zN3FMvkvf=^L=XuTM7gW7HkwQd^U5)^nmmG0QM9#4NH;!_HFaR$14x7{+cpMvz{`#V zMc7Vq4j5}l@qJ$_lO@unxo}vJ(z54iuFh?je1p7<9q`sET^Wx@ME{mpfw7NgJ=MC-uiBQXdliEWQA#8ONr~`i6u6IbclMK zn5yY$_z?~lGsP;%^od9iPt0TRywRX`k8}~35Cb`MHC{cA=Oval^Uf|C7u7@tN z)!nPLE%MN<^0#E7EPvRMm#;Yvi+>d6LljI~cwKyk-)u0%j5KQ|ENYd!S zQ-tnPr1`Ezs?J=t-wybC_0Czc;+s7irv)U!XEQFEPEJx*txH*OvB9`j4x{7W#<&+K zaczvLqV48x7RN5hI2_;!@EyveSXXH@PlU#g6L4LtmlSA5_ZgMQAkWVxR(y$TEXBr0 zPaw#z*=azI6?gYRZR6v-ED5Y8x@_)$Y^FLg=2EuWt=lT&a@v^gGK#V8pQtNr3!Ewo zEIBgo^Dbfv5|NXRR&fR-&Ag3NOFseV`5G8=05^v9hB-Vp8#in#Y(V&7GcM80iF@2eB%qd2qpW|99v zd-aIz{UORZqT0a`70`>d;tYQ9r?5ChnTlMoKo3NujEcA>uQLS{)Op0PVOn?Qr?}3p z8dj@6EeRW@SsPQtnV^yFBv?o)fg*B=EWgAS^}ozXg!WO=Waz_~*CdRl3rc>8e|PqO zOpv-?ZT3*4k9KXX(ooYum*+`_QuLni9Jg}Ri^j5093Rnh@>z=lyGyYz=lYqwderkp zg*iB1EO)?2;yyb07{`Hrw8mna0ud$vH_X9O1_$sUBLDNAN-`S)M!(2pR>Y%-CJTxV zd=(#rfCd`(H1vf-i|6px73yoKh4@uL0k*AHOFqBq!a3&Y=o)e0<1H+Tve1ygyt7XA*cl0a&n^?VRlYkoI-pD&V76Q@i|PSZXO_uW1SSW< z-tmtAst2laD0_q1;I~ID&3bfja$3K?ZLF$ioOp+ft*85|Rm!)Rqdrdvh&k&OYF&5g zNtukBM8+7&bj-pfG$(_lOK71HyYjSS_D3#a!R@F!PZfet#CX%aLT#8jvuK zB#;w(cyyZ+`v(3m0B@N!WAY&o8_*U?g{S7^P&Ir#lil5*gVIMmM6z^SzU8v2n;=O2 z4@wbww`S}#{?OkPD5)9IESSgw^q|&73+FX3TtE9^eN$&fH+&k=cF`CIOb(=lOe0bn zef~9)k}J2R{f&`&(|yA9hA6}6ruRgl2JQ;^ zx>N=xqgq!zg2Ep@Pnh}}^m`;Q^pXqa`2JeM3i;1(0X_(6${=S!})HA)s+D?a-`C|N0*>f zA@m%!(EgAD4j&gAaDoE(i&iMz00yyaD0Ev-QL6?!*JFu|-g5otpY}WdyT+b6cFl^Q ziMz96ZsNo`=!Vm1dl*oC3^{_Vc>^e6fFZjB8gm^7k6-q=poL__FP* z%ycp=JtmgH2h-eMNmcC3Wsdeoy_|M<{!DSv3zNK4(`l`1ELt9pD+?f>6nkqp6Y`+b zEnXH`G4b8$d59*qK^JvC)l!o1JYpUdnAou`hcG3Z5(!$|s;zr?3NS+Wm6NJo2DTg; z5w|3p5#@?v5|g-QV6PsG8IHSd--dxmNQnt|yab9|c?f;J-$&Wc3by}uR~oghY0M~n z7aw~;w2+{#fqSn`(P{KFNUbN-mVP5Q3)+i2HPlc;1-qN{Pri7!Xyp1#X=pSxCFKso zkH_`a+xus1r*@R>HdE5<@7>4;2sDuX4hgROgc%U}Rc49g*{AKO|How!v{3MgP*f?N=>Tel7+1gY(Ym2+o?Wdg}iPg?OqqH-w=j3Gj$HJN!Y>VMrkG`q;|PK^oNLI^`j&g zvXx*~w?JZkl+ZPF&t7Aqp}BQi-D;~<;_Y`cTvFgiF%I8&l>b2vi#4Hjl(^Saxiy^0l&^3l}7!F#Vh5JvXHVci{ON>3gm` zRkIXd>b4aap5pdBXvrVABiAD5#AJ+v8(6O9rwf4<6R9)hHr+5cWz!IxxMU2TNFp<4 zJBeI|dMeyc0I?8-;{e=J;mWL~o=07IqYmiAgdL2)T1^B+kYDFr&T$K3X3Y@F@JvDZ1gsz_#zB2k)cK@wsu*_*b`n)rsG>AHQ%|{weNFa zh&pl1$P`hc6}qe1VJs5b@Yji+WKV(Mkldh}yk?AMagzZw>@8_l0#~+^>GvJS*Ek{U zgWFC*5pfY-Uv0xXQXRpR^EBgaFBQf&CTOY2(-xf?Ht|`Z%J%*jPlE?4G&^qcYRYhm z1Qr&nkJ5-72^C%+E^usoYSeCfB?4^8g(OFwyP7JVL9c?n9`>v+DRpK+;TlIv16n}0 z5d;jSgJ|(94epAr{5F6(q;)p-7n`k35;R)hTu0gt2v8~&5-Ko0U&k|4B&c1m&%h$C`5iGhvQ1qIqhT9sEwnAPBiXhf<87$_gt`V|5unA#yP-bGQCYlY%M&~LUOoE`TvMg*x}lCdS(S#{^BzsBliYwyv(Y-^8CxaTZL%4 zW^0{`fz97p!OWs%F8?bNiJfmcO zPAWcmc#@7;_q6|>MttG=uagi!9loOOolKv&T)df);FkH4kn!DGI%mV(mPxdc)6k;V zD(6lL*dj?HHEzV^W$5XP=!PF#B?_)4%dLaaT+4~MF1GOvc$J55+EL}}U2x6q>0Tqh zpG%9s>0^Y#UL4;CnW1R*!z$2hKU@9d@p)vakZKL z(tp)Uoxif~@0-M!ebe06TKskF^78RAE~~a_^ORYmCndibnZ~5&Y^xRLD5PU-V5Z3q z-&3#K$AvyVGh~Qok;GTaS zn-!4oG41CgViufxr@BFm^T8-(fnXHU^2L7;J~{b`KwW*u%FoBwsVUTo45y*%ryc7m_@QjHIC2fxdkxbA$T5dM%<>P&J#zBW`lQ)wJyZd?I!&bx; zc(NN3u-i}ln6-r2LfR)1hxvSIV0X!qu);0bug}-S1TwG8==8@g!CHpC2aEnB7TR8T9!D^V@pc zh#{tXJrE=i5QG*YB0%>=c^pO8K2?s!faRv#Bq#1299VwB@ z6(GR=rM%#RxY1xrGmZL6HevC7tUrq=n=n*&Y5()aNC1lpXWMvc_zAv-Kohs<@}?EpiCGoXRPq)uT`wEOb(u-H;SG`;^G9|1xt6T4^J)|j>2QBm;oT>mGWFb^Bj<_{P{Ylo|D6($SLq{j z&aU$S%4|W4SOZ;(uuoUckYtp~LE@6*$dCFct9VH0xE`OFpai0S+D|(;o4I{li24py znVHcbYaKIn033w^3?aw2!$}k4M}AJ05Uzuqp|rSmbD)TUd!s>uS9)9oqo5^@HP_$f z-a1P3vqB^7k&zΞ6(Vi@v5wkc(kV>eaZ@~v&gKN1L3 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

    =XNbj#(UC_J7mz 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