diff --git a/BUILDING.md b/BUILDING.md
index 14206976e48a12..b63901297b1a40 100644
--- a/BUILDING.md
+++ b/BUILDING.md
@@ -69,14 +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
- infrastructure concerns.
+ coverage. Test failures on tier 2 platforms will block releases.
+ Infrastructure issues may delay the release of binaries for these platforms.
* **Experimental**: May not compile or test suite may not pass. The core team
does not create releases for these platforms. Test failures on experimental
platforms do not block releases. Contributions to improve support for these
@@ -87,12 +84,10 @@ will be updated to reflect those changes.
### Platform list
-Compiling and running Node.js is supported for a limited set of operating
-systems, architectures and libc versions. The table below lists the
-combinations that the core team has committed to supporting and the nature of
-that support as per the support tiers above. A list of
-[supported compile toolchains](#supported-toolchains) is also supplied for
-tier 1 platforms.
+Node.js compilation/execution support depends on operating system, architecture,
+and libc version. The table below lists the support tier for each supported
+combination. A list of [supported compile toolchains](#supported-toolchains) is
+also supplied for tier 1 platforms.
**For production applications, run Node.js on supported platforms only.**
@@ -227,18 +222,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 +235,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 +251,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
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 39c3d092a4ba98..166336dcb8e7b2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,7 +30,8 @@ release.
-13.3.0
+13.4.0
+13.3.0
13.2.0
13.1.0
13.0.1
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/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/_cli.js b/benchmark/_cli.js
index 8b9f22d0fb4b57..771cc72bff1964 100644
--- a/benchmark/_cli.js
+++ b/benchmark/_cli.js
@@ -34,7 +34,7 @@ function CLI(usage, settings) {
if (arg === '--') {
// Only items can follow --
mode = 'item';
- } else if (['both', 'option'].includes(mode) && arg[0] === '-') {
+ } else if ('both' === mode && arg[0] === '-') {
// Optional arguments declaration
if (arg[1] === '-') {
@@ -82,13 +82,12 @@ CLI.prototype.abort = function(msg) {
CLI.prototype.benchmarks = function() {
const paths = [];
- const filter = this.optional.filter || false;
for (const category of this.items) {
if (benchmarks[category] === undefined)
continue;
for (const scripts of benchmarks[category]) {
- if (filter && scripts.lastIndexOf(filter) === -1) continue;
+ if (this.shouldSkip(scripts)) continue;
paths.push(path.join(category, scripts));
}
@@ -96,3 +95,23 @@ CLI.prototype.benchmarks = function() {
return paths;
};
+
+CLI.prototype.shouldSkip = function(scripts) {
+ const filters = this.optional.filter || [];
+ const excludes = this.optional.exclude || [];
+ let skip = filters.length > 0;
+
+ for (const filter of filters) {
+ if (scripts.lastIndexOf(filter) !== -1) {
+ skip = false;
+ }
+ }
+
+ for (const exclude of excludes) {
+ if (scripts.lastIndexOf(exclude) !== -1) {
+ skip = true;
+ }
+ }
+
+ return skip;
+};
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/benchmark/compare.js b/benchmark/compare.js
index bd7c4a95cbb617..53f82bb4b9f1b9 100644
--- a/benchmark/compare.js
+++ b/benchmark/compare.js
@@ -18,10 +18,13 @@ const cli = CLI(`usage: ./node compare.js [options] [--] ...
--new ./new-node-binary new node binary (required)
--old ./old-node-binary old node binary (required)
--runs 30 number of samples
- --filter pattern string to filter benchmark scripts
+ --filter pattern includes only benchmark scripts matching
+ (can be repeated)
+ --exclude pattern excludes scripts matching (can be
+ repeated)
--set variable=value set benchmark variable (can be repeated)
--no-progress don't show benchmark progress indicator
-`, { arrayArgs: ['set'], boolArgs: ['no-progress'] });
+`, { arrayArgs: ['set', 'filter', 'exclude'], boolArgs: ['no-progress'] });
if (!cli.optional.new || !cli.optional.old) {
cli.abort(cli.usage);
diff --git a/benchmark/run.js b/benchmark/run.js
index 2eb1ab1a4b0905..8e81a2c5e16ab7 100644
--- a/benchmark/run.js
+++ b/benchmark/run.js
@@ -8,10 +8,13 @@ const cli = CLI(`usage: ./node run.js [options] [--] ...
Run each benchmark in the directory a single time, more than one
directory can be specified.
- --filter pattern string to filter benchmark scripts
+ --filter pattern includes only benchmark scripts matching
+ (can be repeated)
+ --exclude pattern excludes scripts matching (can be
+ repeated)
--set variable=value set benchmark variable (can be repeated)
--format [simple|csv] optional value that specifies the output format
-`, { arrayArgs: ['set'] });
+`, { arrayArgs: ['set', 'filter', 'exclude'] });
const benchmarks = cli.benchmarks();
if (benchmarks.length === 0) {
diff --git a/benchmark/util/format.js b/benchmark/util/format.js
index 44e950a6ca6522..976e0f4e655486 100644
--- a/benchmark/util/format.js
+++ b/benchmark/util/format.js
@@ -13,6 +13,8 @@ const inputs = {
'no-replace-2': ['foobar', 'yeah', 'mensch', 5],
'only-objects': [{ msg: 'This is an error' }, { msg: 'This is an error' }],
'many-%': ['replace%%%%s%%%%many%s%s%s', 'percent'],
+ 'object-to-string': ['foo %s bar', { toString() { return 'bla'; } }],
+ 'object-%s': ['foo %s bar', { a: true, b: false }],
};
const bench = common.createBenchmark(main, {
diff --git a/benchmark/util/inspect-proxy.js b/benchmark/util/inspect-proxy.js
index dde86941ff42a3..02379cdc770f3b 100644
--- a/benchmark/util/inspect-proxy.js
+++ b/benchmark/util/inspect-proxy.js
@@ -3,13 +3,21 @@
const util = require('util');
const common = require('../common.js');
-const bench = common.createBenchmark(main, { n: [2e4] });
+const bench = common.createBenchmark(main, {
+ n: [1e5],
+ showProxy: [0, 1],
+ isProxy: [0, 1]
+});
-function main({ n }) {
- const proxyA = new Proxy({}, { get: () => {} });
- const proxyB = new Proxy(() => {}, {});
+function main({ n, showProxy, isProxy }) {
+ let proxyA = {};
+ let proxyB = () => {};
+ if (isProxy) {
+ proxyA = new Proxy(proxyA, { get: () => {} });
+ proxyB = new Proxy(proxyB, {});
+ }
bench.start();
for (let i = 0; i < n; i += 1)
- util.inspect({ a: proxyA, b: proxyB }, { showProxy: true });
+ util.inspect({ a: proxyA, b: proxyB }, { showProxy });
bench.end(n);
}
diff --git a/doc/guides/writing-and-running-benchmarks.md b/benchmark/writing-and-running-benchmarks.md
similarity index 83%
rename from doc/guides/writing-and-running-benchmarks.md
rename to benchmark/writing-and-running-benchmarks.md
index 6097830aeeba1f..1db72d22de5324 100644
--- a/doc/guides/writing-and-running-benchmarks.md
+++ b/benchmark/writing-and-running-benchmarks.md
@@ -8,6 +8,7 @@
* [Running benchmarks](#running-benchmarks)
* [Running individual benchmarks](#running-individual-benchmarks)
* [Running all benchmarks](#running-all-benchmarks)
+ * [Filtering benchmarks](#filtering-benchmarks)
* [Comparing Node.js versions](#comparing-nodejs-versions)
* [Comparing parameters](#comparing-parameters)
* [Running Benchmarks on the CI](#running-benchmarks-on-the-ci)
@@ -149,6 +150,87 @@ It is possible to execute more groups by adding extra process arguments.
$ node benchmark/run.js assert async_hooks
```
+#### Filtering benchmarks
+
+`benchmark/run.js` and `benchmark/compare.js` have `--filter pattern` and
+`--exclude pattern` options, which can be used to run a subset of benchmarks or
+to exclude specific benchmarks from the execution, respectively.
+
+```console
+$ node benchmark/run.js --filter "deepequal-b" assert
+
+assert/deepequal-buffer.js
+assert/deepequal-buffer.js method="deepEqual" strict=0 len=100 n=20000: 773,200.4995493788
+assert/deepequal-buffer.js method="notDeepEqual" strict=0 len=100 n=20000: 964,411.712953848
+
+$ node benchmark/run.js --exclude "deepequal-b" assert
+
+assert/deepequal-map.js
+assert/deepequal-map.js method="deepEqual_primitiveOnly" strict=0 len=500 n=500: 20,445.06368453332
+assert/deepequal-map.js method="deepEqual_objectOnly" strict=0 len=500 n=500: 1,393.3481642240833
+...
+
+assert/deepequal-object.js
+assert/deepequal-object.js method="deepEqual" strict=0 size=100 n=5000: 1,053.1950937538475
+assert/deepequal-object.js method="notDeepEqual" strict=0 size=100 n=5000: 9,734.193251965213
+...
+```
+
+`--filter` and `--exclude` can be repeated to provide multiple patterns.
+
+```console
+$ node benchmark/run.js --filter "deepequal-b" --filter "deepequal-m" assert
+
+assert/deepequal-buffer.js
+assert/deepequal-buffer.js method="deepEqual" strict=0 len=100 n=20000: 773,200.4995493788
+assert/deepequal-buffer.js method="notDeepEqual" strict=0 len=100 n=20000: 964,411.712953848
+
+assert/deepequal-map.js
+assert/deepequal-map.js method="deepEqual_primitiveOnly" strict=0 len=500 n=500: 20,445.06368453332
+assert/deepequal-map.js method="deepEqual_objectOnly" strict=0 len=500 n=500: 1,393.3481642240833
+
+$ node benchmark/run.js --exclude "deepequal-b" --exclude "deepequal-m" assert
+
+assert/deepequal-object.js
+assert/deepequal-object.js method="deepEqual" strict=0 size=100 n=5000: 1,053.1950937538475
+assert/deepequal-object.js method="notDeepEqual" strict=0 size=100 n=5000: 9,734.193251965213
+...
+
+assert/deepequal-prims-and-objs-big-array-set.js
+assert/deepequal-prims-and-objs-big-array-set.js method="deepEqual_Array" strict=0 len=20000 n=25 primitive="string": 865.2977195251661
+assert/deepequal-prims-and-objs-big-array-set.js method="notDeepEqual_Array" strict=0 len=20000 n=25 primitive="string": 827.8297281403861
+assert/deepequal-prims-and-objs-big-array-set.js method="deepEqual_Set" strict=0 len=20000 n=25 primitive="string": 28,826.618268696366
+...
+```
+
+If `--filter` and `--exclude` are used together, `--filter` is applied first,
+and `--exclude` is applied on the result of `--filter`:
+
+```console
+$ node benchmark/run.js --filter "bench-" process
+
+process/bench-env.js
+process/bench-env.js operation="get" n=1000000: 2,356,946.0770617095
+process/bench-env.js operation="set" n=1000000: 1,295,176.3266261867
+process/bench-env.js operation="enumerate" n=1000000: 24,592.32231990992
+process/bench-env.js operation="query" n=1000000: 3,625,787.2150573144
+process/bench-env.js operation="delete" n=1000000: 1,521,131.5742806569
+
+process/bench-hrtime.js
+process/bench-hrtime.js type="raw" n=1000000: 13,178,002.113936031
+process/bench-hrtime.js type="diff" n=1000000: 11,585,435.712423025
+process/bench-hrtime.js type="bigint" n=1000000: 13,342,884.703919787
+
+$ node benchmark/run.js --filter "bench-" --exclude "hrtime" process
+
+process/bench-env.js
+process/bench-env.js operation="get" n=1000000: 2,356,946.0770617095
+process/bench-env.js operation="set" n=1000000: 1,295,176.3266261867
+process/bench-env.js operation="enumerate" n=1000000: 24,592.32231990992
+process/bench-env.js operation="query" n=1000000: 3,625,787.2150573144
+process/bench-env.js operation="delete" n=1000000: 1,521,131.5742806569
+```
+
### Comparing Node.js versions
To compare the effect of a new Node.js version use the `compare.js` tool. This
diff --git a/common.gypi b/common.gypi
index 54a8d930c4c062..210e86eeb260d5 100644
--- a/common.gypi
+++ b/common.gypi
@@ -73,9 +73,6 @@
# TODO(refack): make v8-perfetto happen
'v8_use_perfetto': 0,
- 'v8_enable_pointer_compression': 0,
- 'v8_enable_31bit_smis_on_64bit_arch': 0,
-
##### end V8 defaults #####
'conditions': [
@@ -130,8 +127,8 @@
'ldflags': [ '-Wl,-bbigtoc' ],
}],
['OS == "android"', {
- 'cflags': [ '-fPIE' ],
- 'ldflags': [ '-fPIE', '-pie' ]
+ 'cflags': [ '-fPIC' ],
+ 'ldflags': [ '-fPIC' ]
}],
],
'msvs_settings': {
@@ -190,8 +187,8 @@
],
},],
['OS == "android"', {
- 'cflags': [ '-fPIE' ],
- 'ldflags': [ '-fPIE', '-pie' ]
+ 'cflags': [ '-fPIC' ],
+ 'ldflags': [ '-fPIC' ]
}],
],
'msvs_settings': {
diff --git a/configure.py b/configure.py
index 48624aba92bf19..fb6a316118a9cb 100755
--- a/configure.py
+++ b/configure.py
@@ -346,6 +346,11 @@
dest='trace_maps',
help='Enable the --trace-maps flag in V8 (use at your own risk)')
+parser.add_option('--experimental-enable-pointer-compression',
+ action='store_true',
+ dest='enable_pointer_compression',
+ help='[Experimental] Enable V8 pointer compression (limits max heap to 4GB and breaks ABI compatibility)')
+
parser.add_option('--v8-options',
action='store',
dest='v8_options',
@@ -1117,14 +1122,17 @@ def configure_node(o):
o['variables']['node_shared'] = b(options.shared)
node_module_version = getmoduleversion.get_version()
- if sys.platform == 'darwin':
+ if options.dest_os == 'android':
+ shlib_suffix = 'so'
+ elif sys.platform == 'darwin':
shlib_suffix = '%s.dylib'
elif sys.platform.startswith('aix'):
shlib_suffix = '%s.a'
else:
shlib_suffix = 'so.%s'
+ if '%s' in shlib_suffix:
+ shlib_suffix %= node_module_version
- shlib_suffix %= node_module_version
o['variables']['node_module_version'] = int(node_module_version)
o['variables']['shlib_suffix'] = shlib_suffix
@@ -1192,6 +1200,8 @@ def configure_v8(o):
o['variables']['v8_random_seed'] = 0 # Use a random seed for hash tables.
o['variables']['v8_promise_internal_field_count'] = 1 # Add internal field to promises for async hooks.
o['variables']['v8_use_siphash'] = 0 if options.without_siphash else 1
+ o['variables']['v8_enable_pointer_compression'] = 1 if options.enable_pointer_compression else 0
+ o['variables']['v8_enable_31bit_smis_on_64bit_arch'] = 1 if options.enable_pointer_compression else 0
o['variables']['v8_trace_maps'] = 1 if options.trace_maps else 0
o['variables']['node_use_v8_platform'] = b(not options.without_v8_platform)
o['variables']['node_use_bundled_v8'] = b(not options.without_bundled_v8)
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 @@
* |
*
* 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 962fe59750de58..f55e9252f6da9b 100644
Binary files a/deps/icu-small/source/data/in/icudt64l.dat.bz2 and b/deps/icu-small/source/data/in/icudt65l.dat.bz2 differ
diff --git a/deps/icu-small/source/i18n/alphaindex.cpp b/deps/icu-small/source/i18n/alphaindex.cpp
index 99f70114cbdb15..532e3373835e7c 100644
--- a/deps/icu-small/source/i18n/alphaindex.cpp
+++ b/deps/icu-small/source/i18n/alphaindex.cpp
@@ -260,8 +260,7 @@ AlphabeticIndex::ImmutableIndex *AlphabeticIndex::buildImmutableIndex(UErrorCode
// but that would be worth it only if this method is called multiple times,
// or called after using the old-style bucket iterator API.
LocalPointer immutableBucketList(createBucketList(errorCode));
- LocalPointer coll(
- static_cast(collatorPrimaryOnly_->clone()));
+ LocalPointer coll(collatorPrimaryOnly_->clone());
if (immutableBucketList.isNull() || coll.isNull()) {
errorCode = U_MEMORY_ALLOCATION_ERROR;
return NULL;
@@ -907,7 +906,7 @@ void AlphabeticIndex::init(const Locale *locale, UErrorCode &status) {
return;
}
}
- collatorPrimaryOnly_ = static_cast(collator_->clone());
+ collatorPrimaryOnly_ = collator_->clone();
if (collatorPrimaryOnly_ == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
@@ -958,7 +957,7 @@ collatorComparator(const void *context, const void *left, const void *right) {
}
if (leftString == NULL) {
return 1;
- };
+ }
if (rightString == NULL) {
return -1;
}
diff --git a/deps/icu-small/source/i18n/anytrans.cpp b/deps/icu-small/source/i18n/anytrans.cpp
index 6e382b824b95b7..167b0185285371 100644
--- a/deps/icu-small/source/i18n/anytrans.cpp
+++ b/deps/icu-small/source/i18n/anytrans.cpp
@@ -226,7 +226,7 @@ AnyTransliterator::AnyTransliterator(const AnyTransliterator& o) :
/**
* Transliterator API.
*/
-Transliterator* AnyTransliterator::clone() const {
+AnyTransliterator* AnyTransliterator::clone() const {
return new AnyTransliterator(*this);
}
diff --git a/deps/icu-small/source/i18n/anytrans.h b/deps/icu-small/source/i18n/anytrans.h
index 703d42b6d4be55..627dee3c814e68 100644
--- a/deps/icu-small/source/i18n/anytrans.h
+++ b/deps/icu-small/source/i18n/anytrans.h
@@ -66,7 +66,7 @@ class AnyTransliterator : public Transliterator {
/**
* Transliterator API.
*/
- virtual Transliterator* clone() const;
+ virtual AnyTransliterator* clone() const;
/**
* Implements {@link Transliterator#handleTransliterate}.
diff --git a/deps/icu-small/source/i18n/astro.cpp b/deps/icu-small/source/i18n/astro.cpp
index 0d521b037dd772..d28e516472e1b9 100644
--- a/deps/icu-small/source/i18n/astro.cpp
+++ b/deps/icu-small/source/i18n/astro.cpp
@@ -65,10 +65,7 @@ static inline UBool isINVALID(double d) {
return(uprv_isNaN(d));
}
-static icu::UMutex *ccLock() {
- static icu::UMutex m = U_MUTEX_INITIALIZER;
- return &m;
-}
+static icu::UMutex ccLock;
U_CDECL_BEGIN
static UBool calendar_astro_cleanup(void) {
@@ -1552,12 +1549,12 @@ int32_t CalendarCache::get(CalendarCache** cache, int32_t key, UErrorCode &statu
if(U_FAILURE(status)) {
return 0;
}
- umtx_lock(ccLock());
+ umtx_lock(&ccLock);
if(*cache == NULL) {
createCache(cache, status);
if(U_FAILURE(status)) {
- umtx_unlock(ccLock());
+ umtx_unlock(&ccLock);
return 0;
}
}
@@ -1565,7 +1562,7 @@ int32_t CalendarCache::get(CalendarCache** cache, int32_t key, UErrorCode &statu
res = uhash_igeti((*cache)->fTable, key);
U_DEBUG_ASTRO_MSG(("%p: GET: [%d] == %d\n", (*cache)->fTable, key, res));
- umtx_unlock(ccLock());
+ umtx_unlock(&ccLock);
return res;
}
@@ -1573,12 +1570,12 @@ void CalendarCache::put(CalendarCache** cache, int32_t key, int32_t value, UErro
if(U_FAILURE(status)) {
return;
}
- umtx_lock(ccLock());
+ umtx_lock(&ccLock);
if(*cache == NULL) {
createCache(cache, status);
if(U_FAILURE(status)) {
- umtx_unlock(ccLock());
+ umtx_unlock(&ccLock);
return;
}
}
@@ -1586,7 +1583,7 @@ void CalendarCache::put(CalendarCache** cache, int32_t key, int32_t value, UErro
uhash_iputi((*cache)->fTable, key, value, &status);
U_DEBUG_ASTRO_MSG(("%p: PUT: [%d] := %d\n", (*cache)->fTable, key, value));
- umtx_unlock(ccLock());
+ umtx_unlock(&ccLock);
}
CalendarCache::CalendarCache(int32_t size, UErrorCode &status) {
diff --git a/deps/icu-small/source/i18n/bocsu.h b/deps/icu-small/source/i18n/bocsu.h
index 6b8ed5197097fd..631e29aa768b9d 100644
--- a/deps/icu-small/source/i18n/bocsu.h
+++ b/deps/icu-small/source/i18n/bocsu.h
@@ -144,14 +144,14 @@ U_NAMESPACE_END
* yields negative modulo results and quotients that are one more than
* what we need here.
*/
-#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
U_CFUNC UChar32
u_writeIdenticalLevelRun(UChar32 prev, const UChar *s, int32_t length, icu::ByteSink &sink);
diff --git a/deps/icu-small/source/i18n/brktrans.cpp b/deps/icu-small/source/i18n/brktrans.cpp
index ac9e2afb7e4679..46b0e345dae97d 100644
--- a/deps/icu-small/source/i18n/brktrans.cpp
+++ b/deps/icu-small/source/i18n/brktrans.cpp
@@ -64,7 +64,7 @@ BreakTransliterator::BreakTransliterator(const BreakTransliterator& o) :
/**
* Transliterator API.
*/
-Transliterator* BreakTransliterator::clone(void) const {
+BreakTransliterator* BreakTransliterator::clone() const {
return new BreakTransliterator(*this);
}
diff --git a/deps/icu-small/source/i18n/brktrans.h b/deps/icu-small/source/i18n/brktrans.h
index fcc8bdd002ca76..caa1e16ee6e62e 100644
--- a/deps/icu-small/source/i18n/brktrans.h
+++ b/deps/icu-small/source/i18n/brktrans.h
@@ -54,7 +54,7 @@ class BreakTransliterator : public Transliterator {
* Transliterator API.
* @return A copy of the object.
*/
- virtual Transliterator* clone(void) const;
+ virtual BreakTransliterator* clone() const;
virtual const UnicodeString &getInsertion() const;
diff --git a/deps/icu-small/source/i18n/buddhcal.cpp b/deps/icu-small/source/i18n/buddhcal.cpp
index b6ccbc4749955a..bddfd1768a0aba 100644
--- a/deps/icu-small/source/i18n/buddhcal.cpp
+++ b/deps/icu-small/source/i18n/buddhcal.cpp
@@ -53,7 +53,7 @@ BuddhistCalendar& BuddhistCalendar::operator= ( const BuddhistCalendar& right)
return *this;
}
-Calendar* BuddhistCalendar::clone(void) const
+BuddhistCalendar* BuddhistCalendar::clone() const
{
return new BuddhistCalendar(*this);
}
@@ -133,7 +133,7 @@ void BuddhistCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& stat
*/
static UDate gSystemDefaultCenturyStart = DBL_MIN;
static int32_t gSystemDefaultCenturyStartYear = -1;
-static icu::UInitOnce gBCInitOnce;
+static icu::UInitOnce gBCInitOnce = U_INITONCE_INITIALIZER;
UBool BuddhistCalendar::haveDefaultCentury() const
diff --git a/deps/icu-small/source/i18n/buddhcal.h b/deps/icu-small/source/i18n/buddhcal.h
index 89e3f3dec36625..c3ffa6a41d3565 100644
--- a/deps/icu-small/source/i18n/buddhcal.h
+++ b/deps/icu-small/source/i18n/buddhcal.h
@@ -94,7 +94,7 @@ class BuddhistCalendar : public GregorianCalendar {
* @return return a polymorphic copy of this calendar.
* @internal
*/
- virtual Calendar* clone(void) const;
+ virtual BuddhistCalendar* clone() const;
public:
/**
diff --git a/deps/icu-small/source/i18n/calendar.cpp b/deps/icu-small/source/i18n/calendar.cpp
index 85a387ef49ed16..94625465614547 100644
--- a/deps/icu-small/source/i18n/calendar.cpp
+++ b/deps/icu-small/source/i18n/calendar.cpp
@@ -268,6 +268,8 @@ static ECalType getCalendarTypeForLocale(const char *locid) {
// canonicalize, so grandfathered variant will be transformed to keywords
// e.g ja_JP_TRADITIONAL -> ja_JP@calendar=japanese
+ // NOTE: Since ICU-20187, ja_JP_TRADITIONAL no longer canonicalizes, and
+ // the Gregorian calendar is returned instead.
int32_t canonicalLen = uloc_canonicalize(locid, canonicalName, sizeof(canonicalName) - 1, &status);
if (U_FAILURE(status)) {
return CALTYPE_GREGORIAN;
@@ -748,6 +750,7 @@ fSkippedWallTime(UCAL_WALLTIME_LAST)
validLocale[0] = 0;
actualLocale[0] = 0;
if (U_FAILURE(success)) {
+ delete zone;
return;
}
if(zone == 0) {
@@ -2592,7 +2595,7 @@ Calendar::isWeekend(UDate date, UErrorCode &status) const
return FALSE;
}
// clone the calendar so we don't mess with the real one.
- Calendar *work = (Calendar*)this->clone();
+ Calendar *work = this->clone();
if (work == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return FALSE;
@@ -2752,7 +2755,7 @@ Calendar::getActualMinimum(UCalendarDateFields field, UErrorCode& status) const
// clone the calendar so we don't mess with the real one, and set it to
// accept anything for the field values
- Calendar *work = (Calendar*)this->clone();
+ Calendar *work = this->clone();
if (work == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return 0;
diff --git a/deps/icu-small/source/i18n/casetrn.cpp b/deps/icu-small/source/i18n/casetrn.cpp
index f08d448881d364..06750b29837223 100644
--- a/deps/icu-small/source/i18n/casetrn.cpp
+++ b/deps/icu-small/source/i18n/casetrn.cpp
@@ -125,7 +125,7 @@ CaseMapTransliterator::CaseMapTransliterator(const CaseMapTransliterator& o) :
/**
* Transliterator API.
*/
-/*Transliterator* CaseMapTransliterator::clone(void) const {
+/*CaseMapTransliterator* CaseMapTransliterator::clone() const {
return new CaseMapTransliterator(*this);
}*/
diff --git a/deps/icu-small/source/i18n/casetrn.h b/deps/icu-small/source/i18n/casetrn.h
index eee443fc81d4e6..47914022f857eb 100644
--- a/deps/icu-small/source/i18n/casetrn.h
+++ b/deps/icu-small/source/i18n/casetrn.h
@@ -58,7 +58,7 @@ class CaseMapTransliterator : public Transliterator {
* Transliterator API.
* @return a copy of the object.
*/
- virtual Transliterator* clone(void) const = 0;
+ virtual CaseMapTransliterator* clone() const = 0;
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
diff --git a/deps/icu-small/source/i18n/chnsecal.cpp b/deps/icu-small/source/i18n/chnsecal.cpp
index 3c4ad2a846619f..2ff9f755afe1f1 100644
--- a/deps/icu-small/source/i18n/chnsecal.cpp
+++ b/deps/icu-small/source/i18n/chnsecal.cpp
@@ -51,10 +51,7 @@ static void debug_chnsecal_msg(const char *pat, ...)
// --- The cache --
-static icu::UMutex *astroLock() { // Protects access to gChineseCalendarAstro.
- static icu::UMutex m = U_MUTEX_INITIALIZER;
- return &m;
-}
+static icu::UMutex astroLock;
static icu::CalendarAstronomer *gChineseCalendarAstro = NULL;
// Lazy Creation & Access synchronized by class CalendarCache with a mutex.
@@ -121,7 +118,7 @@ U_NAMESPACE_BEGIN
//-------------------------------------------------------------------------
-Calendar* ChineseCalendar::clone() const {
+ChineseCalendar* ChineseCalendar::clone() const {
return new ChineseCalendar(*this);
}
@@ -538,14 +535,14 @@ int32_t ChineseCalendar::winterSolstice(int32_t gyear) const {
// PST 1298 with a final result of Dec 14 10:31:59 PST 1299.
double ms = daysToMillis(Grego::fieldsToDay(gyear, UCAL_DECEMBER, 1));
- umtx_lock(astroLock());
+ umtx_lock(&astroLock);
if(gChineseCalendarAstro == NULL) {
gChineseCalendarAstro = new CalendarAstronomer();
ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup);
}
gChineseCalendarAstro->setTime(ms);
UDate solarLong = gChineseCalendarAstro->getSunTime(CalendarAstronomer::WINTER_SOLSTICE(), TRUE);
- umtx_unlock(astroLock());
+ umtx_unlock(&astroLock);
// Winter solstice is 270 degrees solar longitude aka Dongzhi
cacheValue = (int32_t)millisToDays(solarLong);
@@ -568,14 +565,14 @@ int32_t ChineseCalendar::winterSolstice(int32_t gyear) const {
*/
int32_t ChineseCalendar::newMoonNear(double days, UBool after) const {
- umtx_lock(astroLock());
+ umtx_lock(&astroLock);
if(gChineseCalendarAstro == NULL) {
gChineseCalendarAstro = new CalendarAstronomer();
ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup);
}
gChineseCalendarAstro->setTime(daysToMillis(days));
UDate newMoon = gChineseCalendarAstro->getMoonTime(CalendarAstronomer::NEW_MOON(), after);
- umtx_unlock(astroLock());
+ umtx_unlock(&astroLock);
return (int32_t) millisToDays(newMoon);
}
@@ -600,14 +597,14 @@ int32_t ChineseCalendar::synodicMonthsBetween(int32_t day1, int32_t day2) const
*/
int32_t ChineseCalendar::majorSolarTerm(int32_t days) const {
- umtx_lock(astroLock());
+ umtx_lock(&astroLock);
if(gChineseCalendarAstro == NULL) {
gChineseCalendarAstro = new CalendarAstronomer();
ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup);
}
gChineseCalendarAstro->setTime(daysToMillis(days));
UDate solarLongitude = gChineseCalendarAstro->getSunLongitude();
- umtx_unlock(astroLock());
+ umtx_unlock(&astroLock);
// Compute (floor(solarLongitude / (pi/6)) + 2) % 12
int32_t term = ( ((int32_t)(6 * solarLongitude / CalendarAstronomer::PI)) + 2 ) % 12;
diff --git a/deps/icu-small/source/i18n/chnsecal.h b/deps/icu-small/source/i18n/chnsecal.h
index 1b27d2d1bcc78b..c7c063738145e7 100644
--- a/deps/icu-small/source/i18n/chnsecal.h
+++ b/deps/icu-small/source/i18n/chnsecal.h
@@ -144,7 +144,7 @@ class U_I18N_API ChineseCalendar : public Calendar {
virtual ~ChineseCalendar();
// clone
- virtual Calendar* clone() const;
+ virtual ChineseCalendar* clone() const;
private:
diff --git a/deps/icu-small/source/i18n/choicfmt.cpp b/deps/icu-small/source/i18n/choicfmt.cpp
index 1b846704bfe1e4..16880706d3f1dc 100644
--- a/deps/icu-small/source/i18n/choicfmt.cpp
+++ b/deps/icu-small/source/i18n/choicfmt.cpp
@@ -563,7 +563,7 @@ ChoiceFormat::matchStringUntilLimitPart(
// -------------------------------------
-Format*
+ChoiceFormat*
ChoiceFormat::clone() const
{
ChoiceFormat *aCopy = new ChoiceFormat(*this);
diff --git a/deps/icu-small/source/i18n/coll.cpp b/deps/icu-small/source/i18n/coll.cpp
index 8bbe133664c2cd..984831e761bdd6 100644
--- a/deps/icu-small/source/i18n/coll.cpp
+++ b/deps/icu-small/source/i18n/coll.cpp
@@ -67,7 +67,7 @@ static int32_t availableLocaleListCount;
static icu::ICULocaleService* gService = NULL;
static icu::UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER;
#endif
-static icu::UInitOnce gAvailableLocaleListInitOnce;
+static icu::UInitOnce gAvailableLocaleListInitOnce = U_INITONCE_INITIALIZER;
/**
* Release all static memory held by collator.
diff --git a/deps/icu-small/source/i18n/collationiterator.cpp b/deps/icu-small/source/i18n/collationiterator.cpp
index 961c9e9acef675..18ccf014f0a48c 100644
--- a/deps/icu-small/source/i18n/collationiterator.cpp
+++ b/deps/icu-small/source/i18n/collationiterator.cpp
@@ -872,7 +872,7 @@ CollationIterator::previousCE(UVector32 &offsets, UErrorCode &errorCode) {
// consistent with forward iteration.
while(offsets.size() <= ceBuffer.length) {
offsets.addElement(limitOffset, errorCode);
- };
+ }
}
return ceBuffer.get(--ceBuffer.length);
} else {
@@ -932,7 +932,7 @@ CollationIterator::previousCEUnsafe(UChar32 c, UVector32 &offsets, UErrorCode &e
offset = getOffset();
while(offsets.size() < ceBuffer.length) {
offsets.addElement(offset, errorCode);
- };
+ }
}
U_ASSERT(offsets.size() == ceBuffer.length);
// End offset corresponding to just after the unsafe-backwards segment.
diff --git a/deps/icu-small/source/i18n/compactdecimalformat.cpp b/deps/icu-small/source/i18n/compactdecimalformat.cpp
index 4dd2241b23d0a6..a4c9dad25c408f 100644
--- a/deps/icu-small/source/i18n/compactdecimalformat.cpp
+++ b/deps/icu-small/source/i18n/compactdecimalformat.cpp
@@ -30,9 +30,9 @@ CompactDecimalFormat::CompactDecimalFormat(const Locale& inLocale, UNumberCompac
: DecimalFormat(new DecimalFormatSymbols(inLocale, status), status) {
if (U_FAILURE(status)) return;
// Minimal properties: let the non-shim code path do most of the logic for us.
- fields->properties->compactStyle = style;
- fields->properties->groupingSize = -2; // do not forward grouping information
- fields->properties->minimumGroupingDigits = 2;
+ fields->properties.compactStyle = style;
+ fields->properties.groupingSize = -2; // do not forward grouping information
+ fields->properties.minimumGroupingDigits = 2;
touch(status);
}
@@ -45,7 +45,7 @@ CompactDecimalFormat& CompactDecimalFormat::operator=(const CompactDecimalFormat
return *this;
}
-Format* CompactDecimalFormat::clone() const {
+CompactDecimalFormat* CompactDecimalFormat::clone() const {
return new CompactDecimalFormat(*this);
}
diff --git a/deps/icu-small/source/i18n/coptccal.cpp b/deps/icu-small/source/i18n/coptccal.cpp
index 39691217d0fcb5..229119bf164e80 100644
--- a/deps/icu-small/source/i18n/coptccal.cpp
+++ b/deps/icu-small/source/i18n/coptccal.cpp
@@ -40,7 +40,7 @@ CopticCalendar::~CopticCalendar()
{
}
-Calendar*
+CopticCalendar*
CopticCalendar::clone() const
{
return new CopticCalendar(*this);
diff --git a/deps/icu-small/source/i18n/coptccal.h b/deps/icu-small/source/i18n/coptccal.h
index 0b82c36088fb0d..dc2d79c89e6c22 100644
--- a/deps/icu-small/source/i18n/coptccal.h
+++ b/deps/icu-small/source/i18n/coptccal.h
@@ -145,7 +145,7 @@ class CopticCalendar : public CECalendar {
* @return return a polymorphic copy of this calendar.
* @internal
*/
- virtual Calendar* clone(void) const;
+ virtual CopticCalendar* clone() const;
/**
* return the calendar type, "coptic"
diff --git a/deps/icu-small/source/i18n/cpdtrans.cpp b/deps/icu-small/source/i18n/cpdtrans.cpp
index a204de5a5352dd..624ae431d35aa6 100644
--- a/deps/icu-small/source/i18n/cpdtrans.cpp
+++ b/deps/icu-small/source/i18n/cpdtrans.cpp
@@ -323,7 +323,7 @@ CompoundTransliterator& CompoundTransliterator::operator=(
/**
* Transliterator API.
*/
-Transliterator* CompoundTransliterator::clone(void) const {
+CompoundTransliterator* CompoundTransliterator::clone() const {
return new CompoundTransliterator(*this);
}
diff --git a/deps/icu-small/source/i18n/cpdtrans.h b/deps/icu-small/source/i18n/cpdtrans.h
index 29f3ba83fc1d57..e51b209411f68b 100644
--- a/deps/icu-small/source/i18n/cpdtrans.h
+++ b/deps/icu-small/source/i18n/cpdtrans.h
@@ -98,7 +98,7 @@ class U_I18N_API CompoundTransliterator : public Transliterator {
/**
* Transliterator API.
*/
- virtual Transliterator* clone(void) const;
+ virtual CompoundTransliterator* clone() const;
/**
* Returns the number of transliterators in this chain.
diff --git a/deps/icu-small/source/i18n/csdetect.cpp b/deps/icu-small/source/i18n/csdetect.cpp
index ad3565155dd382..566333fec667ad 100644
--- a/deps/icu-small/source/i18n/csdetect.cpp
+++ b/deps/icu-small/source/i18n/csdetect.cpp
@@ -47,7 +47,7 @@ struct CSRecognizerInfo : public UMemory {
U_NAMESPACE_END
static icu::CSRecognizerInfo **fCSRecognizers = NULL;
-static icu::UInitOnce gCSRecognizersInitOnce;
+static icu::UInitOnce gCSRecognizersInitOnce = U_INITONCE_INITIALIZER;
static int32_t fCSRecognizers_size = 0;
U_CDECL_BEGIN
diff --git a/deps/icu-small/source/i18n/curramt.cpp b/deps/icu-small/source/i18n/curramt.cpp
index 019c17df8e3379..69ab42ace9d9ec 100644
--- a/deps/icu-small/source/i18n/curramt.cpp
+++ b/deps/icu-small/source/i18n/curramt.cpp
@@ -38,7 +38,7 @@ CurrencyAmount& CurrencyAmount::operator=(const CurrencyAmount& other) {
return *this;
}
-UObject* CurrencyAmount::clone() const {
+CurrencyAmount* CurrencyAmount::clone() const {
return new CurrencyAmount(*this);
}
diff --git a/deps/icu-small/source/i18n/currfmt.cpp b/deps/icu-small/source/i18n/currfmt.cpp
index 8f20f783d25031..0ad0492ee7afbc 100644
--- a/deps/icu-small/source/i18n/currfmt.cpp
+++ b/deps/icu-small/source/i18n/currfmt.cpp
@@ -33,7 +33,7 @@ CurrencyFormat::CurrencyFormat(const CurrencyFormat& other) :
CurrencyFormat::~CurrencyFormat() {
}
-Format* CurrencyFormat::clone() const {
+CurrencyFormat* CurrencyFormat::clone() const {
return new CurrencyFormat(*this);
}
diff --git a/deps/icu-small/source/i18n/currfmt.h b/deps/icu-small/source/i18n/currfmt.h
index cc9bb3c1bacd05..69a031957bcea9 100644
--- a/deps/icu-small/source/i18n/currfmt.h
+++ b/deps/icu-small/source/i18n/currfmt.h
@@ -57,7 +57,7 @@ class CurrencyFormat : public MeasureFormat {
/**
* Override Format API.
*/
- virtual Format* clone() const;
+ virtual CurrencyFormat* clone() const;
using MeasureFormat::format;
diff --git a/deps/icu-small/source/i18n/currunit.cpp b/deps/icu-small/source/i18n/currunit.cpp
index 39c49e468d117d..03347604a4c1fc 100644
--- a/deps/icu-small/source/i18n/currunit.cpp
+++ b/deps/icu-small/source/i18n/currunit.cpp
@@ -109,7 +109,7 @@ CurrencyUnit& CurrencyUnit::operator=(const CurrencyUnit& other) {
return *this;
}
-UObject* CurrencyUnit::clone() const {
+CurrencyUnit* CurrencyUnit::clone() const {
return new CurrencyUnit(*this);
}
diff --git a/deps/icu-small/source/i18n/dangical.cpp b/deps/icu-small/source/i18n/dangical.cpp
index bc3951f210ec45..54e2e99fa66711 100644
--- a/deps/icu-small/source/i18n/dangical.cpp
+++ b/deps/icu-small/source/i18n/dangical.cpp
@@ -65,7 +65,7 @@ DangiCalendar::~DangiCalendar()
{
}
-Calendar*
+DangiCalendar*
DangiCalendar::clone() const
{
return new DangiCalendar(*this);
diff --git a/deps/icu-small/source/i18n/dangical.h b/deps/icu-small/source/i18n/dangical.h
index 1a1e06b9020295..4f2cf384f57664 100644
--- a/deps/icu-small/source/i18n/dangical.h
+++ b/deps/icu-small/source/i18n/dangical.h
@@ -66,7 +66,7 @@ class DangiCalendar : public ChineseCalendar {
* Clone.
* @internal
*/
- virtual Calendar* clone() const;
+ virtual DangiCalendar* clone() const;
//----------------------------------------------------------------------
// Internal methods & astronomical calculations
diff --git a/deps/icu-small/source/i18n/datefmt.cpp b/deps/icu-small/source/i18n/datefmt.cpp
index 039f5bc226bb0a..413139db84c50d 100644
--- a/deps/icu-small/source/i18n/datefmt.cpp
+++ b/deps/icu-small/source/i18n/datefmt.cpp
@@ -154,7 +154,7 @@ DateFormat& DateFormat::operator=(const DateFormat& other)
fCalendar = NULL;
}
if(other.fNumberFormat) {
- fNumberFormat = (NumberFormat*)other.fNumberFormat->clone();
+ fNumberFormat = other.fNumberFormat->clone();
} else {
fNumberFormat = NULL;
}
@@ -598,7 +598,7 @@ DateFormat::adoptNumberFormat(NumberFormat* newNumberFormat)
void
DateFormat::setNumberFormat(const NumberFormat& newNumberFormat)
{
- NumberFormat* newNumFmtClone = (NumberFormat*)newNumberFormat.clone();
+ NumberFormat* newNumFmtClone = newNumberFormat.clone();
if (newNumFmtClone != NULL) {
adoptNumberFormat(newNumFmtClone);
}
diff --git a/deps/icu-small/source/i18n/decNumberLocal.h b/deps/icu-small/source/i18n/decNumberLocal.h
index f6c291a9ad3359..e8d1b38653eb9d 100644
--- a/deps/icu-small/source/i18n/decNumberLocal.h
+++ b/deps/icu-small/source/i18n/decNumberLocal.h
@@ -259,7 +259,7 @@
/* 2,000,000,000 (as is needed for negative exponents of */
/* subnormals). The unsigned integer pow is used as a temporary */
/* variable. */
- #define TODIGIT(u, cut, c, pow) { \
+ #define TODIGIT(u, cut, c, pow) UPRV_BLOCK_MACRO_BEGIN { \
*(c)='0'; \
pow=DECPOWERS[cut]*2; \
if ((u)>pow) { \
@@ -272,7 +272,7 @@
if ((u)>=pow) {(u)-=pow; *(c)+=2;} \
pow/=2; \
if ((u)>=pow) {(u)-=pow; *(c)+=1;} \
- }
+ } UPRV_BLOCK_MACRO_END
/* ---------------------------------------------------------------- */
/* Definitions for fixed-precision modules (only valid after */
diff --git a/deps/icu-small/source/i18n/decimfmt.cpp b/deps/icu-small/source/i18n/decimfmt.cpp
index 2a1e9347fa10d0..6a69c9d7a300e6 100644
--- a/deps/icu-small/source/i18n/decimfmt.cpp
+++ b/deps/icu-small/source/i18n/decimfmt.cpp
@@ -95,7 +95,7 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols*
new CurrencyPluralInfo(fields->symbols->getLocale(), status),
status);
if (U_FAILURE(status)) { return; }
- fields->properties->currencyPluralInfo.fPtr.adoptInstead(cpi.orphan());
+ fields->properties.currencyPluralInfo.fPtr.adoptInstead(cpi.orphan());
}
touch(status);
}
@@ -111,21 +111,14 @@ DecimalFormat::DecimalFormat(const DecimalFormatSymbols* symbolsToAdopt, UErrorC
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
- fields->formatter.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(), status);
- fields->properties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status);
- fields->exportedProperties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status);
if (adoptedSymbols.isNull()) {
fields->symbols.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(status), status);
} else {
fields->symbols.adoptInsteadAndCheckErrorCode(adoptedSymbols.orphan(), status);
}
- // In order to simplify error handling logic in the various getters/setters/etc, we do not allow
- // any partially populated DecimalFormatFields object. We must have a fully complete fields object
- // or else we set it to nullptr.
- if (fields->formatter.isNull() || fields->properties.isNull() || fields->exportedProperties.isNull() || fields->symbols.isNull()) {
+ if (U_FAILURE(status)) {
delete fields;
fields = nullptr;
- status = U_MEMORY_ALLOCATION_ERROR;
}
}
@@ -133,8 +126,8 @@ DecimalFormat::DecimalFormat(const DecimalFormatSymbols* symbolsToAdopt, UErrorC
void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) {
if (fields == nullptr) { return; }
- if (value == fields->properties->parseAllInput) { return; }
- fields->properties->parseAllInput = value;
+ if (value == fields->properties.parseAllInput) { return; }
+ fields->properties.parseAllInput = value;
}
#endif
@@ -379,9 +372,9 @@ void DecimalFormat::setGroupingUsed(UBool enabled) {
if (fields == nullptr) {
return;
}
- if (UBOOL_TO_BOOL(enabled) == fields->properties->groupingUsed) { return; }
+ if (UBOOL_TO_BOOL(enabled) == fields->properties.groupingUsed) { return; }
NumberFormat::setGroupingUsed(enabled); // to set field for compatibility
- fields->properties->groupingUsed = enabled;
+ fields->properties.groupingUsed = enabled;
touchNoError();
}
@@ -389,9 +382,9 @@ void DecimalFormat::setParseIntegerOnly(UBool value) {
if (fields == nullptr) {
return;
}
- if (UBOOL_TO_BOOL(value) == fields->properties->parseIntegerOnly) { return; }
+ if (UBOOL_TO_BOOL(value) == fields->properties.parseIntegerOnly) { return; }
NumberFormat::setParseIntegerOnly(value); // to set field for compatibility
- fields->properties->parseIntegerOnly = value;
+ fields->properties.parseIntegerOnly = value;
touchNoError();
}
@@ -400,9 +393,9 @@ void DecimalFormat::setLenient(UBool enable) {
return;
}
ParseMode mode = enable ? PARSE_MODE_LENIENT : PARSE_MODE_STRICT;
- if (!fields->properties->parseMode.isNull() && mode == fields->properties->parseMode.getNoError()) { return; }
+ if (!fields->properties.parseMode.isNull() && mode == fields->properties.parseMode.getNoError()) { return; }
NumberFormat::setLenient(enable); // to set field for compatibility
- fields->properties->parseMode = mode;
+ fields->properties.parseMode = mode;
touchNoError();
}
@@ -441,19 +434,16 @@ DecimalFormat::DecimalFormat(const DecimalFormat& source) : NumberFormat(source)
// Note: it is not safe to copy fields->formatter or fWarehouse directly because fields->formatter might have
// dangling pointers to fields inside fWarehouse. The safe thing is to re-construct fields->formatter from
// the property bag, despite being somewhat slower.
- fields = new DecimalFormatFields();
+ fields = new DecimalFormatFields(source.fields->properties);
if (fields == nullptr) {
return; // no way to report an error.
}
UErrorCode status = U_ZERO_ERROR;
- fields->formatter.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(), status);
- fields->properties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(*source.fields->properties), status);
fields->symbols.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(*source.fields->symbols), status);
- fields->exportedProperties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status);
// In order to simplify error handling logic in the various getters/setters/etc, we do not allow
// any partially populated DecimalFormatFields object. We must have a fully complete fields object
// or else we set it to nullptr.
- if (fields->formatter.isNull() || fields->properties.isNull() || fields->exportedProperties.isNull() || fields->symbols.isNull()) {
+ if (U_FAILURE(status)) {
delete fields;
fields = nullptr;
return;
@@ -470,8 +460,8 @@ DecimalFormat& DecimalFormat::operator=(const DecimalFormat& rhs) {
if (fields == nullptr || rhs.fields == nullptr) {
return *this; // unfortunately, no way to report an error.
}
- *fields->properties = *rhs.fields->properties;
- fields->exportedProperties->clear();
+ fields->properties = rhs.fields->properties;
+ fields->exportedProperties.clear();
UErrorCode status = U_ZERO_ERROR;
LocalPointer dfs(new DecimalFormatSymbols(*rhs.fields->symbols), status);
if (U_FAILURE(status)) {
@@ -495,7 +485,7 @@ DecimalFormat::~DecimalFormat() {
delete fields;
}
-Format* DecimalFormat::clone() const {
+DecimalFormat* DecimalFormat::clone() const {
// can only clone valid objects.
if (fields == nullptr) {
return nullptr;
@@ -517,7 +507,7 @@ UBool DecimalFormat::operator==(const Format& other) const {
if (fields == nullptr || otherDF->fields == nullptr) {
return false;
}
- return *fields->properties == *otherDF->fields->properties && *fields->symbols == *otherDF->fields->symbols;
+ return fields->properties == otherDF->fields->properties && *fields->symbols == *otherDF->fields->symbols;
}
UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, FieldPosition& pos) const {
@@ -529,7 +519,7 @@ UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, Fie
return appendTo;
}
UErrorCode localStatus = U_ZERO_ERROR;
- FormattedNumber output = fields->formatter->formatDouble(number, localStatus);
+ FormattedNumber output = fields->formatter.formatDouble(number, localStatus);
fieldPositionHelper(output, pos, appendTo.length(), localStatus);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, localStatus);
@@ -550,7 +540,7 @@ UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, Fie
if (pos.getField() == FieldPosition::DONT_CARE && fastFormatDouble(number, appendTo)) {
return appendTo;
}
- FormattedNumber output = fields->formatter->formatDouble(number, status);
+ FormattedNumber output = fields->formatter.formatDouble(number, status);
fieldPositionHelper(output, pos, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@@ -572,7 +562,7 @@ DecimalFormat::format(double number, UnicodeString& appendTo, FieldPositionItera
if (posIter == nullptr && fastFormatDouble(number, appendTo)) {
return appendTo;
}
- FormattedNumber output = fields->formatter->formatDouble(number, status);
+ FormattedNumber output = fields->formatter.formatDouble(number, status);
fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@@ -603,7 +593,7 @@ UnicodeString& DecimalFormat::format(int64_t number, UnicodeString& appendTo, Fi
return appendTo;
}
UErrorCode localStatus = U_ZERO_ERROR;
- FormattedNumber output = fields->formatter->formatInt(number, localStatus);
+ FormattedNumber output = fields->formatter.formatInt(number, localStatus);
fieldPositionHelper(output, pos, appendTo.length(), localStatus);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, localStatus);
@@ -624,7 +614,7 @@ UnicodeString& DecimalFormat::format(int64_t number, UnicodeString& appendTo, Fi
if (pos.getField() == FieldPosition::DONT_CARE && fastFormatInt64(number, appendTo)) {
return appendTo;
}
- FormattedNumber output = fields->formatter->formatInt(number, status);
+ FormattedNumber output = fields->formatter.formatInt(number, status);
fieldPositionHelper(output, pos, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@@ -646,7 +636,7 @@ DecimalFormat::format(int64_t number, UnicodeString& appendTo, FieldPositionIter
if (posIter == nullptr && fastFormatInt64(number, appendTo)) {
return appendTo;
}
- FormattedNumber output = fields->formatter->formatInt(number, status);
+ FormattedNumber output = fields->formatter.formatInt(number, status);
fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@@ -665,7 +655,7 @@ DecimalFormat::format(StringPiece number, UnicodeString& appendTo, FieldPosition
appendTo.setToBogus();
return appendTo;
}
- FormattedNumber output = fields->formatter->formatDecimal(number, status);
+ FormattedNumber output = fields->formatter.formatDecimal(number, status);
fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@@ -683,7 +673,7 @@ UnicodeString& DecimalFormat::format(const DecimalQuantity& number, UnicodeStrin
appendTo.setToBogus();
return appendTo;
}
- FormattedNumber output = fields->formatter->formatDecimalQuantity(number, status);
+ FormattedNumber output = fields->formatter.formatDecimalQuantity(number, status);
fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@@ -702,7 +692,7 @@ DecimalFormat::format(const DecimalQuantity& number, UnicodeString& appendTo, Fi
appendTo.setToBogus();
return appendTo;
}
- FormattedNumber output = fields->formatter->formatDecimalQuantity(number, status);
+ FormattedNumber output = fields->formatter.formatDecimalQuantity(number, status);
fieldPositionHelper(output, pos, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@@ -823,7 +813,7 @@ const CurrencyPluralInfo* DecimalFormat::getCurrencyPluralInfo(void) const {
if (fields == nullptr) {
return nullptr;
}
- return fields->properties->currencyPluralInfo.fPtr.getAlias();
+ return fields->properties.currencyPluralInfo.fPtr.getAlias();
}
void DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt) {
@@ -833,7 +823,7 @@ void DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt) {
if (fields == nullptr) {
return;
}
- fields->properties->currencyPluralInfo.fPtr.adoptInstead(cpi.orphan());
+ fields->properties.currencyPluralInfo.fPtr.adoptInstead(cpi.orphan());
touchNoError();
}
@@ -841,11 +831,11 @@ void DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info) {
if (fields == nullptr) {
return;
}
- if (fields->properties->currencyPluralInfo.fPtr.isNull()) {
+ if (fields->properties.currencyPluralInfo.fPtr.isNull()) {
// Note: clone() can fail with OOM error, but we have no way to report it. :(
- fields->properties->currencyPluralInfo.fPtr.adoptInstead(info.clone());
+ fields->properties.currencyPluralInfo.fPtr.adoptInstead(info.clone());
} else {
- *fields->properties->currencyPluralInfo.fPtr = info; // copy-assignment operator
+ *fields->properties.currencyPluralInfo.fPtr = info; // copy-assignment operator
}
touchNoError();
}
@@ -856,7 +846,7 @@ UnicodeString& DecimalFormat::getPositivePrefix(UnicodeString& result) const {
return result;
}
UErrorCode status = U_ZERO_ERROR;
- fields->formatter->getAffixImpl(true, false, result, status);
+ fields->formatter.getAffixImpl(true, false, result, status);
if (U_FAILURE(status)) { result.setToBogus(); }
return result;
}
@@ -865,8 +855,8 @@ void DecimalFormat::setPositivePrefix(const UnicodeString& newValue) {
if (fields == nullptr) {
return;
}
- if (newValue == fields->properties->positivePrefix) { return; }
- fields->properties->positivePrefix = newValue;
+ if (newValue == fields->properties.positivePrefix) { return; }
+ fields->properties.positivePrefix = newValue;
touchNoError();
}
@@ -876,7 +866,7 @@ UnicodeString& DecimalFormat::getNegativePrefix(UnicodeString& result) const {
return result;
}
UErrorCode status = U_ZERO_ERROR;
- fields->formatter->getAffixImpl(true, true, result, status);
+ fields->formatter.getAffixImpl(true, true, result, status);
if (U_FAILURE(status)) { result.setToBogus(); }
return result;
}
@@ -885,8 +875,8 @@ void DecimalFormat::setNegativePrefix(const UnicodeString& newValue) {
if (fields == nullptr) {
return;
}
- if (newValue == fields->properties->negativePrefix) { return; }
- fields->properties->negativePrefix = newValue;
+ if (newValue == fields->properties.negativePrefix) { return; }
+ fields->properties.negativePrefix = newValue;
touchNoError();
}
@@ -896,7 +886,7 @@ UnicodeString& DecimalFormat::getPositiveSuffix(UnicodeString& result) const {
return result;
}
UErrorCode status = U_ZERO_ERROR;
- fields->formatter->getAffixImpl(false, false, result, status);
+ fields->formatter.getAffixImpl(false, false, result, status);
if (U_FAILURE(status)) { result.setToBogus(); }
return result;
}
@@ -905,8 +895,8 @@ void DecimalFormat::setPositiveSuffix(const UnicodeString& newValue) {
if (fields == nullptr) {
return;
}
- if (newValue == fields->properties->positiveSuffix) { return; }
- fields->properties->positiveSuffix = newValue;
+ if (newValue == fields->properties.positiveSuffix) { return; }
+ fields->properties.positiveSuffix = newValue;
touchNoError();
}
@@ -916,7 +906,7 @@ UnicodeString& DecimalFormat::getNegativeSuffix(UnicodeString& result) const {
return result;
}
UErrorCode status = U_ZERO_ERROR;
- fields->formatter->getAffixImpl(false, true, result, status);
+ fields->formatter.getAffixImpl(false, true, result, status);
if (U_FAILURE(status)) { result.setToBogus(); }
return result;
}
@@ -925,8 +915,8 @@ void DecimalFormat::setNegativeSuffix(const UnicodeString& newValue) {
if (fields == nullptr) {
return;
}
- if (newValue == fields->properties->negativeSuffix) { return; }
- fields->properties->negativeSuffix = newValue;
+ if (newValue == fields->properties.negativeSuffix) { return; }
+ fields->properties.negativeSuffix = newValue;
touchNoError();
}
@@ -935,13 +925,13 @@ UBool DecimalFormat::isSignAlwaysShown() const {
if (fields == nullptr) {
return DecimalFormatProperties::getDefault().signAlwaysShown;
}
- return fields->properties->signAlwaysShown;
+ return fields->properties.signAlwaysShown;
}
void DecimalFormat::setSignAlwaysShown(UBool value) {
if (fields == nullptr) { return; }
- if (UBOOL_TO_BOOL(value) == fields->properties->signAlwaysShown) { return; }
- fields->properties->signAlwaysShown = value;
+ if (UBOOL_TO_BOOL(value) == fields->properties.signAlwaysShown) { return; }
+ fields->properties.signAlwaysShown = value;
touchNoError();
}
@@ -952,7 +942,7 @@ int32_t DecimalFormat::getMultiplier(void) const {
// Fallback to using the default instance of DecimalFormatProperties.
dfp = &(DecimalFormatProperties::getDefault());
} else {
- dfp = fields->properties.getAlias();
+ dfp = &fields->properties;
}
if (dfp->multiplier != 1) {
return dfp->multiplier;
@@ -984,11 +974,11 @@ void DecimalFormat::setMultiplier(int32_t multiplier) {
value = temp;
}
if (delta != -1) {
- fields->properties->magnitudeMultiplier = delta;
- fields->properties->multiplier = 1;
+ fields->properties.magnitudeMultiplier = delta;
+ fields->properties.multiplier = 1;
} else {
- fields->properties->magnitudeMultiplier = 0;
- fields->properties->multiplier = multiplier;
+ fields->properties.magnitudeMultiplier = 0;
+ fields->properties.multiplier = multiplier;
}
touchNoError();
}
@@ -999,13 +989,13 @@ int32_t DecimalFormat::getMultiplierScale() const {
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().multiplierScale;
}
- return fields->properties->multiplierScale;
+ return fields->properties.multiplierScale;
}
void DecimalFormat::setMultiplierScale(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->multiplierScale) { return; }
- fields->properties->multiplierScale = newValue;
+ if (newValue == fields->properties.multiplierScale) { return; }
+ fields->properties.multiplierScale = newValue;
touchNoError();
}
@@ -1015,13 +1005,13 @@ double DecimalFormat::getRoundingIncrement(void) const {
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().roundingIncrement;
}
- return fields->exportedProperties->roundingIncrement;
+ return fields->exportedProperties.roundingIncrement;
}
void DecimalFormat::setRoundingIncrement(double newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->roundingIncrement) { return; }
- fields->properties->roundingIncrement = newValue;
+ if (newValue == fields->properties.roundingIncrement) { return; }
+ fields->properties.roundingIncrement = newValue;
touchNoError();
}
@@ -1032,17 +1022,17 @@ ERoundingMode DecimalFormat::getRoundingMode(void) const {
return static_cast(DecimalFormatProperties::getDefault().roundingMode.getNoError());
}
// UNumberFormatRoundingMode and ERoundingMode have the same values.
- return static_cast(fields->exportedProperties->roundingMode.getNoError());
+ return static_cast(fields->exportedProperties.roundingMode.getNoError());
}
void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) {
if (fields == nullptr) { return; }
auto uRoundingMode = static_cast(roundingMode);
- if (!fields->properties->roundingMode.isNull() && uRoundingMode == fields->properties->roundingMode.getNoError()) {
+ if (!fields->properties.roundingMode.isNull() && uRoundingMode == fields->properties.roundingMode.getNoError()) {
return;
}
NumberFormat::setMaximumIntegerDigits(roundingMode); // to set field for compatibility
- fields->properties->roundingMode = uRoundingMode;
+ fields->properties.roundingMode = uRoundingMode;
touchNoError();
}
@@ -1052,52 +1042,52 @@ int32_t DecimalFormat::getFormatWidth(void) const {
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().formatWidth;
}
- return fields->properties->formatWidth;
+ return fields->properties.formatWidth;
}
void DecimalFormat::setFormatWidth(int32_t width) {
if (fields == nullptr) { return; }
- if (width == fields->properties->formatWidth) { return; }
- fields->properties->formatWidth = width;
+ if (width == fields->properties.formatWidth) { return; }
+ fields->properties.formatWidth = width;
touchNoError();
}
UnicodeString DecimalFormat::getPadCharacterString() const {
- if (fields == nullptr || fields->properties->padString.isBogus()) {
+ if (fields == nullptr || fields->properties.padString.isBogus()) {
// Readonly-alias the static string kFallbackPaddingString
return {TRUE, kFallbackPaddingString, -1};
} else {
- return fields->properties->padString;
+ return fields->properties.padString;
}
}
void DecimalFormat::setPadCharacter(const UnicodeString& padChar) {
if (fields == nullptr) { return; }
- if (padChar == fields->properties->padString) { return; }
+ if (padChar == fields->properties.padString) { return; }
if (padChar.length() > 0) {
- fields->properties->padString = UnicodeString(padChar.char32At(0));
+ fields->properties.padString = UnicodeString(padChar.char32At(0));
} else {
- fields->properties->padString.setToBogus();
+ fields->properties.padString.setToBogus();
}
touchNoError();
}
EPadPosition DecimalFormat::getPadPosition(void) const {
- if (fields == nullptr || fields->properties->padPosition.isNull()) {
+ if (fields == nullptr || fields->properties.padPosition.isNull()) {
return EPadPosition::kPadBeforePrefix;
} else {
// UNumberFormatPadPosition and EPadPosition have the same values.
- return static_cast(fields->properties->padPosition.getNoError());
+ return static_cast(fields->properties.padPosition.getNoError());
}
}
void DecimalFormat::setPadPosition(EPadPosition padPos) {
if (fields == nullptr) { return; }
auto uPadPos = static_cast(padPos);
- if (!fields->properties->padPosition.isNull() && uPadPos == fields->properties->padPosition.getNoError()) {
+ if (!fields->properties.padPosition.isNull() && uPadPos == fields->properties.padPosition.getNoError()) {
return;
}
- fields->properties->padPosition = uPadPos;
+ fields->properties.padPosition = uPadPos;
touchNoError();
}
@@ -1107,17 +1097,17 @@ UBool DecimalFormat::isScientificNotation(void) const {
// Fallback to using the default instance of DecimalFormatProperties.
return (DecimalFormatProperties::getDefault().minimumExponentDigits != -1);
}
- return (fields->properties->minimumExponentDigits != -1);
+ return (fields->properties.minimumExponentDigits != -1);
}
void DecimalFormat::setScientificNotation(UBool useScientific) {
if (fields == nullptr) { return; }
int32_t minExp = useScientific ? 1 : -1;
- if (fields->properties->minimumExponentDigits == minExp) { return; }
+ if (fields->properties.minimumExponentDigits == minExp) { return; }
if (useScientific) {
- fields->properties->minimumExponentDigits = 1;
+ fields->properties.minimumExponentDigits = 1;
} else {
- fields->properties->minimumExponentDigits = -1;
+ fields->properties.minimumExponentDigits = -1;
}
touchNoError();
}
@@ -1128,13 +1118,13 @@ int8_t DecimalFormat::getMinimumExponentDigits(void) const {
// Fallback to using the default instance of DecimalFormatProperties.
return static_cast(DecimalFormatProperties::getDefault().minimumExponentDigits);
}
- return static_cast(fields->properties->minimumExponentDigits);
+ return static_cast(fields->properties.minimumExponentDigits);
}
void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) {
if (fields == nullptr) { return; }
- if (minExpDig == fields->properties->minimumExponentDigits) { return; }
- fields->properties->minimumExponentDigits = minExpDig;
+ if (minExpDig == fields->properties.minimumExponentDigits) { return; }
+ fields->properties.minimumExponentDigits = minExpDig;
touchNoError();
}
@@ -1144,13 +1134,13 @@ UBool DecimalFormat::isExponentSignAlwaysShown(void) const {
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().exponentSignAlwaysShown;
}
- return fields->properties->exponentSignAlwaysShown;
+ return fields->properties.exponentSignAlwaysShown;
}
void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) {
if (fields == nullptr) { return; }
- if (UBOOL_TO_BOOL(expSignAlways) == fields->properties->exponentSignAlwaysShown) { return; }
- fields->properties->exponentSignAlwaysShown = expSignAlways;
+ if (UBOOL_TO_BOOL(expSignAlways) == fields->properties.exponentSignAlwaysShown) { return; }
+ fields->properties.exponentSignAlwaysShown = expSignAlways;
touchNoError();
}
@@ -1161,7 +1151,7 @@ int32_t DecimalFormat::getGroupingSize(void) const {
// Fallback to using the default instance of DecimalFormatProperties.
groupingSize = DecimalFormatProperties::getDefault().groupingSize;
} else {
- groupingSize = fields->properties->groupingSize;
+ groupingSize = fields->properties.groupingSize;
}
if (groupingSize < 0) {
return 0;
@@ -1171,8 +1161,8 @@ int32_t DecimalFormat::getGroupingSize(void) const {
void DecimalFormat::setGroupingSize(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->groupingSize) { return; }
- fields->properties->groupingSize = newValue;
+ if (newValue == fields->properties.groupingSize) { return; }
+ fields->properties.groupingSize = newValue;
touchNoError();
}
@@ -1183,7 +1173,7 @@ int32_t DecimalFormat::getSecondaryGroupingSize(void) const {
// Fallback to using the default instance of DecimalFormatProperties.
grouping2 = DecimalFormatProperties::getDefault().secondaryGroupingSize;
} else {
- grouping2 = fields->properties->secondaryGroupingSize;
+ grouping2 = fields->properties.secondaryGroupingSize;
}
if (grouping2 < 0) {
return 0;
@@ -1193,8 +1183,8 @@ int32_t DecimalFormat::getSecondaryGroupingSize(void) const {
void DecimalFormat::setSecondaryGroupingSize(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->secondaryGroupingSize) { return; }
- fields->properties->secondaryGroupingSize = newValue;
+ if (newValue == fields->properties.secondaryGroupingSize) { return; }
+ fields->properties.secondaryGroupingSize = newValue;
touchNoError();
}
@@ -1204,13 +1194,13 @@ int32_t DecimalFormat::getMinimumGroupingDigits() const {
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().minimumGroupingDigits;
}
- return fields->properties->minimumGroupingDigits;
+ return fields->properties.minimumGroupingDigits;
}
void DecimalFormat::setMinimumGroupingDigits(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->minimumGroupingDigits) { return; }
- fields->properties->minimumGroupingDigits = newValue;
+ if (newValue == fields->properties.minimumGroupingDigits) { return; }
+ fields->properties.minimumGroupingDigits = newValue;
touchNoError();
}
@@ -1220,13 +1210,13 @@ UBool DecimalFormat::isDecimalSeparatorAlwaysShown(void) const {
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().decimalSeparatorAlwaysShown;
}
- return fields->properties->decimalSeparatorAlwaysShown;
+ return fields->properties.decimalSeparatorAlwaysShown;
}
void DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue) {
if (fields == nullptr) { return; }
- if (UBOOL_TO_BOOL(newValue) == fields->properties->decimalSeparatorAlwaysShown) { return; }
- fields->properties->decimalSeparatorAlwaysShown = newValue;
+ if (UBOOL_TO_BOOL(newValue) == fields->properties.decimalSeparatorAlwaysShown) { return; }
+ fields->properties.decimalSeparatorAlwaysShown = newValue;
touchNoError();
}
@@ -1236,13 +1226,13 @@ UBool DecimalFormat::isDecimalPatternMatchRequired(void) const {
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().decimalPatternMatchRequired;
}
- return fields->properties->decimalPatternMatchRequired;
+ return fields->properties.decimalPatternMatchRequired;
}
void DecimalFormat::setDecimalPatternMatchRequired(UBool newValue) {
if (fields == nullptr) { return; }
- if (UBOOL_TO_BOOL(newValue) == fields->properties->decimalPatternMatchRequired) { return; }
- fields->properties->decimalPatternMatchRequired = newValue;
+ if (UBOOL_TO_BOOL(newValue) == fields->properties.decimalPatternMatchRequired) { return; }
+ fields->properties.decimalPatternMatchRequired = newValue;
touchNoError();
}
@@ -1252,13 +1242,13 @@ UBool DecimalFormat::isParseNoExponent() const {
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().parseNoExponent;
}
- return fields->properties->parseNoExponent;
+ return fields->properties.parseNoExponent;
}
void DecimalFormat::setParseNoExponent(UBool value) {
if (fields == nullptr) { return; }
- if (UBOOL_TO_BOOL(value) == fields->properties->parseNoExponent) { return; }
- fields->properties->parseNoExponent = value;
+ if (UBOOL_TO_BOOL(value) == fields->properties.parseNoExponent) { return; }
+ fields->properties.parseNoExponent = value;
touchNoError();
}
@@ -1268,13 +1258,13 @@ UBool DecimalFormat::isParseCaseSensitive() const {
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().parseCaseSensitive;
}
- return fields->properties->parseCaseSensitive;
+ return fields->properties.parseCaseSensitive;
}
void DecimalFormat::setParseCaseSensitive(UBool value) {
if (fields == nullptr) { return; }
- if (UBOOL_TO_BOOL(value) == fields->properties->parseCaseSensitive) { return; }
- fields->properties->parseCaseSensitive = value;
+ if (UBOOL_TO_BOOL(value) == fields->properties.parseCaseSensitive) { return; }
+ fields->properties.parseCaseSensitive = value;
touchNoError();
}
@@ -1284,13 +1274,13 @@ UBool DecimalFormat::isFormatFailIfMoreThanMaxDigits() const {
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().formatFailIfMoreThanMaxDigits;
}
- return fields->properties->formatFailIfMoreThanMaxDigits;
+ return fields->properties.formatFailIfMoreThanMaxDigits;
}
void DecimalFormat::setFormatFailIfMoreThanMaxDigits(UBool value) {
if (fields == nullptr) { return; }
- if (UBOOL_TO_BOOL(value) == fields->properties->formatFailIfMoreThanMaxDigits) { return; }
- fields->properties->formatFailIfMoreThanMaxDigits = value;
+ if (UBOOL_TO_BOOL(value) == fields->properties.formatFailIfMoreThanMaxDigits) { return; }
+ fields->properties.formatFailIfMoreThanMaxDigits = value;
touchNoError();
}
@@ -1305,7 +1295,7 @@ UnicodeString& DecimalFormat::toPattern(UnicodeString& result) const {
// so that CurrencyUsage is reflected properly.
// TODO: Consider putting this logic in number_patternstring.cpp instead.
ErrorCode localStatus;
- DecimalFormatProperties tprops(*fields->properties);
+ DecimalFormatProperties tprops(fields->properties);
bool useCurrency = (
!tprops.currency.isNull() ||
!tprops.currencyPluralInfo.fPtr.isNull() ||
@@ -1315,9 +1305,9 @@ UnicodeString& DecimalFormat::toPattern(UnicodeString& result) const {
AffixUtils::hasCurrencySymbols(tprops.negativePrefixPattern, localStatus) ||
AffixUtils::hasCurrencySymbols(tprops.negativeSuffixPattern, localStatus));
if (useCurrency) {
- tprops.minimumFractionDigits = fields->exportedProperties->minimumFractionDigits;
- tprops.maximumFractionDigits = fields->exportedProperties->maximumFractionDigits;
- tprops.roundingIncrement = fields->exportedProperties->roundingIncrement;
+ tprops.minimumFractionDigits = fields->exportedProperties.minimumFractionDigits;
+ tprops.maximumFractionDigits = fields->exportedProperties.maximumFractionDigits;
+ tprops.roundingIncrement = fields->exportedProperties.roundingIncrement;
}
result = PatternStringUtils::propertiesToPatternString(tprops, localStatus);
return result;
@@ -1373,49 +1363,53 @@ void DecimalFormat::applyLocalizedPattern(const UnicodeString& localizedPattern,
void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->maximumIntegerDigits) { return; }
+ if (newValue == fields->properties.maximumIntegerDigits) { return; }
// For backwards compatibility, conflicting min/max need to keep the most recent setting.
- int32_t min = fields->properties->minimumIntegerDigits;
+ int32_t min = fields->properties.minimumIntegerDigits;
if (min >= 0 && min > newValue) {
- fields->properties->minimumIntegerDigits = newValue;
+ fields->properties.minimumIntegerDigits = newValue;
}
- fields->properties->maximumIntegerDigits = newValue;
+ fields->properties.maximumIntegerDigits = newValue;
touchNoError();
}
void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->minimumIntegerDigits) { return; }
+ if (newValue == fields->properties.minimumIntegerDigits) { return; }
// For backwards compatibility, conflicting min/max need to keep the most recent setting.
- int32_t max = fields->properties->maximumIntegerDigits;
+ int32_t max = fields->properties.maximumIntegerDigits;
if (max >= 0 && max < newValue) {
- fields->properties->maximumIntegerDigits = newValue;
+ fields->properties.maximumIntegerDigits = newValue;
}
- fields->properties->minimumIntegerDigits = newValue;
+ fields->properties.minimumIntegerDigits = newValue;
touchNoError();
}
void DecimalFormat::setMaximumFractionDigits(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->maximumFractionDigits) { return; }
+ if (newValue == fields->properties.maximumFractionDigits) { return; }
+ // cap for backward compatibility, formerly 340, now 999
+ if (newValue > kMaxIntFracSig) {
+ newValue = kMaxIntFracSig;
+ }
// For backwards compatibility, conflicting min/max need to keep the most recent setting.
- int32_t min = fields->properties->minimumFractionDigits;
+ int32_t min = fields->properties.minimumFractionDigits;
if (min >= 0 && min > newValue) {
- fields->properties->minimumFractionDigits = newValue;
+ fields->properties.minimumFractionDigits = newValue;
}
- fields->properties->maximumFractionDigits = newValue;
+ fields->properties.maximumFractionDigits = newValue;
touchNoError();
}
void DecimalFormat::setMinimumFractionDigits(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->minimumFractionDigits) { return; }
+ if (newValue == fields->properties.minimumFractionDigits) { return; }
// For backwards compatibility, conflicting min/max need to keep the most recent setting.
- int32_t max = fields->properties->maximumFractionDigits;
+ int32_t max = fields->properties.maximumFractionDigits;
if (max >= 0 && max < newValue) {
- fields->properties->maximumFractionDigits = newValue;
+ fields->properties.maximumFractionDigits = newValue;
}
- fields->properties->minimumFractionDigits = newValue;
+ fields->properties.minimumFractionDigits = newValue;
touchNoError();
}
@@ -1425,7 +1419,7 @@ int32_t DecimalFormat::getMinimumSignificantDigits() const {
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().minimumSignificantDigits;
}
- return fields->exportedProperties->minimumSignificantDigits;
+ return fields->exportedProperties.minimumSignificantDigits;
}
int32_t DecimalFormat::getMaximumSignificantDigits() const {
@@ -1434,28 +1428,28 @@ int32_t DecimalFormat::getMaximumSignificantDigits() const {
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().maximumSignificantDigits;
}
- return fields->exportedProperties->maximumSignificantDigits;
+ return fields->exportedProperties.maximumSignificantDigits;
}
void DecimalFormat::setMinimumSignificantDigits(int32_t value) {
if (fields == nullptr) { return; }
- if (value == fields->properties->minimumSignificantDigits) { return; }
- int32_t max = fields->properties->maximumSignificantDigits;
+ if (value == fields->properties.minimumSignificantDigits) { return; }
+ int32_t max = fields->properties.maximumSignificantDigits;
if (max >= 0 && max < value) {
- fields->properties->maximumSignificantDigits = value;
+ fields->properties.maximumSignificantDigits = value;
}
- fields->properties->minimumSignificantDigits = value;
+ fields->properties.minimumSignificantDigits = value;
touchNoError();
}
void DecimalFormat::setMaximumSignificantDigits(int32_t value) {
if (fields == nullptr) { return; }
- if (value == fields->properties->maximumSignificantDigits) { return; }
- int32_t min = fields->properties->minimumSignificantDigits;
+ if (value == fields->properties.maximumSignificantDigits) { return; }
+ int32_t min = fields->properties.minimumSignificantDigits;
if (min >= 0 && min > value) {
- fields->properties->minimumSignificantDigits = value;
+ fields->properties.minimumSignificantDigits = value;
}
- fields->properties->maximumSignificantDigits = value;
+ fields->properties.maximumSignificantDigits = value;
touchNoError();
}
@@ -1466,7 +1460,7 @@ UBool DecimalFormat::areSignificantDigitsUsed() const {
// Fallback to using the default instance of DecimalFormatProperties.
dfp = &(DecimalFormatProperties::getDefault());
} else {
- dfp = fields->properties.getAlias();
+ dfp = &fields->properties;
}
return dfp->minimumSignificantDigits != -1 || dfp->maximumSignificantDigits != -1;
}
@@ -1476,20 +1470,20 @@ void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) {
// These are the default values from the old implementation.
if (useSignificantDigits) {
- if (fields->properties->minimumSignificantDigits != -1 ||
- fields->properties->maximumSignificantDigits != -1) {
+ if (fields->properties.minimumSignificantDigits != -1 ||
+ fields->properties.maximumSignificantDigits != -1) {
return;
}
} else {
- if (fields->properties->minimumSignificantDigits == -1 &&
- fields->properties->maximumSignificantDigits == -1) {
+ if (fields->properties.minimumSignificantDigits == -1 &&
+ fields->properties.maximumSignificantDigits == -1) {
return;
}
}
int32_t minSig = useSignificantDigits ? 1 : -1;
int32_t maxSig = useSignificantDigits ? 6 : -1;
- fields->properties->minimumSignificantDigits = minSig;
- fields->properties->maximumSignificantDigits = maxSig;
+ fields->properties.minimumSignificantDigits = minSig;
+ fields->properties.maximumSignificantDigits = maxSig;
touchNoError();
}
@@ -1503,11 +1497,11 @@ void DecimalFormat::setCurrency(const char16_t* theCurrency, UErrorCode& ec) {
}
CurrencyUnit currencyUnit(theCurrency, ec);
if (U_FAILURE(ec)) { return; }
- if (!fields->properties->currency.isNull() && fields->properties->currency.getNoError() == currencyUnit) {
+ if (!fields->properties.currency.isNull() && fields->properties.currency.getNoError() == currencyUnit) {
return;
}
NumberFormat::setCurrency(theCurrency, ec); // to set field for compatibility
- fields->properties->currency = currencyUnit;
+ fields->properties.currency = currencyUnit;
// TODO: Set values in fields->symbols, too?
touchNoError();
}
@@ -1525,20 +1519,20 @@ void DecimalFormat::setCurrencyUsage(UCurrencyUsage newUsage, UErrorCode* ec) {
*ec = U_MEMORY_ALLOCATION_ERROR;
return;
}
- if (!fields->properties->currencyUsage.isNull() && newUsage == fields->properties->currencyUsage.getNoError()) {
+ if (!fields->properties.currencyUsage.isNull() && newUsage == fields->properties.currencyUsage.getNoError()) {
return;
}
- fields->properties->currencyUsage = newUsage;
+ fields->properties.currencyUsage = newUsage;
touch(*ec);
}
UCurrencyUsage DecimalFormat::getCurrencyUsage() const {
// CurrencyUsage is not exported, so we have to get it from the input property bag.
// TODO: Should we export CurrencyUsage instead?
- if (fields == nullptr || fields->properties->currencyUsage.isNull()) {
+ if (fields == nullptr || fields->properties.currencyUsage.isNull()) {
return UCURR_USAGE_STANDARD;
}
- return fields->properties->currencyUsage.getNoError();
+ return fields->properties.currencyUsage.getNoError();
}
void
@@ -1550,7 +1544,7 @@ DecimalFormat::formatToDecimalQuantity(double number, DecimalQuantity& output, U
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
- fields->formatter->formatDouble(number, status).getDecimalQuantity(output, status);
+ fields->formatter.formatDouble(number, status).getDecimalQuantity(output, status);
}
void DecimalFormat::formatToDecimalQuantity(const Formattable& number, DecimalQuantity& output,
@@ -1564,7 +1558,7 @@ void DecimalFormat::formatToDecimalQuantity(const Formattable& number, DecimalQu
}
UFormattedNumberData obj;
number.populateDecimalQuantity(obj.quantity, status);
- fields->formatter->formatImpl(&obj, status);
+ fields->formatter.formatImpl(&obj, status);
output = std::move(obj.quantity);
}
@@ -1576,12 +1570,7 @@ const number::LocalizedNumberFormatter* DecimalFormat::toNumberFormatter(UErrorC
status = U_MEMORY_ALLOCATION_ERROR;
return nullptr;
}
- return &*fields->formatter;
-}
-
-const number::LocalizedNumberFormatter& DecimalFormat::toNumberFormatter() const {
- UErrorCode localStatus = U_ZERO_ERROR;
- return *toNumberFormatter(localStatus);
+ return &fields->formatter;
}
/** Rebuilds the formatter object from the property bag. */
@@ -1608,9 +1597,9 @@ void DecimalFormat::touch(UErrorCode& status) {
// Since memory has already been allocated for the formatter, we can move assign a stack-allocated object
// and don't need to call new. (Which is slower and could possibly fail).
- *fields->formatter = NumberPropertyMapper::create(
- *fields->properties, *fields->symbols, fields->warehouse, *fields->exportedProperties, status).locale(
- locale);
+ fields->formatter = NumberPropertyMapper::create(
+ fields->properties, *fields->symbols, fields->warehouse, fields->exportedProperties, status
+ ).locale(locale);
// Do this after fields->exportedProperties are set up
setupFastFormat();
@@ -1620,13 +1609,13 @@ void DecimalFormat::touch(UErrorCode& status) {
delete fields->atomicCurrencyParser.exchange(nullptr);
// In order for the getters to work, we need to populate some fields in NumberFormat.
- NumberFormat::setCurrency(fields->exportedProperties->currency.get(status).getISOCurrency(), status);
- NumberFormat::setMaximumIntegerDigits(fields->exportedProperties->maximumIntegerDigits);
- NumberFormat::setMinimumIntegerDigits(fields->exportedProperties->minimumIntegerDigits);
- NumberFormat::setMaximumFractionDigits(fields->exportedProperties->maximumFractionDigits);
- NumberFormat::setMinimumFractionDigits(fields->exportedProperties->minimumFractionDigits);
+ NumberFormat::setCurrency(fields->exportedProperties.currency.get(status).getISOCurrency(), status);
+ NumberFormat::setMaximumIntegerDigits(fields->exportedProperties.maximumIntegerDigits);
+ NumberFormat::setMinimumIntegerDigits(fields->exportedProperties.minimumIntegerDigits);
+ NumberFormat::setMaximumFractionDigits(fields->exportedProperties.maximumFractionDigits);
+ NumberFormat::setMinimumFractionDigits(fields->exportedProperties.minimumFractionDigits);
// fImpl->properties, not fields->exportedProperties, since this information comes from the pattern:
- NumberFormat::setGroupingUsed(fields->properties->groupingUsed);
+ NumberFormat::setGroupingUsed(fields->properties.groupingUsed);
}
void DecimalFormat::touchNoError() {
@@ -1639,7 +1628,7 @@ void DecimalFormat::setPropertiesFromPattern(const UnicodeString& pattern, int32
if (U_SUCCESS(status)) {
// Cast workaround to get around putting the enum in the public header file
auto actualIgnoreRounding = static_cast(ignoreRounding);
- PatternParser::parseToExistingProperties(pattern, *fields->properties, actualIgnoreRounding, status);
+ PatternParser::parseToExistingProperties(pattern, fields->properties, actualIgnoreRounding, status);
}
}
@@ -1658,7 +1647,7 @@ const numparse::impl::NumberParserImpl* DecimalFormat::getParser(UErrorCode& sta
}
// Try computing the parser on our own
- auto* temp = NumberParserImpl::createParserFromProperties(*fields->properties, *fields->symbols, false, status);
+ auto* temp = NumberParserImpl::createParserFromProperties(fields->properties, *fields->symbols, false, status);
if (U_FAILURE(status)) {
return nullptr;
}
@@ -1691,7 +1680,7 @@ const numparse::impl::NumberParserImpl* DecimalFormat::getCurrencyParser(UErrorC
}
// Try computing the parser on our own
- auto* temp = NumberParserImpl::createParserFromProperties(*fields->properties, *fields->symbols, true, status);
+ auto* temp = NumberParserImpl::createParserFromProperties(fields->properties, *fields->symbols, true, status);
if (temp == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR;
// although we may still dereference, call sites should be guarded
@@ -1739,7 +1728,7 @@ DecimalFormat::fieldPositionIteratorHelper(const number::FormattedNumber& format
void DecimalFormat::setupFastFormat() {
// Check the majority of properties:
- if (!fields->properties->equalsDefaultExceptFastFormat()) {
+ if (!fields->properties.equalsDefaultExceptFastFormat()) {
trace("no fast format: equality\n");
fields->canUseFastFormat = false;
return;
@@ -1747,12 +1736,12 @@ void DecimalFormat::setupFastFormat() {
// Now check the remaining properties.
// Nontrivial affixes:
- UBool trivialPP = fields->properties->positivePrefixPattern.isEmpty();
- UBool trivialPS = fields->properties->positiveSuffixPattern.isEmpty();
- UBool trivialNP = fields->properties->negativePrefixPattern.isBogus() || (
- fields->properties->negativePrefixPattern.length() == 1 &&
- fields->properties->negativePrefixPattern.charAt(0) == u'-');
- UBool trivialNS = fields->properties->negativeSuffixPattern.isEmpty();
+ UBool trivialPP = fields->properties.positivePrefixPattern.isEmpty();
+ UBool trivialPS = fields->properties.positiveSuffixPattern.isEmpty();
+ UBool trivialNP = fields->properties.negativePrefixPattern.isBogus() || (
+ fields->properties.negativePrefixPattern.length() == 1 &&
+ fields->properties.negativePrefixPattern.charAt(0) == u'-');
+ UBool trivialNS = fields->properties.negativeSuffixPattern.isEmpty();
if (!trivialPP || !trivialPS || !trivialNP || !trivialNS) {
trace("no fast format: affixes\n");
fields->canUseFastFormat = false;
@@ -1760,8 +1749,8 @@ void DecimalFormat::setupFastFormat() {
}
// Grouping (secondary grouping is forbidden in equalsDefaultExceptFastFormat):
- bool groupingUsed = fields->properties->groupingUsed;
- int32_t groupingSize = fields->properties->groupingSize;
+ bool groupingUsed = fields->properties.groupingUsed;
+ int32_t groupingSize = fields->properties.groupingSize;
bool unusualGroupingSize = groupingSize > 0 && groupingSize != 3;
const UnicodeString& groupingString = fields->symbols->getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
if (groupingUsed && (unusualGroupingSize || groupingString.length() != 1)) {
@@ -1771,8 +1760,8 @@ void DecimalFormat::setupFastFormat() {
}
// Integer length:
- int32_t minInt = fields->exportedProperties->minimumIntegerDigits;
- int32_t maxInt = fields->exportedProperties->maximumIntegerDigits;
+ int32_t minInt = fields->exportedProperties.minimumIntegerDigits;
+ int32_t maxInt = fields->exportedProperties.maximumIntegerDigits;
// Fastpath supports up to only 10 digits (length of INT32_MIN)
if (minInt > 10) {
trace("no fast format: integer\n");
@@ -1781,7 +1770,7 @@ void DecimalFormat::setupFastFormat() {
}
// Fraction length (no fraction part allowed in fast path):
- int32_t minFrac = fields->exportedProperties->minimumFractionDigits;
+ int32_t minFrac = fields->exportedProperties.minimumFractionDigits;
if (minFrac > 0) {
trace("no fast format: fraction\n");
fields->canUseFastFormat = false;
diff --git a/deps/icu-small/source/i18n/double-conversion-bignum-dtoa.cpp b/deps/icu-small/source/i18n/double-conversion-bignum-dtoa.cpp
index 2add399f87c91f..a95910df0421d1 100644
--- a/deps/icu-small/source/i18n/double-conversion-bignum-dtoa.cpp
+++ b/deps/icu-small/source/i18n/double-conversion-bignum-dtoa.cpp
@@ -49,7 +49,7 @@ U_NAMESPACE_BEGIN
namespace double_conversion {
static int NormalizedExponent(uint64_t significand, int exponent) {
- ASSERT(significand != 0);
+ DOUBLE_CONVERSION_ASSERT(significand != 0);
while ((significand & Double::kHiddenBit) == 0) {
significand = significand << 1;
exponent = exponent - 1;
@@ -90,26 +90,26 @@ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
// Generates 'requested_digits' after the decimal point.
static void BignumToFixed(int requested_digits, int* decimal_point,
Bignum* numerator, Bignum* denominator,
- Vector(buffer), int* length);
+ Vector buffer, int* length);
// Generates 'count' digits of numerator/denominator.
// Once 'count' digits have been produced rounds the result depending on the
// remainder (remainders of exactly .5 round upwards). Might update the
// decimal_point when rounding up (for example for 0.9999).
static void GenerateCountedDigits(int count, int* decimal_point,
Bignum* numerator, Bignum* denominator,
- Vector(buffer), int* length);
+ Vector buffer, int* length);
void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
Vector buffer, int* length, int* decimal_point) {
- ASSERT(v > 0);
- ASSERT(!Double(v).IsSpecial());
+ DOUBLE_CONVERSION_ASSERT(v > 0);
+ DOUBLE_CONVERSION_ASSERT(!Double(v).IsSpecial());
uint64_t significand;
int exponent;
bool lower_boundary_is_closer;
if (mode == BIGNUM_DTOA_SHORTEST_SINGLE) {
float f = static_cast(v);
- ASSERT(f == v);
+ DOUBLE_CONVERSION_ASSERT(f == v);
significand = Single(f).Significand();
exponent = Single(f).Exponent();
lower_boundary_is_closer = Single(f).LowerBoundaryIsCloser();
@@ -148,7 +148,7 @@ void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
// 4e-324. In this case the denominator needs fewer than 324*4 binary digits.
// The maximum double is 1.7976931348623157e308 which needs fewer than
// 308*4 binary digits.
- ASSERT(Bignum::kMaxSignificantBits >= 324*4);
+ DOUBLE_CONVERSION_ASSERT(Bignum::kMaxSignificantBits >= 324*4);
InitialScaledStartValues(significand, exponent, lower_boundary_is_closer,
estimated_power, need_boundary_deltas,
&numerator, &denominator,
@@ -177,7 +177,7 @@ void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
buffer, length);
break;
default:
- UNREACHABLE();
+ DOUBLE_CONVERSION_UNREACHABLE();
}
buffer[*length] = '\0';
}
@@ -209,7 +209,7 @@ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
for (;;) {
uint16_t digit;
digit = numerator->DivideModuloIntBignum(*denominator);
- ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
+ DOUBLE_CONVERSION_ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
// digit = numerator / denominator (integer division).
// numerator = numerator % denominator.
buffer[(*length)++] = static_cast(digit + '0');
@@ -255,7 +255,7 @@ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
// loop would have stopped earlier.
// We still have an assert here in case the preconditions were not
// satisfied.
- ASSERT(buffer[(*length) - 1] != '9');
+ DOUBLE_CONVERSION_ASSERT(buffer[(*length) - 1] != '9');
buffer[(*length) - 1]++;
} else {
// Halfway case.
@@ -266,7 +266,7 @@ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
if ((buffer[(*length) - 1] - '0') % 2 == 0) {
// Round down => Do nothing.
} else {
- ASSERT(buffer[(*length) - 1] != '9');
+ DOUBLE_CONVERSION_ASSERT(buffer[(*length) - 1] != '9');
buffer[(*length) - 1]++;
}
}
@@ -278,9 +278,9 @@ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
// Round up.
// Note again that the last digit could not be '9' since this would have
// stopped the loop earlier.
- // We still have an ASSERT here, in case the preconditions were not
+ // We still have an DOUBLE_CONVERSION_ASSERT here, in case the preconditions were not
// satisfied.
- ASSERT(buffer[(*length) -1] != '9');
+ DOUBLE_CONVERSION_ASSERT(buffer[(*length) -1] != '9');
buffer[(*length) - 1]++;
return;
}
@@ -297,11 +297,11 @@ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
static void GenerateCountedDigits(int count, int* decimal_point,
Bignum* numerator, Bignum* denominator,
Vector buffer, int* length) {
- ASSERT(count >= 0);
+ DOUBLE_CONVERSION_ASSERT(count >= 0);
for (int i = 0; i < count - 1; ++i) {
uint16_t digit;
digit = numerator->DivideModuloIntBignum(*denominator);
- ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
+ DOUBLE_CONVERSION_ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
// digit = numerator / denominator (integer division).
// numerator = numerator % denominator.
buffer[i] = static_cast(digit + '0');
@@ -314,7 +314,7 @@ static void GenerateCountedDigits(int count, int* decimal_point,
if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
digit++;
}
- ASSERT(digit <= 10);
+ DOUBLE_CONVERSION_ASSERT(digit <= 10);
buffer[count - 1] = static_cast(digit + '0');
// Correct bad digits (in case we had a sequence of '9's). Propagate the
// carry until we hat a non-'9' or til we reach the first digit.
@@ -339,7 +339,7 @@ static void GenerateCountedDigits(int count, int* decimal_point,
// Input verifies: 1 <= (numerator + delta) / denominator < 10.
static void BignumToFixed(int requested_digits, int* decimal_point,
Bignum* numerator, Bignum* denominator,
- Vector(buffer), int* length) {
+ Vector buffer, int* length) {
// Note that we have to look at more than just the requested_digits, since
// a number could be rounded up. Example: v=0.5 with requested_digits=0.
// Even though the power of v equals 0 we can't just stop here.
@@ -355,7 +355,7 @@ static void BignumToFixed(int requested_digits, int* decimal_point,
} else if (-(*decimal_point) == requested_digits) {
// We only need to verify if the number rounds down or up.
// Ex: 0.04 and 0.06 with requested_digits == 1.
- ASSERT(*decimal_point == -requested_digits);
+ DOUBLE_CONVERSION_ASSERT(*decimal_point == -requested_digits);
// Initially the fraction lies in range (1, 10]. Multiply the denominator
// by 10 so that we can compare more easily.
denominator->Times10();
@@ -434,7 +434,7 @@ static void InitialScaledStartValuesPositiveExponent(
Bignum* numerator, Bignum* denominator,
Bignum* delta_minus, Bignum* delta_plus) {
// A positive exponent implies a positive power.
- ASSERT(estimated_power >= 0);
+ DOUBLE_CONVERSION_ASSERT(estimated_power >= 0);
// Since the estimated_power is positive we simply multiply the denominator
// by 10^estimated_power.
@@ -520,7 +520,7 @@ static void InitialScaledStartValuesNegativeExponentNegativePower(
// numerator = v * 10^-estimated_power * 2 * 2^-exponent.
// Remember: numerator has been abused as power_ten. So no need to assign it
// to itself.
- ASSERT(numerator == power_ten);
+ DOUBLE_CONVERSION_ASSERT(numerator == power_ten);
numerator->MultiplyByUInt64(significand);
// denominator = 2 * 2^-exponent with exponent < 0.
diff --git a/deps/icu-small/source/i18n/double-conversion-bignum.cpp b/deps/icu-small/source/i18n/double-conversion-bignum.cpp
index 5356923921c3c1..996d75c9f60a14 100644
--- a/deps/icu-small/source/i18n/double-conversion-bignum.cpp
+++ b/deps/icu-small/source/i18n/double-conversion-bignum.cpp
@@ -34,6 +34,9 @@
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
+#include
+#include
+
// ICU PATCH: Customize header file paths for ICU.
#include "double-conversion-bignum.h"
@@ -44,136 +47,129 @@ U_NAMESPACE_BEGIN
namespace double_conversion {
-Bignum::Bignum()
- : bigits_buffer_(), bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
- for (int i = 0; i < kBigitCapacity; ++i) {
- bigits_[i] = 0;
- }
+Bignum::Chunk& Bignum::RawBigit(const int index) {
+ DOUBLE_CONVERSION_ASSERT(static_cast(index) < kBigitCapacity);
+ return bigits_buffer_[index];
+}
+
+
+const Bignum::Chunk& Bignum::RawBigit(const int index) const {
+ DOUBLE_CONVERSION_ASSERT(static_cast(index) < kBigitCapacity);
+ return bigits_buffer_[index];
}
template
-static int BitSize(S value) {
+static int BitSize(const S value) {
(void) value; // Mark variable as used.
return 8 * sizeof(value);
}
// Guaranteed to lie in one Bigit.
-void Bignum::AssignUInt16(uint16_t value) {
- ASSERT(kBigitSize >= BitSize(value));
+void Bignum::AssignUInt16(const uint16_t value) {
+ DOUBLE_CONVERSION_ASSERT(kBigitSize >= BitSize(value));
Zero();
- if (value == 0) return;
-
- EnsureCapacity(1);
- bigits_[0] = value;
- used_digits_ = 1;
+ if (value > 0) {
+ RawBigit(0) = value;
+ used_bigits_ = 1;
+ }
}
void Bignum::AssignUInt64(uint64_t value) {
- const int kUInt64Size = 64;
-
Zero();
- if (value == 0) return;
-
- int needed_bigits = kUInt64Size / kBigitSize + 1;
- EnsureCapacity(needed_bigits);
- for (int i = 0; i < needed_bigits; ++i) {
- bigits_[i] = value & kBigitMask;
- value = value >> kBigitSize;
+ for(int i = 0; value > 0; ++i) {
+ RawBigit(i) = value & kBigitMask;
+ value >>= kBigitSize;
+ ++used_bigits_;
}
- used_digits_ = needed_bigits;
- Clamp();
}
void Bignum::AssignBignum(const Bignum& other) {
exponent_ = other.exponent_;
- for (int i = 0; i < other.used_digits_; ++i) {
- bigits_[i] = other.bigits_[i];
+ for (int i = 0; i < other.used_bigits_; ++i) {
+ RawBigit(i) = other.RawBigit(i);
}
- // Clear the excess digits (if there were any).
- for (int i = other.used_digits_; i < used_digits_; ++i) {
- bigits_[i] = 0;
- }
- used_digits_ = other.used_digits_;
+ used_bigits_ = other.used_bigits_;
}
-static uint64_t ReadUInt64(Vector buffer,
- int from,
- int digits_to_read) {
+static uint64_t ReadUInt64(const Vector buffer,
+ const int from,
+ const int digits_to_read) {
uint64_t result = 0;
for (int i = from; i < from + digits_to_read; ++i) {
- int digit = buffer[i] - '0';
- ASSERT(0 <= digit && digit <= 9);
+ const int digit = buffer[i] - '0';
+ DOUBLE_CONVERSION_ASSERT(0 <= digit && digit <= 9);
result = result * 10 + digit;
}
return result;
}
-void Bignum::AssignDecimalString(Vector value) {
+void Bignum::AssignDecimalString(const Vector value) {
// 2^64 = 18446744073709551616 > 10^19
- const int kMaxUint64DecimalDigits = 19;
+ static const int kMaxUint64DecimalDigits = 19;
Zero();
int length = value.length();
- unsigned int pos = 0;
+ unsigned pos = 0;
// Let's just say that each digit needs 4 bits.
while (length >= kMaxUint64DecimalDigits) {
- uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits);
+ const uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits);
pos += kMaxUint64DecimalDigits;
length -= kMaxUint64DecimalDigits;
MultiplyByPowerOfTen(kMaxUint64DecimalDigits);
AddUInt64(digits);
}
- uint64_t digits = ReadUInt64(value, pos, length);
+ const uint64_t digits = ReadUInt64(value, pos, length);
MultiplyByPowerOfTen(length);
AddUInt64(digits);
Clamp();
}
-static int HexCharValue(char c) {
- if ('0' <= c && c <= '9') return c - '0';
- if ('a' <= c && c <= 'f') return 10 + c - 'a';
- ASSERT('A' <= c && c <= 'F');
+static uint64_t HexCharValue(const int c) {
+ if ('0' <= c && c <= '9') {
+ return c - '0';
+ }
+ if ('a' <= c && c <= 'f') {
+ return 10 + c - 'a';
+ }
+ DOUBLE_CONVERSION_ASSERT('A' <= c && c <= 'F');
return 10 + c - 'A';
}
+// Unlike AssignDecimalString(), this function is "only" used
+// for unit-tests and therefore not performance critical.
void Bignum::AssignHexString(Vector value) {
Zero();
- int length = value.length();
-
- int needed_bigits = length * 4 / kBigitSize + 1;
- EnsureCapacity(needed_bigits);
- int string_index = length - 1;
- for (int i = 0; i < needed_bigits - 1; ++i) {
- // These bigits are guaranteed to be "full".
- Chunk current_bigit = 0;
- for (int j = 0; j < kBigitSize / 4; j++) {
- current_bigit += HexCharValue(value[string_index--]) << (j * 4);
+ // Required capacity could be reduced by ignoring leading zeros.
+ EnsureCapacity(((value.length() * 4) + kBigitSize - 1) / kBigitSize);
+ DOUBLE_CONVERSION_ASSERT(sizeof(uint64_t) * 8 >= kBigitSize + 4); // TODO: static_assert
+ // Accumulates converted hex digits until at least kBigitSize bits.
+ // Works with non-factor-of-four kBigitSizes.
+ uint64_t tmp = 0; // Accumulates converted hex digits until at least
+ for (int cnt = 0; !value.is_empty(); value.pop_back()) {
+ tmp |= (HexCharValue(value.last()) << cnt);
+ if ((cnt += 4) >= kBigitSize) {
+ RawBigit(used_bigits_++) = (tmp & kBigitMask);
+ cnt -= kBigitSize;
+ tmp >>= kBigitSize;
}
- bigits_[i] = current_bigit;
- }
- used_digits_ = needed_bigits - 1;
-
- Chunk most_significant_bigit = 0; // Could be = 0;
- for (int j = 0; j <= string_index; ++j) {
- most_significant_bigit <<= 4;
- most_significant_bigit += HexCharValue(value[j]);
}
- if (most_significant_bigit != 0) {
- bigits_[used_digits_] = most_significant_bigit;
- used_digits_++;
+ if (tmp > 0) {
+ RawBigit(used_bigits_++) = tmp;
}
Clamp();
}
-void Bignum::AddUInt64(uint64_t operand) {
- if (operand == 0) return;
+void Bignum::AddUInt64(const uint64_t operand) {
+ if (operand == 0) {
+ return;
+ }
Bignum other;
other.AssignUInt64(operand);
AddBignum(other);
@@ -181,8 +177,8 @@ void Bignum::AddUInt64(uint64_t operand) {
void Bignum::AddBignum(const Bignum& other) {
- ASSERT(IsClamped());
- ASSERT(other.IsClamped());
+ DOUBLE_CONVERSION_ASSERT(IsClamped());
+ DOUBLE_CONVERSION_ASSERT(other.IsClamped());
// If this has a greater exponent than other append zero-bigits to this.
// After this call exponent_ <= other.exponent_.
@@ -200,48 +196,52 @@ void Bignum::AddBignum(const Bignum& other) {
// cccccccccccc 0000
// In both cases we might need a carry bigit.
- EnsureCapacity(1 + Max(BigitLength(), other.BigitLength()) - exponent_);
+ EnsureCapacity(1 + (std::max)(BigitLength(), other.BigitLength()) - exponent_);
Chunk carry = 0;
int bigit_pos = other.exponent_ - exponent_;
- ASSERT(bigit_pos >= 0);
- for (int i = 0; i < other.used_digits_; ++i) {
- Chunk sum = bigits_[bigit_pos] + other.bigits_[i] + carry;
- bigits_[bigit_pos] = sum & kBigitMask;
+ DOUBLE_CONVERSION_ASSERT(bigit_pos >= 0);
+ for (int i = used_bigits_; i < bigit_pos; ++i) {
+ RawBigit(i) = 0;
+ }
+ for (int i = 0; i < other.used_bigits_; ++i) {
+ const Chunk my = (bigit_pos < used_bigits_) ? RawBigit(bigit_pos) : 0;
+ const Chunk sum = my + other.RawBigit(i) + carry;
+ RawBigit(bigit_pos) = sum & kBigitMask;
carry = sum >> kBigitSize;
- bigit_pos++;
+ ++bigit_pos;
}
-
while (carry != 0) {
- Chunk sum = bigits_[bigit_pos] + carry;
- bigits_[bigit_pos] = sum & kBigitMask;
+ const Chunk my = (bigit_pos < used_bigits_) ? RawBigit(bigit_pos) : 0;
+ const Chunk sum = my + carry;
+ RawBigit(bigit_pos) = sum & kBigitMask;
carry = sum >> kBigitSize;
- bigit_pos++;
+ ++bigit_pos;
}
- used_digits_ = Max(bigit_pos, used_digits_);
- ASSERT(IsClamped());
+ used_bigits_ = (std::max)(bigit_pos, static_cast(used_bigits_));
+ DOUBLE_CONVERSION_ASSERT(IsClamped());
}
void Bignum::SubtractBignum(const Bignum& other) {
- ASSERT(IsClamped());
- ASSERT(other.IsClamped());
+ DOUBLE_CONVERSION_ASSERT(IsClamped());
+ DOUBLE_CONVERSION_ASSERT(other.IsClamped());
// We require this to be bigger than other.
- ASSERT(LessEqual(other, *this));
+ DOUBLE_CONVERSION_ASSERT(LessEqual(other, *this));
Align(other);
- int offset = other.exponent_ - exponent_;
+ const int offset = other.exponent_ - exponent_;
Chunk borrow = 0;
int i;
- for (i = 0; i < other.used_digits_; ++i) {
- ASSERT((borrow == 0) || (borrow == 1));
- Chunk difference = bigits_[i + offset] - other.bigits_[i] - borrow;
- bigits_[i + offset] = difference & kBigitMask;
+ for (i = 0; i < other.used_bigits_; ++i) {
+ DOUBLE_CONVERSION_ASSERT((borrow == 0) || (borrow == 1));
+ const Chunk difference = RawBigit(i + offset) - other.RawBigit(i) - borrow;
+ RawBigit(i + offset) = difference & kBigitMask;
borrow = difference >> (kChunkSize - 1);
}
while (borrow != 0) {
- Chunk difference = bigits_[i + offset] - borrow;
- bigits_[i + offset] = difference & kBigitMask;
+ const Chunk difference = RawBigit(i + offset) - borrow;
+ RawBigit(i + offset) = difference & kBigitMask;
borrow = difference >> (kChunkSize - 1);
++i;
}
@@ -249,91 +249,105 @@ void Bignum::SubtractBignum(const Bignum& other) {
}
-void Bignum::ShiftLeft(int shift_amount) {
- if (used_digits_ == 0) return;
- exponent_ += shift_amount / kBigitSize;
- int local_shift = shift_amount % kBigitSize;
- EnsureCapacity(used_digits_ + 1);
+void Bignum::ShiftLeft(const int shift_amount) {
+ if (used_bigits_ == 0) {
+ return;
+ }
+ exponent_ += (shift_amount / kBigitSize);
+ const int local_shift = shift_amount % kBigitSize;
+ EnsureCapacity(used_bigits_ + 1);
BigitsShiftLeft(local_shift);
}
-void Bignum::MultiplyByUInt32(uint32_t factor) {
- if (factor == 1) return;
+void Bignum::MultiplyByUInt32(const uint32_t factor) {
+ if (factor == 1) {
+ return;
+ }
if (factor == 0) {
Zero();
return;
}
- if (used_digits_ == 0) return;
-
+ if (used_bigits_ == 0) {
+ return;
+ }
// The product of a bigit with the factor is of size kBigitSize + 32.
// Assert that this number + 1 (for the carry) fits into double chunk.
- ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1);
+ DOUBLE_CONVERSION_ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1);
DoubleChunk carry = 0;
- for (int i = 0; i < used_digits_; ++i) {
- DoubleChunk product = static_cast(factor) * bigits_[i] + carry;
- bigits_[i] = static_cast(product & kBigitMask);
+ for (int i = 0; i < used_bigits_; ++i) {
+ const DoubleChunk product = static_cast(factor) * RawBigit(i) + carry;
+ RawBigit(i) = static_cast(product & kBigitMask);
carry = (product >> kBigitSize);
}
while (carry != 0) {
- EnsureCapacity(used_digits_ + 1);
- bigits_[used_digits_] = carry & kBigitMask;
- used_digits_++;
+ EnsureCapacity(used_bigits_ + 1);
+ RawBigit(used_bigits_) = carry & kBigitMask;
+ used_bigits_++;
carry >>= kBigitSize;
}
}
-void Bignum::MultiplyByUInt64(uint64_t factor) {
- if (factor == 1) return;
+void Bignum::MultiplyByUInt64(const uint64_t factor) {
+ if (factor == 1) {
+ return;
+ }
if (factor == 0) {
Zero();
return;
}
- ASSERT(kBigitSize < 32);
+ if (used_bigits_ == 0) {
+ return;
+ }
+ DOUBLE_CONVERSION_ASSERT(kBigitSize < 32);
uint64_t carry = 0;
- uint64_t low = factor & 0xFFFFFFFF;
- uint64_t high = factor >> 32;
- for (int i = 0; i < used_digits_; ++i) {
- uint64_t product_low = low * bigits_[i];
- uint64_t product_high = high * bigits_[i];
- uint64_t tmp = (carry & kBigitMask) + product_low;
- bigits_[i] = tmp & kBigitMask;
+ const uint64_t low = factor & 0xFFFFFFFF;
+ const uint64_t high = factor >> 32;
+ for (int i = 0; i < used_bigits_; ++i) {
+ const uint64_t product_low = low * RawBigit(i);
+ const uint64_t product_high = high * RawBigit(i);
+ const uint64_t tmp = (carry & kBigitMask) + product_low;
+ RawBigit(i) = tmp & kBigitMask;
carry = (carry >> kBigitSize) + (tmp >> kBigitSize) +
(product_high << (32 - kBigitSize));
}
while (carry != 0) {
- EnsureCapacity(used_digits_ + 1);
- bigits_[used_digits_] = carry & kBigitMask;
- used_digits_++;
+ EnsureCapacity(used_bigits_ + 1);
+ RawBigit(used_bigits_) = carry & kBigitMask;
+ used_bigits_++;
carry >>= kBigitSize;
}
}
-void Bignum::MultiplyByPowerOfTen(int exponent) {
- const uint64_t kFive27 = UINT64_2PART_C(0x6765c793, fa10079d);
- const uint16_t kFive1 = 5;
- const uint16_t kFive2 = kFive1 * 5;
- const uint16_t kFive3 = kFive2 * 5;
- const uint16_t kFive4 = kFive3 * 5;
- const uint16_t kFive5 = kFive4 * 5;
- const uint16_t kFive6 = kFive5 * 5;
- const uint32_t kFive7 = kFive6 * 5;
- const uint32_t kFive8 = kFive7 * 5;
- const uint32_t kFive9 = kFive8 * 5;
- const uint32_t kFive10 = kFive9 * 5;
- const uint32_t kFive11 = kFive10 * 5;
- const uint32_t kFive12 = kFive11 * 5;
- const uint32_t kFive13 = kFive12 * 5;
- const uint32_t kFive1_to_12[] =
+void Bignum::MultiplyByPowerOfTen(const int exponent) {
+ static const uint64_t kFive27 = DOUBLE_CONVERSION_UINT64_2PART_C(0x6765c793, fa10079d);
+ static const uint16_t kFive1 = 5;
+ static const uint16_t kFive2 = kFive1 * 5;
+ static const uint16_t kFive3 = kFive2 * 5;
+ static const uint16_t kFive4 = kFive3 * 5;
+ static const uint16_t kFive5 = kFive4 * 5;
+ static const uint16_t kFive6 = kFive5 * 5;
+ static const uint32_t kFive7 = kFive6 * 5;
+ static const uint32_t kFive8 = kFive7 * 5;
+ static const uint32_t kFive9 = kFive8 * 5;
+ static const uint32_t kFive10 = kFive9 * 5;
+ static const uint32_t kFive11 = kFive10 * 5;
+ static const uint32_t kFive12 = kFive11 * 5;
+ static const uint32_t kFive13 = kFive12 * 5;
+ static const uint32_t kFive1_to_12[] =
{ kFive1, kFive2, kFive3, kFive4, kFive5, kFive6,
kFive7, kFive8, kFive9, kFive10, kFive11, kFive12 };
- ASSERT(exponent >= 0);
- if (exponent == 0) return;
- if (used_digits_ == 0) return;
+ DOUBLE_CONVERSION_ASSERT(exponent >= 0);
+ if (exponent == 0) {
+ return;
+ }
+ if (used_bigits_ == 0) {
+ return;
+ }
// We shift by exponent at the end just before returning.
int remaining_exponent = exponent;
while (remaining_exponent >= 27) {
@@ -352,8 +366,8 @@ void Bignum::MultiplyByPowerOfTen(int exponent) {
void Bignum::Square() {
- ASSERT(IsClamped());
- int product_length = 2 * used_digits_;
+ DOUBLE_CONVERSION_ASSERT(IsClamped());
+ const int product_length = 2 * used_bigits_;
EnsureCapacity(product_length);
// Comba multiplication: compute each column separately.
@@ -368,64 +382,64 @@ void Bignum::Square() {
//
// Assert that the additional number of bits in a DoubleChunk are enough to
// sum up used_digits of Bigit*Bigit.
- if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_digits_) {
- UNIMPLEMENTED();
+ if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_bigits_) {
+ DOUBLE_CONVERSION_UNIMPLEMENTED();
}
DoubleChunk accumulator = 0;
// First shift the digits so we don't overwrite them.
- int copy_offset = used_digits_;
- for (int i = 0; i < used_digits_; ++i) {
- bigits_[copy_offset + i] = bigits_[i];
+ const int copy_offset = used_bigits_;
+ for (int i = 0; i < used_bigits_; ++i) {
+ RawBigit(copy_offset + i) = RawBigit(i);
}
// We have two loops to avoid some 'if's in the loop.
- for (int i = 0; i < used_digits_; ++i) {
+ for (int i = 0; i < used_bigits_; ++i) {
// Process temporary digit i with power i.
// The sum of the two indices must be equal to i.
int bigit_index1 = i;
int bigit_index2 = 0;
// Sum all of the sub-products.
while (bigit_index1 >= 0) {
- Chunk chunk1 = bigits_[copy_offset + bigit_index1];
- Chunk chunk2 = bigits_[copy_offset + bigit_index2];
+ const Chunk chunk1 = RawBigit(copy_offset + bigit_index1);
+ const Chunk chunk2 = RawBigit(copy_offset + bigit_index2);
accumulator += static_cast(chunk1) * chunk2;
bigit_index1--;
bigit_index2++;
}
- bigits_[i] = static_cast(accumulator) & kBigitMask;
+ RawBigit(i) = static_cast(accumulator) & kBigitMask;
accumulator >>= kBigitSize;
}
- for (int i = used_digits_; i < product_length; ++i) {
- int bigit_index1 = used_digits_ - 1;
+ for (int i = used_bigits_; i < product_length; ++i) {
+ int bigit_index1 = used_bigits_ - 1;
int bigit_index2 = i - bigit_index1;
// Invariant: sum of both indices is again equal to i.
// Inner loop runs 0 times on last iteration, emptying accumulator.
- while (bigit_index2 < used_digits_) {
- Chunk chunk1 = bigits_[copy_offset + bigit_index1];
- Chunk chunk2 = bigits_[copy_offset + bigit_index2];
+ while (bigit_index2 < used_bigits_) {
+ const Chunk chunk1 = RawBigit(copy_offset + bigit_index1);
+ const Chunk chunk2 = RawBigit(copy_offset + bigit_index2);
accumulator += static_cast(chunk1) * chunk2;
bigit_index1--;
bigit_index2++;
}
- // The overwritten bigits_[i] will never be read in further loop iterations,
+ // The overwritten RawBigit(i) will never be read in further loop iterations,
// because bigit_index1 and bigit_index2 are always greater
- // than i - used_digits_.
- bigits_[i] = static_cast(accumulator) & kBigitMask;
+ // than i - used_bigits_.
+ RawBigit(i) = static_cast(accumulator) & kBigitMask;
accumulator >>= kBigitSize;
}
// Since the result was guaranteed to lie inside the number the
// accumulator must be 0 now.
- ASSERT(accumulator == 0);
+ DOUBLE_CONVERSION_ASSERT(accumulator == 0);
// Don't forget to update the used_digits and the exponent.
- used_digits_ = product_length;
+ used_bigits_ = product_length;
exponent_ *= 2;
Clamp();
}
-void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {
- ASSERT(base != 0);
- ASSERT(power_exponent >= 0);
+void Bignum::AssignPowerUInt16(uint16_t base, const int power_exponent) {
+ DOUBLE_CONVERSION_ASSERT(base != 0);
+ DOUBLE_CONVERSION_ASSERT(power_exponent >= 0);
if (power_exponent == 0) {
AssignUInt16(1);
return;
@@ -445,7 +459,7 @@ void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {
tmp_base >>= 1;
bit_size++;
}
- int final_size = bit_size * power_exponent;
+ const int final_size = bit_size * power_exponent;
// 1 extra bigit for the shifting, and one for rounded final_size.
EnsureCapacity(final_size / kBigitSize + 2);
@@ -466,10 +480,10 @@ void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {
// Verify that there is enough space in this_value to perform the
// multiplication. The first bit_size bits must be 0.
if ((power_exponent & mask) != 0) {
- ASSERT(bit_size > 0);
- uint64_t base_bits_mask =
- ~((static_cast(1) << (64 - bit_size)) - 1);
- bool high_bits_zero = (this_value & base_bits_mask) == 0;
+ DOUBLE_CONVERSION_ASSERT(bit_size > 0);
+ const uint64_t base_bits_mask =
+ ~((static_cast(1) << (64 - bit_size)) - 1);
+ const bool high_bits_zero = (this_value & base_bits_mask) == 0;
if (high_bits_zero) {
this_value *= base;
} else {
@@ -499,9 +513,9 @@ void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {
// Precondition: this/other < 16bit.
uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) {
- ASSERT(IsClamped());
- ASSERT(other.IsClamped());
- ASSERT(other.used_digits_ > 0);
+ DOUBLE_CONVERSION_ASSERT(IsClamped());
+ DOUBLE_CONVERSION_ASSERT(other.IsClamped());
+ DOUBLE_CONVERSION_ASSERT(other.used_bigits_ > 0);
// Easy case: if we have less digits than the divisor than the result is 0.
// Note: this handles the case where this == 0, too.
@@ -519,34 +533,34 @@ uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) {
// This naive approach is extremely inefficient if `this` divided by other
// is big. This function is implemented for doubleToString where
// the result should be small (less than 10).
- ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16));
- ASSERT(bigits_[used_digits_ - 1] < 0x10000);
+ DOUBLE_CONVERSION_ASSERT(other.RawBigit(other.used_bigits_ - 1) >= ((1 << kBigitSize) / 16));
+ DOUBLE_CONVERSION_ASSERT(RawBigit(used_bigits_ - 1) < 0x10000);
// Remove the multiples of the first digit.
// Example this = 23 and other equals 9. -> Remove 2 multiples.
- result += static_cast(bigits_[used_digits_ - 1]);
- SubtractTimes(other, bigits_[used_digits_ - 1]);
+ result += static_cast(RawBigit(used_bigits_ - 1));
+ SubtractTimes(other, RawBigit(used_bigits_ - 1));
}
- ASSERT(BigitLength() == other.BigitLength());
+ DOUBLE_CONVERSION_ASSERT(BigitLength() == other.BigitLength());
// Both bignums are at the same length now.
// Since other has more than 0 digits we know that the access to
- // bigits_[used_digits_ - 1] is safe.
- Chunk this_bigit = bigits_[used_digits_ - 1];
- Chunk other_bigit = other.bigits_[other.used_digits_ - 1];
+ // RawBigit(used_bigits_ - 1) is safe.
+ const Chunk this_bigit = RawBigit(used_bigits_ - 1);
+ const Chunk other_bigit = other.RawBigit(other.used_bigits_ - 1);
- if (other.used_digits_ == 1) {
+ if (other.used_bigits_ == 1) {
// Shortcut for easy (and common) case.
int quotient = this_bigit / other_bigit;
- bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient;
- ASSERT(quotient < 0x10000);
+ RawBigit(used_bigits_ - 1) = this_bigit - other_bigit * quotient;
+ DOUBLE_CONVERSION_ASSERT(quotient < 0x10000);
result += static_cast(quotient);
Clamp();
return result;
}
- int division_estimate = this_bigit / (other_bigit + 1);
- ASSERT(division_estimate < 0x10000);
+ const int division_estimate = this_bigit / (other_bigit + 1);
+ DOUBLE_CONVERSION_ASSERT(division_estimate < 0x10000);
result += static_cast(division_estimate);
SubtractTimes(other, division_estimate);
@@ -566,7 +580,7 @@ uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) {
template
static int SizeInHexChars(S number) {
- ASSERT(number > 0);
+ DOUBLE_CONVERSION_ASSERT(number > 0);
int result = 0;
while (number != 0) {
number >>= 4;
@@ -576,29 +590,35 @@ static int SizeInHexChars(S number) {
}
-static char HexCharOfValue(int value) {
- ASSERT(0 <= value && value <= 16);
- if (value < 10) return static_cast(value + '0');
+static char HexCharOfValue(const int value) {
+ DOUBLE_CONVERSION_ASSERT(0 <= value && value <= 16);
+ if (value < 10) {
+ return static_cast(value + '0');
+ }
return static_cast(value - 10 + 'A');
}
-bool Bignum::ToHexString(char* buffer, int buffer_size) const {
- ASSERT(IsClamped());
+bool Bignum::ToHexString(char* buffer, const int buffer_size) const {
+ DOUBLE_CONVERSION_ASSERT(IsClamped());
// Each bigit must be printable as separate hex-character.
- ASSERT(kBigitSize % 4 == 0);
- const int kHexCharsPerBigit = kBigitSize / 4;
+ DOUBLE_CONVERSION_ASSERT(kBigitSize % 4 == 0);
+ static const int kHexCharsPerBigit = kBigitSize / 4;
- if (used_digits_ == 0) {
- if (buffer_size < 2) return false;
+ if (used_bigits_ == 0) {
+ if (buffer_size < 2) {
+ return false;
+ }
buffer[0] = '0';
buffer[1] = '\0';
return true;
}
// We add 1 for the terminating '\0' character.
- int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit +
- SizeInHexChars(bigits_[used_digits_ - 1]) + 1;
- if (needed_chars > buffer_size) return false;
+ const int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit +
+ SizeInHexChars(RawBigit(used_bigits_ - 1)) + 1;
+ if (needed_chars > buffer_size) {
+ return false;
+ }
int string_index = needed_chars - 1;
buffer[string_index--] = '\0';
for (int i = 0; i < exponent_; ++i) {
@@ -606,15 +626,15 @@ bool Bignum::ToHexString(char* buffer, int buffer_size) const {
buffer[string_index--] = '0';
}
}
- for (int i = 0; i < used_digits_ - 1; ++i) {
- Chunk current_bigit = bigits_[i];
+ for (int i = 0; i < used_bigits_ - 1; ++i) {
+ Chunk current_bigit = RawBigit(i);
for (int j = 0; j < kHexCharsPerBigit; ++j) {
buffer[string_index--] = HexCharOfValue(current_bigit & 0xF);
current_bigit >>= 4;
}
}
// And finally the last bigit.
- Chunk most_significant_bigit = bigits_[used_digits_ - 1];
+ Chunk most_significant_bigit = RawBigit(used_bigits_ - 1);
while (most_significant_bigit != 0) {
buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF);
most_significant_bigit >>= 4;
@@ -623,25 +643,37 @@ bool Bignum::ToHexString(char* buffer, int buffer_size) const {
}
-Bignum::Chunk Bignum::BigitAt(int index) const {
- if (index >= BigitLength()) return 0;
- if (index < exponent_) return 0;
- return bigits_[index - exponent_];
+Bignum::Chunk Bignum::BigitOrZero(const int index) const {
+ if (index >= BigitLength()) {
+ return 0;
+ }
+ if (index < exponent_) {
+ return 0;
+ }
+ return RawBigit(index - exponent_);
}
int Bignum::Compare(const Bignum& a, const Bignum& b) {
- ASSERT(a.IsClamped());
- ASSERT(b.IsClamped());
- int bigit_length_a = a.BigitLength();
- int bigit_length_b = b.BigitLength();
- if (bigit_length_a < bigit_length_b) return -1;
- if (bigit_length_a > bigit_length_b) return +1;
- for (int i = bigit_length_a - 1; i >= Min(a.exponent_, b.exponent_); --i) {
- Chunk bigit_a = a.BigitAt(i);
- Chunk bigit_b = b.BigitAt(i);
- if (bigit_a < bigit_b) return -1;
- if (bigit_a > bigit_b) return +1;
+ DOUBLE_CONVERSION_ASSERT(a.IsClamped());
+ DOUBLE_CONVERSION_ASSERT(b.IsClamped());
+ const int bigit_length_a = a.BigitLength();
+ const int bigit_length_b = b.BigitLength();
+ if (bigit_length_a < bigit_length_b) {
+ return -1;
+ }
+ if (bigit_length_a > bigit_length_b) {
+ return +1;
+ }
+ for (int i = bigit_length_a - 1; i >= (std::min)(a.exponent_, b.exponent_); --i) {
+ const Chunk bigit_a = a.BigitOrZero(i);
+ const Chunk bigit_b = b.BigitOrZero(i);
+ if (bigit_a < bigit_b) {
+ return -1;
+ }
+ if (bigit_a > bigit_b) {
+ return +1;
+ }
// Otherwise they are equal up to this digit. Try the next digit.
}
return 0;
@@ -649,14 +681,18 @@ int Bignum::Compare(const Bignum& a, const Bignum& b) {
int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) {
- ASSERT(a.IsClamped());
- ASSERT(b.IsClamped());
- ASSERT(c.IsClamped());
+ DOUBLE_CONVERSION_ASSERT(a.IsClamped());
+ DOUBLE_CONVERSION_ASSERT(b.IsClamped());
+ DOUBLE_CONVERSION_ASSERT(c.IsClamped());
if (a.BigitLength() < b.BigitLength()) {
return PlusCompare(b, a, c);
}
- if (a.BigitLength() + 1 < c.BigitLength()) return -1;
- if (a.BigitLength() > c.BigitLength()) return +1;
+ if (a.BigitLength() + 1 < c.BigitLength()) {
+ return -1;
+ }
+ if (a.BigitLength() > c.BigitLength()) {
+ return +1;
+ }
// The exponent encodes 0-bigits. So if there are more 0-digits in 'a' than
// 'b' has digits, then the bigit-length of 'a'+'b' must be equal to the one
// of 'a'.
@@ -666,92 +702,83 @@ int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) {
Chunk borrow = 0;
// Starting at min_exponent all digits are == 0. So no need to compare them.
- int min_exponent = Min(Min(a.exponent_, b.exponent_), c.exponent_);
+ const int min_exponent = (std::min)((std::min)(a.exponent_, b.exponent_), c.exponent_);
for (int i = c.BigitLength() - 1; i >= min_exponent; --i) {
- Chunk chunk_a = a.BigitAt(i);
- Chunk chunk_b = b.BigitAt(i);
- Chunk chunk_c = c.BigitAt(i);
- Chunk sum = chunk_a + chunk_b;
+ const Chunk chunk_a = a.BigitOrZero(i);
+ const Chunk chunk_b = b.BigitOrZero(i);
+ const Chunk chunk_c = c.BigitOrZero(i);
+ const Chunk sum = chunk_a + chunk_b;
if (sum > chunk_c + borrow) {
return +1;
} else {
borrow = chunk_c + borrow - sum;
- if (borrow > 1) return -1;
+ if (borrow > 1) {
+ return -1;
+ }
borrow <<= kBigitSize;
}
}
- if (borrow == 0) return 0;
+ if (borrow == 0) {
+ return 0;
+ }
return -1;
}
void Bignum::Clamp() {
- while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) {
- used_digits_--;
+ while (used_bigits_ > 0 && RawBigit(used_bigits_ - 1) == 0) {
+ used_bigits_--;
}
- if (used_digits_ == 0) {
+ if (used_bigits_ == 0) {
// Zero.
exponent_ = 0;
}
}
-bool Bignum::IsClamped() const {
- return used_digits_ == 0 || bigits_[used_digits_ - 1] != 0;
-}
-
-
-void Bignum::Zero() {
- for (int i = 0; i < used_digits_; ++i) {
- bigits_[i] = 0;
- }
- used_digits_ = 0;
- exponent_ = 0;
-}
-
-
void Bignum::Align(const Bignum& other) {
if (exponent_ > other.exponent_) {
- // If "X" represents a "hidden" digit (by the exponent) then we are in the
+ // If "X" represents a "hidden" bigit (by the exponent) then we are in the
// following case (a == this, b == other):
// a: aaaaaaXXXX or a: aaaaaXXX
// b: bbbbbbX b: bbbbbbbbXX
// We replace some of the hidden digits (X) of a with 0 digits.
// a: aaaaaa000X or a: aaaaa0XX
- int zero_digits = exponent_ - other.exponent_;
- EnsureCapacity(used_digits_ + zero_digits);
- for (int i = used_digits_ - 1; i >= 0; --i) {
- bigits_[i + zero_digits] = bigits_[i];
+ const int zero_bigits = exponent_ - other.exponent_;
+ EnsureCapacity(used_bigits_ + zero_bigits);
+ for (int i = used_bigits_ - 1; i >= 0; --i) {
+ RawBigit(i + zero_bigits) = RawBigit(i);
}
- for (int i = 0; i < zero_digits; ++i) {
- bigits_[i] = 0;
+ for (int i = 0; i < zero_bigits; ++i) {
+ RawBigit(i) = 0;
}
- used_digits_ += zero_digits;
- exponent_ -= zero_digits;
- ASSERT(used_digits_ >= 0);
- ASSERT(exponent_ >= 0);
+ used_bigits_ += zero_bigits;
+ exponent_ -= zero_bigits;
+
+ DOUBLE_CONVERSION_ASSERT(used_bigits_ >= 0);
+ DOUBLE_CONVERSION_ASSERT(exponent_ >= 0);
}
}
-void Bignum::BigitsShiftLeft(int shift_amount) {
- ASSERT(shift_amount < kBigitSize);
- ASSERT(shift_amount >= 0);
+void Bignum::BigitsShiftLeft(const int shift_amount) {
+ DOUBLE_CONVERSION_ASSERT(shift_amount < kBigitSize);
+ DOUBLE_CONVERSION_ASSERT(shift_amount >= 0);
Chunk carry = 0;
- for (int i = 0; i < used_digits_; ++i) {
- Chunk new_carry = bigits_[i] >> (kBigitSize - shift_amount);
- bigits_[i] = ((bigits_[i] << shift_amount) + carry) & kBigitMask;
+ for (int i = 0; i < used_bigits_; ++i) {
+ const Chunk new_carry = RawBigit(i) >> (kBigitSize - shift_amount);
+ RawBigit(i) = ((RawBigit(i) << shift_amount) + carry) & kBigitMask;
carry = new_carry;
}
if (carry != 0) {
- bigits_[used_digits_] = carry;
- used_digits_++;
+ RawBigit(used_bigits_) = carry;
+ used_bigits_++;
}
}
-void Bignum::SubtractTimes(const Bignum& other, int factor) {
- ASSERT(exponent_ <= other.exponent_);
+void Bignum::SubtractTimes(const Bignum& other, const int factor) {
+ DOUBLE_CONVERSION_ASSERT(exponent_ <= other.exponent_);
if (factor < 3) {
for (int i = 0; i < factor; ++i) {
SubtractBignum(other);
@@ -759,19 +786,21 @@ void Bignum::SubtractTimes(const Bignum& other, int factor) {
return;
}
Chunk borrow = 0;
- int exponent_diff = other.exponent_ - exponent_;
- for (int i = 0; i < other.used_digits_; ++i) {
- DoubleChunk product = static_cast(factor) * other.bigits_[i];
- DoubleChunk remove = borrow + product;
- Chunk difference = bigits_[i + exponent_diff] - (remove & kBigitMask);
- bigits_[i + exponent_diff] = difference & kBigitMask;
+ const int exponent_diff = other.exponent_ - exponent_;
+ for (int i = 0; i < other.used_bigits_; ++i) {
+ const DoubleChunk product = static_cast(factor) * other.RawBigit(i);
+ const DoubleChunk remove = borrow + product;
+ const Chunk difference = RawBigit(i + exponent_diff) - (remove & kBigitMask);
+ RawBigit(i + exponent_diff) = difference & kBigitMask;
borrow = static_cast((difference >> (kChunkSize - 1)) +
(remove >> kBigitSize));
}
- for (int i = other.used_digits_ + exponent_diff; i < used_digits_; ++i) {
- if (borrow == 0) return;
- Chunk difference = bigits_[i] - borrow;
- bigits_[i] = difference & kBigitMask;
+ for (int i = other.used_bigits_ + exponent_diff; i < used_bigits_; ++i) {
+ if (borrow == 0) {
+ return;
+ }
+ const Chunk difference = RawBigit(i) - borrow;
+ RawBigit(i) = difference & kBigitMask;
borrow = difference >> (kChunkSize - 1);
}
Clamp();
diff --git a/deps/icu-small/source/i18n/double-conversion-bignum.h b/deps/icu-small/source/i18n/double-conversion-bignum.h
index d39a3dee010d8b..bae900a15a7420 100644
--- a/deps/icu-small/source/i18n/double-conversion-bignum.h
+++ b/deps/icu-small/source/i18n/double-conversion-bignum.h
@@ -53,26 +53,27 @@ class Bignum {
// exponent.
static const int kMaxSignificantBits = 3584;
- Bignum();
- void AssignUInt16(uint16_t value);
+ Bignum() : used_bigits_(0), exponent_(0) {}
+
+ void AssignUInt16(const uint16_t value);
void AssignUInt64(uint64_t value);
void AssignBignum(const Bignum& other);
- void AssignDecimalString(Vector value);
- void AssignHexString(Vector value);
+ void AssignDecimalString(const Vector value);
+ void AssignHexString(const Vector value);
- void AssignPowerUInt16(uint16_t base, int exponent);
+ void AssignPowerUInt16(uint16_t base, const int exponent);
- void AddUInt64(uint64_t operand);
+ void AddUInt64(const uint64_t operand);
void AddBignum(const Bignum& other);
// Precondition: this >= other.
void SubtractBignum(const Bignum& other);
void Square();
- void ShiftLeft(int shift_amount);
- void MultiplyByUInt32(uint32_t factor);
- void MultiplyByUInt64(uint64_t factor);
- void MultiplyByPowerOfTen(int exponent);
+ void ShiftLeft(const int shift_amount);
+ void MultiplyByUInt32(const uint32_t factor);
+ void MultiplyByUInt64(const uint64_t factor);
+ void MultiplyByPowerOfTen(const int exponent);
void Times10() { return MultiplyByUInt32(10); }
// Pseudocode:
// int result = this / other;
@@ -80,7 +81,7 @@ class Bignum {
// In the worst case this function is in O(this/other).
uint16_t DivideModuloIntBignum(const Bignum& other);
- bool ToHexString(char* buffer, int buffer_size) const;
+ bool ToHexString(char* buffer, const int buffer_size) const;
// Returns
// -1 if a < b,
@@ -124,33 +125,40 @@ class Bignum {
// grow. There are no checks if the stack-allocated space is sufficient.
static const int kBigitCapacity = kMaxSignificantBits / kBigitSize;
- void EnsureCapacity(int size) {
+ static void EnsureCapacity(const int size) {
if (size > kBigitCapacity) {
- UNREACHABLE();
+ DOUBLE_CONVERSION_UNREACHABLE();
}
}
void Align(const Bignum& other);
void Clamp();
- bool IsClamped() const;
- void Zero();
+ bool IsClamped() const {
+ return used_bigits_ == 0 || RawBigit(used_bigits_ - 1) != 0;
+ }
+ void Zero() {
+ used_bigits_ = 0;
+ exponent_ = 0;
+ }
// Requires this to have enough capacity (no tests done).
- // Updates used_digits_ if necessary.
+ // Updates used_bigits_ if necessary.
// shift_amount must be < kBigitSize.
- void BigitsShiftLeft(int shift_amount);
- // BigitLength includes the "hidden" digits encoded in the exponent.
- int BigitLength() const { return used_digits_ + exponent_; }
- Chunk BigitAt(int index) const;
- void SubtractTimes(const Bignum& other, int factor);
-
+ void BigitsShiftLeft(const int shift_amount);
+ // BigitLength includes the "hidden" bigits encoded in the exponent.
+ int BigitLength() const { return used_bigits_ + exponent_; }
+ Chunk& RawBigit(const int index);
+ const Chunk& RawBigit(const int index) const;
+ Chunk BigitOrZero(const int index) const;
+ void SubtractTimes(const Bignum& other, const int factor);
+
+ // The Bignum's value is value(bigits_buffer_) * 2^(exponent_ * kBigitSize),
+ // where the value of the buffer consists of the lower kBigitSize bits of
+ // the first used_bigits_ Chunks in bigits_buffer_, first chunk has lowest
+ // significant bits.
+ int16_t used_bigits_;
+ int16_t exponent_;
Chunk bigits_buffer_[kBigitCapacity];
- // A vector backed by bigits_buffer_. This way accesses to the array are
- // checked for out-of-bounds errors.
- Vector bigits_;
- int used_digits_;
- // The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize).
- int exponent_;
-
- DC_DISALLOW_COPY_AND_ASSIGN(Bignum);
+
+ DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(Bignum);
};
} // namespace double_conversion
diff --git a/deps/icu-small/source/i18n/double-conversion-cached-powers.cpp b/deps/icu-small/source/i18n/double-conversion-cached-powers.cpp
index e1b66d2c65c82e..3bc35c8aaf81dc 100644
--- a/deps/icu-small/source/i18n/double-conversion-cached-powers.cpp
+++ b/deps/icu-small/source/i18n/double-conversion-cached-powers.cpp
@@ -49,6 +49,8 @@ U_NAMESPACE_BEGIN
namespace double_conversion {
+namespace PowersOfTenCache {
+
struct CachedPower {
uint64_t significand;
int16_t binary_exponent;
@@ -56,103 +58,99 @@ struct CachedPower {
};
static const CachedPower kCachedPowers[] = {
- {UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348},
- {UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340},
- {UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332},
- {UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324},
- {UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316},
- {UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308},
- {UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300},
- {UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292},
- {UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284},
- {UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276},
- {UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268},
- {UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260},
- {UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252},
- {UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244},
- {UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236},
- {UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228},
- {UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220},
- {UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212},
- {UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204},
- {UINT64_2PART_C(0xef340a98, 172aace5), -715, -196},
- {UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188},
- {UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180},
- {UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172},
- {UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164},
- {UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156},
- {UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148},
- {UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140},
- {UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132},
- {UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124},
- {UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116},
- {UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108},
- {UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100},
- {UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92},
- {UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84},
- {UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76},
- {UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68},
- {UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60},
- {UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52},
- {UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44},
- {UINT64_2PART_C(0xaa242499, 697392d3), -183, -36},
- {UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28},
- {UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20},
- {UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12},
- {UINT64_2PART_C(0xd1b71758, e219652c), -77, -4},
- {UINT64_2PART_C(0x9c400000, 00000000), -50, 4},
- {UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12},
- {UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20},
- {UINT64_2PART_C(0x813f3978, f8940984), 30, 28},
- {UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36},
- {UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44},
- {UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52},
- {UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60},
- {UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68},
- {UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76},
- {UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84},
- {UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92},
- {UINT64_2PART_C(0x924d692c, a61be758), 269, 100},
- {UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108},
- {UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116},
- {UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124},
- {UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132},
- {UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140},
- {UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148},
- {UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156},
- {UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164},
- {UINT64_2PART_C(0xa59bc234, db398c25), 508, 172},
- {UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180},
- {UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188},
- {UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196},
- {UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204},
- {UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212},
- {UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220},
- {UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228},
- {UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236},
- {UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244},
- {UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252},
- {UINT64_2PART_C(0xd01fef10, a657842c), 800, 260},
- {UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268},
- {UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276},
- {UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284},
- {UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292},
- {UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300},
- {UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308},
- {UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316},
- {UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324},
- {UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332},
- {UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xef340a98, 172aace5), -715, -196},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xaa242499, 697392d3), -183, -36},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xd1b71758, e219652c), -77, -4},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x9c400000, 00000000), -50, 4},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x813f3978, f8940984), 30, 28},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x924d692c, a61be758), 269, 100},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xa59bc234, db398c25), 508, 172},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xd01fef10, a657842c), 800, 260},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332},
+ {DOUBLE_CONVERSION_UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340},
};
static const int kCachedPowersOffset = 348; // -1 * the first decimal_exponent.
static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10)
-// Difference between the decimal exponents in the table above.
-const int PowersOfTenCache::kDecimalExponentDistance = 8;
-const int PowersOfTenCache::kMinDecimalExponent = -348;
-const int PowersOfTenCache::kMaxDecimalExponent = 340;
-void PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
+void GetCachedPowerForBinaryExponentRange(
int min_exponent,
int max_exponent,
DiyFp* power,
@@ -162,30 +160,32 @@ void PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
int foo = kCachedPowersOffset;
int index =
(foo + static_cast(k) - 1) / kDecimalExponentDistance + 1;
- ASSERT(0 <= index && index < static_cast(ARRAY_SIZE(kCachedPowers)));
+ DOUBLE_CONVERSION_ASSERT(0 <= index && index < static_cast(DOUBLE_CONVERSION_ARRAY_SIZE(kCachedPowers)));
CachedPower cached_power = kCachedPowers[index];
- ASSERT(min_exponent <= cached_power.binary_exponent);
+ DOUBLE_CONVERSION_ASSERT(min_exponent <= cached_power.binary_exponent);
(void) max_exponent; // Mark variable as used.
- ASSERT(cached_power.binary_exponent <= max_exponent);
+ DOUBLE_CONVERSION_ASSERT(cached_power.binary_exponent <= max_exponent);
*decimal_exponent = cached_power.decimal_exponent;
*power = DiyFp(cached_power.significand, cached_power.binary_exponent);
}
-void PowersOfTenCache::GetCachedPowerForDecimalExponent(int requested_exponent,
- DiyFp* power,
- int* found_exponent) {
- ASSERT(kMinDecimalExponent <= requested_exponent);
- ASSERT(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance);
+void GetCachedPowerForDecimalExponent(int requested_exponent,
+ DiyFp* power,
+ int* found_exponent) {
+ DOUBLE_CONVERSION_ASSERT(kMinDecimalExponent <= requested_exponent);
+ DOUBLE_CONVERSION_ASSERT(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance);
int index =
(requested_exponent + kCachedPowersOffset) / kDecimalExponentDistance;
CachedPower cached_power = kCachedPowers[index];
*power = DiyFp(cached_power.significand, cached_power.binary_exponent);
*found_exponent = cached_power.decimal_exponent;
- ASSERT(*found_exponent <= requested_exponent);
- ASSERT(requested_exponent < *found_exponent + kDecimalExponentDistance);
+ DOUBLE_CONVERSION_ASSERT(*found_exponent <= requested_exponent);
+ DOUBLE_CONVERSION_ASSERT(requested_exponent < *found_exponent + kDecimalExponentDistance);
}
+} // namespace PowersOfTenCache
+
} // namespace double_conversion
// ICU PATCH: Close ICU namespace
diff --git a/deps/icu-small/source/i18n/double-conversion-cached-powers.h b/deps/icu-small/source/i18n/double-conversion-cached-powers.h
index 438746b143293f..ade27baef8b0c7 100644
--- a/deps/icu-small/source/i18n/double-conversion-cached-powers.h
+++ b/deps/icu-small/source/i18n/double-conversion-cached-powers.h
@@ -46,32 +46,32 @@ U_NAMESPACE_BEGIN
namespace double_conversion {
-class PowersOfTenCache {
- public:
+namespace PowersOfTenCache {
// Not all powers of ten are cached. The decimal exponent of two neighboring
// cached numbers will differ by kDecimalExponentDistance.
- static const int kDecimalExponentDistance;
+ static const int kDecimalExponentDistance = 8;
- static const int kMinDecimalExponent;
- static const int kMaxDecimalExponent;
+ static const int kMinDecimalExponent = -348;
+ static const int kMaxDecimalExponent = 340;
// Returns a cached power-of-ten with a binary exponent in the range
// [min_exponent; max_exponent] (boundaries included).
- static void GetCachedPowerForBinaryExponentRange(int min_exponent,
- int max_exponent,
- DiyFp* power,
- int* decimal_exponent);
+ void GetCachedPowerForBinaryExponentRange(int min_exponent,
+ int max_exponent,
+ DiyFp* power,
+ int* decimal_exponent);
// Returns a cached power of ten x ~= 10^k such that
// k <= decimal_exponent < k + kCachedPowersDecimalDistance.
// The given decimal_exponent must satisfy
// kMinDecimalExponent <= requested_exponent, and
// requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance.
- static void GetCachedPowerForDecimalExponent(int requested_exponent,
- DiyFp* power,
- int* found_exponent);
-};
+ void GetCachedPowerForDecimalExponent(int requested_exponent,
+ DiyFp* power,
+ int* found_exponent);
+
+} // namespace PowersOfTenCache
} // namespace double_conversion
diff --git a/deps/icu-small/source/i18n/double-conversion-diy-fp.cpp b/deps/icu-small/source/i18n/double-conversion-diy-fp.cpp
deleted file mode 100644
index f38430c6c3c90f..00000000000000
--- a/deps/icu-small/source/i18n/double-conversion-diy-fp.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-// © 2018 and later: Unicode, Inc. and others.
-// License & terms of use: http://www.unicode.org/copyright.html
-//
-// From the double-conversion library. Original license:
-//
-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// ICU PATCH: ifdef around UCONFIG_NO_FORMATTING
-#include "unicode/utypes.h"
-#if !UCONFIG_NO_FORMATTING
-
-// ICU PATCH: Customize header file paths for ICU.
-
-#include "double-conversion-diy-fp.h"
-#include "double-conversion-utils.h"
-
-// ICU PATCH: Wrap in ICU namespace
-U_NAMESPACE_BEGIN
-
-namespace double_conversion {
-
-void DiyFp::Multiply(const DiyFp& other) {
- // Simply "emulates" a 128 bit multiplication.
- // However: the resulting number only contains 64 bits. The least
- // significant 64 bits are only used for rounding the most significant 64
- // bits.
- const uint64_t kM32 = 0xFFFFFFFFU;
- uint64_t a = f_ >> 32;
- uint64_t b = f_ & kM32;
- uint64_t c = other.f_ >> 32;
- uint64_t d = other.f_ & kM32;
- uint64_t ac = a * c;
- uint64_t bc = b * c;
- uint64_t ad = a * d;
- uint64_t bd = b * d;
- uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32);
- // By adding 1U << 31 to tmp we round the final result.
- // Halfway cases will be round up.
- tmp += 1U << 31;
- uint64_t result_f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
- e_ += other.e_ + 64;
- f_ = result_f;
-}
-
-} // namespace double_conversion
-
-// ICU PATCH: Close ICU namespace
-U_NAMESPACE_END
-#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/deps/icu-small/source/i18n/double-conversion-diy-fp.h b/deps/icu-small/source/i18n/double-conversion-diy-fp.h
index 21896851d22d32..5820abedf35405 100644
--- a/deps/icu-small/source/i18n/double-conversion-diy-fp.h
+++ b/deps/icu-small/source/i18n/double-conversion-diy-fp.h
@@ -50,36 +50,55 @@ namespace double_conversion {
// with a uint64 significand and an int exponent. Normalized DiyFp numbers will
// have the most significant bit of the significand set.
// Multiplication and Subtraction do not normalize their results.
-// DiyFp are not designed to contain special doubles (NaN and Infinity).
+// DiyFp store only non-negative numbers and are not designed to contain special
+// doubles (NaN and Infinity).
class DiyFp {
public:
static const int kSignificandSize = 64;
DiyFp() : f_(0), e_(0) {}
- DiyFp(uint64_t significand, int exponent) : f_(significand), e_(exponent) {}
+ DiyFp(const uint64_t significand, const int32_t exponent) : f_(significand), e_(exponent) {}
- // this = this - other.
+ // this -= other.
// The exponents of both numbers must be the same and the significand of this
- // must be bigger than the significand of other.
+ // must be greater or equal than the significand of other.
// The result will not be normalized.
void Subtract(const DiyFp& other) {
- ASSERT(e_ == other.e_);
- ASSERT(f_ >= other.f_);
+ DOUBLE_CONVERSION_ASSERT(e_ == other.e_);
+ DOUBLE_CONVERSION_ASSERT(f_ >= other.f_);
f_ -= other.f_;
}
// Returns a - b.
- // The exponents of both numbers must be the same and this must be bigger
- // than other. The result will not be normalized.
+ // The exponents of both numbers must be the same and a must be greater
+ // or equal than b. The result will not be normalized.
static DiyFp Minus(const DiyFp& a, const DiyFp& b) {
DiyFp result = a;
result.Subtract(b);
return result;
}
-
- // this = this * other.
- void Multiply(const DiyFp& other);
+ // this *= other.
+ void Multiply(const DiyFp& other) {
+ // Simply "emulates" a 128 bit multiplication.
+ // However: the resulting number only contains 64 bits. The least
+ // significant 64 bits are only used for rounding the most significant 64
+ // bits.
+ const uint64_t kM32 = 0xFFFFFFFFU;
+ const uint64_t a = f_ >> 32;
+ const uint64_t b = f_ & kM32;
+ const uint64_t c = other.f_ >> 32;
+ const uint64_t d = other.f_ & kM32;
+ const uint64_t ac = a * c;
+ const uint64_t bc = b * c;
+ const uint64_t ad = a * d;
+ const uint64_t bd = b * d;
+ // By adding 1U << 31 to tmp we round the final result.
+ // Halfway cases will be rounded up.
+ const uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32) + (1U << 31);
+ e_ += other.e_ + 64;
+ f_ = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
+ }
// returns a * b;
static DiyFp Times(const DiyFp& a, const DiyFp& b) {
@@ -89,13 +108,13 @@ class DiyFp {
}
void Normalize() {
- ASSERT(f_ != 0);
+ DOUBLE_CONVERSION_ASSERT(f_ != 0);
uint64_t significand = f_;
- int exponent = e_;
+ int32_t exponent = e_;
- // This method is mainly called for normalizing boundaries. In general
- // boundaries need to be shifted by 10 bits. We thus optimize for this case.
- const uint64_t k10MSBits = UINT64_2PART_C(0xFFC00000, 00000000);
+ // This method is mainly called for normalizing boundaries. In general,
+ // boundaries need to be shifted by 10 bits, and we optimize for this case.
+ const uint64_t k10MSBits = DOUBLE_CONVERSION_UINT64_2PART_C(0xFFC00000, 00000000);
while ((significand & k10MSBits) == 0) {
significand <<= 10;
exponent -= 10;
@@ -115,16 +134,16 @@ class DiyFp {
}
uint64_t f() const { return f_; }
- int e() const { return e_; }
+ int32_t e() const { return e_; }
void set_f(uint64_t new_value) { f_ = new_value; }
- void set_e(int new_value) { e_ = new_value; }
+ void set_e(int32_t new_value) { e_ = new_value; }
private:
- static const uint64_t kUint64MSB = UINT64_2PART_C(0x80000000, 00000000);
+ static const uint64_t kUint64MSB = DOUBLE_CONVERSION_UINT64_2PART_C(0x80000000, 00000000);
uint64_t f_;
- int e_;
+ int32_t e_;
};
} // namespace double_conversion
diff --git a/deps/icu-small/source/i18n/double-conversion-double-to-string.cpp b/deps/icu-small/source/i18n/double-conversion-double-to-string.cpp
new file mode 100644
index 00000000000000..44c176f4f9c958
--- /dev/null
+++ b/deps/icu-small/source/i18n/double-conversion-double-to-string.cpp
@@ -0,0 +1,450 @@
+// © 2018 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+//
+// From the double-conversion library. Original license:
+//
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ICU PATCH: ifdef around UCONFIG_NO_FORMATTING
+#include "unicode/utypes.h"
+#if !UCONFIG_NO_FORMATTING
+
+#include
+#include
+#include
+
+// ICU PATCH: Customize header file paths for ICU.
+// The file fixed-dtoa.h is not needed.
+
+#include "double-conversion-double-to-string.h"
+
+#include "double-conversion-bignum-dtoa.h"
+#include "double-conversion-fast-dtoa.h"
+#include "double-conversion-ieee.h"
+#include "double-conversion-utils.h"
+
+// ICU PATCH: Wrap in ICU namespace
+U_NAMESPACE_BEGIN
+
+namespace double_conversion {
+
+#if 0 // not needed for ICU
+const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
+ int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;
+ static DoubleToStringConverter converter(flags,
+ "Infinity",
+ "NaN",
+ 'e',
+ -6, 21,
+ 6, 0);
+ return converter;
+}
+
+
+bool DoubleToStringConverter::HandleSpecialValues(
+ double value,
+ StringBuilder* result_builder) const {
+ Double double_inspect(value);
+ if (double_inspect.IsInfinite()) {
+ if (infinity_symbol_ == NULL) return false;
+ if (value < 0) {
+ result_builder->AddCharacter('-');
+ }
+ result_builder->AddString(infinity_symbol_);
+ return true;
+ }
+ if (double_inspect.IsNan()) {
+ if (nan_symbol_ == NULL) return false;
+ result_builder->AddString(nan_symbol_);
+ return true;
+ }
+ return false;
+}
+
+
+void DoubleToStringConverter::CreateExponentialRepresentation(
+ const char* decimal_digits,
+ int length,
+ int exponent,
+ StringBuilder* result_builder) const {
+ DOUBLE_CONVERSION_ASSERT(length != 0);
+ result_builder->AddCharacter(decimal_digits[0]);
+ if (length != 1) {
+ result_builder->AddCharacter('.');
+ result_builder->AddSubstring(&decimal_digits[1], length-1);
+ }
+ result_builder->AddCharacter(exponent_character_);
+ if (exponent < 0) {
+ result_builder->AddCharacter('-');
+ exponent = -exponent;
+ } else {
+ if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
+ result_builder->AddCharacter('+');
+ }
+ }
+ if (exponent == 0) {
+ result_builder->AddCharacter('0');
+ return;
+ }
+ DOUBLE_CONVERSION_ASSERT(exponent < 1e4);
+ // Changing this constant requires updating the comment of DoubleToStringConverter constructor
+ const int kMaxExponentLength = 5;
+ char buffer[kMaxExponentLength + 1];
+ buffer[kMaxExponentLength] = '\0';
+ int first_char_pos = kMaxExponentLength;
+ while (exponent > 0) {
+ buffer[--first_char_pos] = '0' + (exponent % 10);
+ exponent /= 10;
+ }
+ // Add prefix '0' to make exponent width >= min(min_exponent_with_, kMaxExponentLength)
+ // For example: convert 1e+9 -> 1e+09, if min_exponent_with_ is set to 2
+ while(kMaxExponentLength - first_char_pos < std::min(min_exponent_width_, kMaxExponentLength)) {
+ buffer[--first_char_pos] = '0';
+ }
+ result_builder->AddSubstring(&buffer[first_char_pos],
+ kMaxExponentLength - first_char_pos);
+}
+
+
+void DoubleToStringConverter::CreateDecimalRepresentation(
+ const char* decimal_digits,
+ int length,
+ int decimal_point,
+ int digits_after_point,
+ StringBuilder* result_builder) const {
+ // Create a representation that is padded with zeros if needed.
+ if (decimal_point <= 0) {
+ // "0.00000decimal_rep" or "0.000decimal_rep00".
+ result_builder->AddCharacter('0');
+ if (digits_after_point > 0) {
+ result_builder->AddCharacter('.');
+ result_builder->AddPadding('0', -decimal_point);
+ DOUBLE_CONVERSION_ASSERT(length <= digits_after_point - (-decimal_point));
+ result_builder->AddSubstring(decimal_digits, length);
+ int remaining_digits = digits_after_point - (-decimal_point) - length;
+ result_builder->AddPadding('0', remaining_digits);
+ }
+ } else if (decimal_point >= length) {
+ // "decimal_rep0000.00000" or "decimal_rep.0000".
+ result_builder->AddSubstring(decimal_digits, length);
+ result_builder->AddPadding('0', decimal_point - length);
+ if (digits_after_point > 0) {
+ result_builder->AddCharacter('.');
+ result_builder->AddPadding('0', digits_after_point);
+ }
+ } else {
+ // "decima.l_rep000".
+ DOUBLE_CONVERSION_ASSERT(digits_after_point > 0);
+ result_builder->AddSubstring(decimal_digits, decimal_point);
+ result_builder->AddCharacter('.');
+ DOUBLE_CONVERSION_ASSERT(length - decimal_point <= digits_after_point);
+ result_builder->AddSubstring(&decimal_digits[decimal_point],
+ length - decimal_point);
+ int remaining_digits = digits_after_point - (length - decimal_point);
+ result_builder->AddPadding('0', remaining_digits);
+ }
+ if (digits_after_point == 0) {
+ if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
+ result_builder->AddCharacter('.');
+ }
+ if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
+ result_builder->AddCharacter('0');
+ }
+ }
+}
+
+
+bool DoubleToStringConverter::ToShortestIeeeNumber(
+ double value,
+ StringBuilder* result_builder,
+ DoubleToStringConverter::DtoaMode mode) const {
+ DOUBLE_CONVERSION_ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE);
+ if (Double(value).IsSpecial()) {
+ return HandleSpecialValues(value, result_builder);
+ }
+
+ int decimal_point;
+ bool sign;
+ const int kDecimalRepCapacity = kBase10MaximalLength + 1;
+ char decimal_rep[kDecimalRepCapacity];
+ int decimal_rep_length;
+
+ DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity,
+ &sign, &decimal_rep_length, &decimal_point);
+
+ bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
+ if (sign && (value != 0.0 || !unique_zero)) {
+ result_builder->AddCharacter('-');
+ }
+
+ int exponent = decimal_point - 1;
+ if ((decimal_in_shortest_low_ <= exponent) &&
+ (exponent < decimal_in_shortest_high_)) {
+ CreateDecimalRepresentation(decimal_rep, decimal_rep_length,
+ decimal_point,
+ (std::max)(0, decimal_rep_length - decimal_point),
+ result_builder);
+ } else {
+ CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
+ result_builder);
+ }
+ return true;
+}
+
+
+bool DoubleToStringConverter::ToFixed(double value,
+ int requested_digits,
+ StringBuilder* result_builder) const {
+ DOUBLE_CONVERSION_ASSERT(kMaxFixedDigitsBeforePoint == 60);
+ const double kFirstNonFixed = 1e60;
+
+ if (Double(value).IsSpecial()) {
+ return HandleSpecialValues(value, result_builder);
+ }
+
+ if (requested_digits > kMaxFixedDigitsAfterPoint) return false;
+ if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false;
+
+ // Find a sufficiently precise decimal representation of n.
+ int decimal_point;
+ bool sign;
+ // Add space for the '\0' byte.
+ const int kDecimalRepCapacity =
+ kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
+ char decimal_rep[kDecimalRepCapacity];
+ int decimal_rep_length;
+ DoubleToAscii(value, FIXED, requested_digits,
+ decimal_rep, kDecimalRepCapacity,
+ &sign, &decimal_rep_length, &decimal_point);
+
+ bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
+ if (sign && (value != 0.0 || !unique_zero)) {
+ result_builder->AddCharacter('-');
+ }
+
+ CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
+ requested_digits, result_builder);
+ return true;
+}
+
+
+bool DoubleToStringConverter::ToExponential(
+ double value,
+ int requested_digits,
+ StringBuilder* result_builder) const {
+ if (Double(value).IsSpecial()) {
+ return HandleSpecialValues(value, result_builder);
+ }
+
+ if (requested_digits < -1) return false;
+ if (requested_digits > kMaxExponentialDigits) return false;
+
+ int decimal_point;
+ bool sign;
+ // Add space for digit before the decimal point and the '\0' character.
+ const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
+ DOUBLE_CONVERSION_ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
+ char decimal_rep[kDecimalRepCapacity];
+#ifndef NDEBUG
+ // Problem: there is an assert in StringBuilder::AddSubstring() that
+ // will pass this buffer to strlen(), and this buffer is not generally
+ // null-terminated.
+ memset(decimal_rep, 0, sizeof(decimal_rep));
+#endif
+ int decimal_rep_length;
+
+ if (requested_digits == -1) {
+ DoubleToAscii(value, SHORTEST, 0,
+ decimal_rep, kDecimalRepCapacity,
+ &sign, &decimal_rep_length, &decimal_point);
+ } else {
+ DoubleToAscii(value, PRECISION, requested_digits + 1,
+ decimal_rep, kDecimalRepCapacity,
+ &sign, &decimal_rep_length, &decimal_point);
+ DOUBLE_CONVERSION_ASSERT(decimal_rep_length <= requested_digits + 1);
+
+ for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
+ decimal_rep[i] = '0';
+ }
+ decimal_rep_length = requested_digits + 1;
+ }
+
+ bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
+ if (sign && (value != 0.0 || !unique_zero)) {
+ result_builder->AddCharacter('-');
+ }
+
+ int exponent = decimal_point - 1;
+ CreateExponentialRepresentation(decimal_rep,
+ decimal_rep_length,
+ exponent,
+ result_builder);
+ return true;
+}
+
+
+bool DoubleToStringConverter::ToPrecision(double value,
+ int precision,
+ StringBuilder* result_builder) const {
+ if (Double(value).IsSpecial()) {
+ return HandleSpecialValues(value, result_builder);
+ }
+
+ if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
+ return false;
+ }
+
+ // Find a sufficiently precise decimal representation of n.
+ int decimal_point;
+ bool sign;
+ // Add one for the terminating null character.
+ const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;
+ char decimal_rep[kDecimalRepCapacity];
+ int decimal_rep_length;
+
+ DoubleToAscii(value, PRECISION, precision,
+ decimal_rep, kDecimalRepCapacity,
+ &sign, &decimal_rep_length, &decimal_point);
+ DOUBLE_CONVERSION_ASSERT(decimal_rep_length <= precision);
+
+ bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
+ if (sign && (value != 0.0 || !unique_zero)) {
+ result_builder->AddCharacter('-');
+ }
+
+ // The exponent if we print the number as x.xxeyyy. That is with the
+ // decimal point after the first digit.
+ int exponent = decimal_point - 1;
+
+ int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
+ if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
+ (decimal_point - precision + extra_zero >
+ max_trailing_padding_zeroes_in_precision_mode_)) {
+ // Fill buffer to contain 'precision' digits.
+ // Usually the buffer is already at the correct length, but 'DoubleToAscii'
+ // is allowed to return less characters.
+ for (int i = decimal_rep_length; i < precision; ++i) {
+ decimal_rep[i] = '0';
+ }
+
+ CreateExponentialRepresentation(decimal_rep,
+ precision,
+ exponent,
+ result_builder);
+ } else {
+ CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
+ (std::max)(0, precision - decimal_point),
+ result_builder);
+ }
+ return true;
+}
+#endif // not needed for ICU
+
+
+static BignumDtoaMode DtoaToBignumDtoaMode(
+ DoubleToStringConverter::DtoaMode dtoa_mode) {
+ switch (dtoa_mode) {
+ case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST;
+ case DoubleToStringConverter::SHORTEST_SINGLE:
+ return BIGNUM_DTOA_SHORTEST_SINGLE;
+ case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED;
+ case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
+ default:
+ DOUBLE_CONVERSION_UNREACHABLE();
+ }
+}
+
+
+void DoubleToStringConverter::DoubleToAscii(double v,
+ DtoaMode mode,
+ int requested_digits,
+ char* buffer,
+ int buffer_length,
+ bool* sign,
+ int* length,
+ int* point) {
+ Vector vector(buffer, buffer_length);
+ DOUBLE_CONVERSION_ASSERT(!Double(v).IsSpecial());
+ DOUBLE_CONVERSION_ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0);
+
+ if (Double(v).Sign() < 0) {
+ *sign = true;
+ v = -v;
+ } else {
+ *sign = false;
+ }
+
+ if (mode == PRECISION && requested_digits == 0) {
+ vector[0] = '\0';
+ *length = 0;
+ return;
+ }
+
+ if (v == 0) {
+ vector[0] = '0';
+ vector[1] = '\0';
+ *length = 1;
+ *point = 1;
+ return;
+ }
+
+ bool fast_worked;
+ switch (mode) {
+ case SHORTEST:
+ fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
+ break;
+#if 0 // not needed for ICU
+ case SHORTEST_SINGLE:
+ fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0,
+ vector, length, point);
+ break;
+ case FIXED:
+ fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
+ break;
+ case PRECISION:
+ fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
+ vector, length, point);
+ break;
+#endif // not needed for ICU
+ default:
+ fast_worked = false;
+ DOUBLE_CONVERSION_UNREACHABLE();
+ }
+ if (fast_worked) return;
+
+ // If the fast dtoa didn't succeed use the slower bignum version.
+ BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
+ BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
+ vector[*length] = '\0';
+}
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/deps/icu-small/source/i18n/double-conversion-double-to-string.h b/deps/icu-small/source/i18n/double-conversion-double-to-string.h
new file mode 100644
index 00000000000000..27bd86784895f8
--- /dev/null
+++ b/deps/icu-small/source/i18n/double-conversion-double-to-string.h
@@ -0,0 +1,419 @@
+// © 2018 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+//
+// From the double-conversion library. Original license:
+//
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ICU PATCH: ifdef around UCONFIG_NO_FORMATTING
+#include "unicode/utypes.h"
+#if !UCONFIG_NO_FORMATTING
+
+#ifndef DOUBLE_CONVERSION_DOUBLE_TO_STRING_H_
+#define DOUBLE_CONVERSION_DOUBLE_TO_STRING_H_
+
+// ICU PATCH: Customize header file paths for ICU.
+
+#include "double-conversion-utils.h"
+
+// ICU PATCH: Wrap in ICU namespace
+U_NAMESPACE_BEGIN
+
+namespace double_conversion {
+
+class DoubleToStringConverter {
+ public:
+#if 0 // not needed for ICU
+ // When calling ToFixed with a double > 10^kMaxFixedDigitsBeforePoint
+ // or a requested_digits parameter > kMaxFixedDigitsAfterPoint then the
+ // function returns false.
+ static const int kMaxFixedDigitsBeforePoint = 60;
+ static const int kMaxFixedDigitsAfterPoint = 60;
+
+ // When calling ToExponential with a requested_digits
+ // parameter > kMaxExponentialDigits then the function returns false.
+ static const int kMaxExponentialDigits = 120;
+
+ // When calling ToPrecision with a requested_digits
+ // parameter < kMinPrecisionDigits or requested_digits > kMaxPrecisionDigits
+ // then the function returns false.
+ static const int kMinPrecisionDigits = 1;
+ static const int kMaxPrecisionDigits = 120;
+
+ enum Flags {
+ NO_FLAGS = 0,
+ EMIT_POSITIVE_EXPONENT_SIGN = 1,
+ EMIT_TRAILING_DECIMAL_POINT = 2,
+ EMIT_TRAILING_ZERO_AFTER_POINT = 4,
+ UNIQUE_ZERO = 8
+ };
+
+ // Flags should be a bit-or combination of the possible Flags-enum.
+ // - NO_FLAGS: no special flags.
+ // - EMIT_POSITIVE_EXPONENT_SIGN: when the number is converted into exponent
+ // form, emits a '+' for positive exponents. Example: 1.2e+2.
+ // - EMIT_TRAILING_DECIMAL_POINT: when the input number is an integer and is
+ // converted into decimal format then a trailing decimal point is appended.
+ // Example: 2345.0 is converted to "2345.".
+ // - EMIT_TRAILING_ZERO_AFTER_POINT: in addition to a trailing decimal point
+ // emits a trailing '0'-character. This flag requires the
+ // EXMIT_TRAILING_DECIMAL_POINT flag.
+ // Example: 2345.0 is converted to "2345.0".
+ // - UNIQUE_ZERO: "-0.0" is converted to "0.0".
+ //
+ // Infinity symbol and nan_symbol provide the string representation for these
+ // special values. If the string is NULL and the special value is encountered
+ // then the conversion functions return false.
+ //
+ // The exponent_character is used in exponential representations. It is
+ // usually 'e' or 'E'.
+ //
+ // When converting to the shortest representation the converter will
+ // represent input numbers in decimal format if they are in the interval
+ // [10^decimal_in_shortest_low; 10^decimal_in_shortest_high[
+ // (lower boundary included, greater boundary excluded).
+ // Example: with decimal_in_shortest_low = -6 and
+ // decimal_in_shortest_high = 21:
+ // ToShortest(0.000001) -> "0.000001"
+ // ToShortest(0.0000001) -> "1e-7"
+ // ToShortest(111111111111111111111.0) -> "111111111111111110000"
+ // ToShortest(100000000000000000000.0) -> "100000000000000000000"
+ // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"
+ //
+ // When converting to precision mode the converter may add
+ // max_leading_padding_zeroes before returning the number in exponential
+ // format.
+ // Example with max_leading_padding_zeroes_in_precision_mode = 6.
+ // ToPrecision(0.0000012345, 2) -> "0.0000012"
+ // ToPrecision(0.00000012345, 2) -> "1.2e-7"
+ // Similarily the converter may add up to
+ // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
+ // returning an exponential representation. A zero added by the
+ // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
+ // Examples for max_trailing_padding_zeroes_in_precision_mode = 1:
+ // ToPrecision(230.0, 2) -> "230"
+ // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT.
+ // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
+ //
+ // The min_exponent_width is used for exponential representations.
+ // The converter adds leading '0's to the exponent until the exponent
+ // is at least min_exponent_width digits long.
+ // The min_exponent_width is clamped to 5.
+ // As such, the exponent may never have more than 5 digits in total.
+ DoubleToStringConverter(int flags,
+ const char* infinity_symbol,
+ const char* nan_symbol,
+ char exponent_character,
+ int decimal_in_shortest_low,
+ int decimal_in_shortest_high,
+ int max_leading_padding_zeroes_in_precision_mode,
+ int max_trailing_padding_zeroes_in_precision_mode,
+ int min_exponent_width = 0)
+ : flags_(flags),
+ infinity_symbol_(infinity_symbol),
+ nan_symbol_(nan_symbol),
+ exponent_character_(exponent_character),
+ decimal_in_shortest_low_(decimal_in_shortest_low),
+ decimal_in_shortest_high_(decimal_in_shortest_high),
+ max_leading_padding_zeroes_in_precision_mode_(
+ max_leading_padding_zeroes_in_precision_mode),
+ max_trailing_padding_zeroes_in_precision_mode_(
+ max_trailing_padding_zeroes_in_precision_mode),
+ min_exponent_width_(min_exponent_width) {
+ // When 'trailing zero after the point' is set, then 'trailing point'
+ // must be set too.
+ DOUBLE_CONVERSION_ASSERT(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) ||
+ !((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0));
+ }
+
+ // Returns a converter following the EcmaScript specification.
+ static const DoubleToStringConverter& EcmaScriptConverter();
+
+ // Computes the shortest string of digits that correctly represent the input
+ // number. Depending on decimal_in_shortest_low and decimal_in_shortest_high
+ // (see constructor) it then either returns a decimal representation, or an
+ // exponential representation.
+ // Example with decimal_in_shortest_low = -6,
+ // decimal_in_shortest_high = 21,
+ // EMIT_POSITIVE_EXPONENT_SIGN activated, and
+ // EMIT_TRAILING_DECIMAL_POINT deactived:
+ // ToShortest(0.000001) -> "0.000001"
+ // ToShortest(0.0000001) -> "1e-7"
+ // ToShortest(111111111111111111111.0) -> "111111111111111110000"
+ // ToShortest(100000000000000000000.0) -> "100000000000000000000"
+ // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"
+ //
+ // Note: the conversion may round the output if the returned string
+ // is accurate enough to uniquely identify the input-number.
+ // For example the most precise representation of the double 9e59 equals
+ // "899999999999999918767229449717619953810131273674690656206848", but
+ // the converter will return the shorter (but still correct) "9e59".
+ //
+ // Returns true if the conversion succeeds. The conversion always succeeds
+ // except when the input value is special and no infinity_symbol or
+ // nan_symbol has been given to the constructor.
+ bool ToShortest(double value, StringBuilder* result_builder) const {
+ return ToShortestIeeeNumber(value, result_builder, SHORTEST);
+ }
+
+ // Same as ToShortest, but for single-precision floats.
+ bool ToShortestSingle(float value, StringBuilder* result_builder) const {
+ return ToShortestIeeeNumber(value, result_builder, SHORTEST_SINGLE);
+ }
+
+
+ // Computes a decimal representation with a fixed number of digits after the
+ // decimal point. The last emitted digit is rounded.
+ //
+ // Examples:
+ // ToFixed(3.12, 1) -> "3.1"
+ // ToFixed(3.1415, 3) -> "3.142"
+ // ToFixed(1234.56789, 4) -> "1234.5679"
+ // ToFixed(1.23, 5) -> "1.23000"
+ // ToFixed(0.1, 4) -> "0.1000"
+ // ToFixed(1e30, 2) -> "1000000000000000019884624838656.00"
+ // ToFixed(0.1, 30) -> "0.100000000000000005551115123126"
+ // ToFixed(0.1, 17) -> "0.10000000000000001"
+ //
+ // If requested_digits equals 0, then the tail of the result depends on
+ // the EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT.
+ // Examples, for requested_digits == 0,
+ // let EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT be
+ // - false and false: then 123.45 -> 123
+ // 0.678 -> 1
+ // - true and false: then 123.45 -> 123.
+ // 0.678 -> 1.
+ // - true and true: then 123.45 -> 123.0
+ // 0.678 -> 1.0
+ //
+ // Returns true if the conversion succeeds. The conversion always succeeds
+ // except for the following cases:
+ // - the input value is special and no infinity_symbol or nan_symbol has
+ // been provided to the constructor,
+ // - 'value' > 10^kMaxFixedDigitsBeforePoint, or
+ // - 'requested_digits' > kMaxFixedDigitsAfterPoint.
+ // The last two conditions imply that the result will never contain more than
+ // 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters
+ // (one additional character for the sign, and one for the decimal point).
+ bool ToFixed(double value,
+ int requested_digits,
+ StringBuilder* result_builder) const;
+
+ // Computes a representation in exponential format with requested_digits
+ // after the decimal point. The last emitted digit is rounded.
+ // If requested_digits equals -1, then the shortest exponential representation
+ // is computed.
+ //
+ // Examples with EMIT_POSITIVE_EXPONENT_SIGN deactivated, and
+ // exponent_character set to 'e'.
+ // ToExponential(3.12, 1) -> "3.1e0"
+ // ToExponential(5.0, 3) -> "5.000e0"
+ // ToExponential(0.001, 2) -> "1.00e-3"
+ // ToExponential(3.1415, -1) -> "3.1415e0"
+ // ToExponential(3.1415, 4) -> "3.1415e0"
+ // ToExponential(3.1415, 3) -> "3.142e0"
+ // ToExponential(123456789000000, 3) -> "1.235e14"
+ // ToExponential(1000000000000000019884624838656.0, -1) -> "1e30"
+ // ToExponential(1000000000000000019884624838656.0, 32) ->
+ // "1.00000000000000001988462483865600e30"
+ // ToExponential(1234, 0) -> "1e3"
+ //
+ // Returns true if the conversion succeeds. The conversion always succeeds
+ // except for the following cases:
+ // - the input value is special and no infinity_symbol or nan_symbol has
+ // been provided to the constructor,
+ // - 'requested_digits' > kMaxExponentialDigits.
+ // The last condition implies that the result will never contain more than
+ // kMaxExponentialDigits + 8 characters (the sign, the digit before the
+ // decimal point, the decimal point, the exponent character, the
+ // exponent's sign, and at most 3 exponent digits).
+ bool ToExponential(double value,
+ int requested_digits,
+ StringBuilder* result_builder) const;
+
+ // Computes 'precision' leading digits of the given 'value' and returns them
+ // either in exponential or decimal format, depending on
+ // max_{leading|trailing}_padding_zeroes_in_precision_mode (given to the
+ // constructor).
+ // The last computed digit is rounded.
+ //
+ // Example with max_leading_padding_zeroes_in_precision_mode = 6.
+ // ToPrecision(0.0000012345, 2) -> "0.0000012"
+ // ToPrecision(0.00000012345, 2) -> "1.2e-7"
+ // Similarily the converter may add up to
+ // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
+ // returning an exponential representation. A zero added by the
+ // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
+ // Examples for max_trailing_padding_zeroes_in_precision_mode = 1:
+ // ToPrecision(230.0, 2) -> "230"
+ // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT.
+ // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
+ // Examples for max_trailing_padding_zeroes_in_precision_mode = 3, and no
+ // EMIT_TRAILING_ZERO_AFTER_POINT:
+ // ToPrecision(123450.0, 6) -> "123450"
+ // ToPrecision(123450.0, 5) -> "123450"
+ // ToPrecision(123450.0, 4) -> "123500"
+ // ToPrecision(123450.0, 3) -> "123000"
+ // ToPrecision(123450.0, 2) -> "1.2e5"
+ //
+ // Returns true if the conversion succeeds. The conversion always succeeds
+ // except for the following cases:
+ // - the input value is special and no infinity_symbol or nan_symbol has
+ // been provided to the constructor,
+ // - precision < kMinPericisionDigits
+ // - precision > kMaxPrecisionDigits
+ // The last condition implies that the result will never contain more than
+ // kMaxPrecisionDigits + 7 characters (the sign, the decimal point, the
+ // exponent character, the exponent's sign, and at most 3 exponent digits).
+ bool ToPrecision(double value,
+ int precision,
+ StringBuilder* result_builder) const;
+#endif // not needed for ICU
+
+ enum DtoaMode {
+ // Produce the shortest correct representation.
+ // For example the output of 0.299999999999999988897 is (the less accurate
+ // but correct) 0.3.
+ SHORTEST,
+ // Same as SHORTEST, but for single-precision floats.
+ SHORTEST_SINGLE,
+ // Produce a fixed number of digits after the decimal point.
+ // For instance fixed(0.1, 4) becomes 0.1000
+ // If the input number is big, the output will be big.
+ FIXED,
+ // Fixed number of digits (independent of the decimal point).
+ PRECISION
+ };
+
+ // The maximal number of digits that are needed to emit a double in base 10.
+ // A higher precision can be achieved by using more digits, but the shortest
+ // accurate representation of any double will never use more digits than
+ // kBase10MaximalLength.
+ // Note that DoubleToAscii null-terminates its input. So the given buffer
+ // should be at least kBase10MaximalLength + 1 characters long.
+ static const int kBase10MaximalLength = 17;
+
+ // Converts the given double 'v' to digit characters. 'v' must not be NaN,
+ // +Infinity, or -Infinity. In SHORTEST_SINGLE-mode this restriction also
+ // applies to 'v' after it has been casted to a single-precision float. That
+ // is, in this mode static_cast(v) must not be NaN, +Infinity or
+ // -Infinity.
+ //
+ // The result should be interpreted as buffer * 10^(point-length).
+ //
+ // The digits are written to the buffer in the platform's charset, which is
+ // often UTF-8 (with ASCII-range digits) but may be another charset, such
+ // as EBCDIC.
+ //
+ // The output depends on the given mode:
+ // - SHORTEST: produce the least amount of digits for which the internal
+ // identity requirement is still satisfied. If the digits are printed
+ // (together with the correct exponent) then reading this number will give
+ // 'v' again. The buffer will choose the representation that is closest to
+ // 'v'. If there are two at the same distance, than the one farther away
+ // from 0 is chosen (halfway cases - ending with 5 - are rounded up).
+ // In this mode the 'requested_digits' parameter is ignored.
+ // - SHORTEST_SINGLE: same as SHORTEST but with single-precision.
+ // - FIXED: produces digits necessary to print a given number with
+ // 'requested_digits' digits after the decimal point. The produced digits
+ // might be too short in which case the caller has to fill the remainder
+ // with '0's.
+ // Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.
+ // Halfway cases are rounded towards +/-Infinity (away from 0). The call
+ // toFixed(0.15, 2) thus returns buffer="2", point=0.
+ // The returned buffer may contain digits that would be truncated from the
+ // shortest representation of the input.
+ // - PRECISION: produces 'requested_digits' where the first digit is not '0'.
+ // Even though the length of produced digits usually equals
+ // 'requested_digits', the function is allowed to return fewer digits, in
+ // which case the caller has to fill the missing digits with '0's.
+ // Halfway cases are again rounded away from 0.
+ // DoubleToAscii expects the given buffer to be big enough to hold all
+ // digits and a terminating null-character. In SHORTEST-mode it expects a
+ // buffer of at least kBase10MaximalLength + 1. In all other modes the
+ // requested_digits parameter and the padding-zeroes limit the size of the
+ // output. Don't forget the decimal point, the exponent character and the
+ // terminating null-character when computing the maximal output size.
+ // The given length is only used in debug mode to ensure the buffer is big
+ // enough.
+ // ICU PATCH: Export this as U_I18N_API for unit tests.
+ static void U_I18N_API DoubleToAscii(double v,
+ DtoaMode mode,
+ int requested_digits,
+ char* buffer,
+ int buffer_length,
+ bool* sign,
+ int* length,
+ int* point);
+
+#if 0 // not needed for ICU
+ private:
+ // Implementation for ToShortest and ToShortestSingle.
+ bool ToShortestIeeeNumber(double value,
+ StringBuilder* result_builder,
+ DtoaMode mode) const;
+
+ // If the value is a special value (NaN or Infinity) constructs the
+ // corresponding string using the configured infinity/nan-symbol.
+ // If either of them is NULL or the value is not special then the
+ // function returns false.
+ bool HandleSpecialValues(double value, StringBuilder* result_builder) const;
+ // Constructs an exponential representation (i.e. 1.234e56).
+ // The given exponent assumes a decimal point after the first decimal digit.
+ void CreateExponentialRepresentation(const char* decimal_digits,
+ int length,
+ int exponent,
+ StringBuilder* result_builder) const;
+ // Creates a decimal representation (i.e 1234.5678).
+ void CreateDecimalRepresentation(const char* decimal_digits,
+ int length,
+ int decimal_point,
+ int digits_after_point,
+ StringBuilder* result_builder) const;
+
+ const int flags_;
+ const char* const infinity_symbol_;
+ const char* const nan_symbol_;
+ const char exponent_character_;
+ const int decimal_in_shortest_low_;
+ const int decimal_in_shortest_high_;
+ const int max_leading_padding_zeroes_in_precision_mode_;
+ const int max_trailing_padding_zeroes_in_precision_mode_;
+ const int min_exponent_width_;
+#endif // not needed for ICU
+
+ DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
+};
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+
+#endif // DOUBLE_CONVERSION_DOUBLE_TO_STRING_H_
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/deps/icu-small/source/i18n/double-conversion-fast-dtoa.cpp b/deps/icu-small/source/i18n/double-conversion-fast-dtoa.cpp
index 8d1499a79b4a2e..87a3d536bf111f 100644
--- a/deps/icu-small/source/i18n/double-conversion-fast-dtoa.cpp
+++ b/deps/icu-small/source/i18n/double-conversion-fast-dtoa.cpp
@@ -152,7 +152,7 @@ static bool RoundWeed(Vector buffer,
// Conceptually rest ~= too_high - buffer
// We need to do the following tests in this order to avoid over- and
// underflows.
- ASSERT(rest <= unsafe_interval);
+ DOUBLE_CONVERSION_ASSERT(rest <= unsafe_interval);
while (rest < small_distance && // Negated condition 1
unsafe_interval - rest >= ten_kappa && // Negated condition 2
(rest + ten_kappa < small_distance || // buffer{-1} > w_high
@@ -198,7 +198,7 @@ static bool RoundWeedCounted(Vector buffer,
uint64_t ten_kappa,
uint64_t unit,
int* kappa) {
- ASSERT(rest < ten_kappa);
+ DOUBLE_CONVERSION_ASSERT(rest < ten_kappa);
// The following tests are done in a specific order to avoid overflows. They
// will work correctly with any uint64 values of rest < ten_kappa and unit.
//
@@ -255,7 +255,7 @@ static void BiggestPowerTen(uint32_t number,
int number_bits,
uint32_t* power,
int* exponent_plus_one) {
- ASSERT(number < (1u << (number_bits + 1)));
+ DOUBLE_CONVERSION_ASSERT(number < (1u << (number_bits + 1)));
// 1233/4096 is approximately 1/lg(10).
int exponent_plus_one_guess = ((number_bits + 1) * 1233 >> 12);
// We increment to skip over the first entry in the kPowersOf10 table.
@@ -317,9 +317,9 @@ static bool DigitGen(DiyFp low,
Vector buffer,
int* length,
int* kappa) {
- ASSERT(low.e() == w.e() && w.e() == high.e());
- ASSERT(low.f() + 1 <= high.f() - 1);
- ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);
+ DOUBLE_CONVERSION_ASSERT(low.e() == w.e() && w.e() == high.e());
+ DOUBLE_CONVERSION_ASSERT(low.f() + 1 <= high.f() - 1);
+ DOUBLE_CONVERSION_ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);
// low, w and high are imprecise, but by less than one ulp (unit in the last
// place).
// If we remove (resp. add) 1 ulp from low (resp. high) we are certain that
@@ -361,7 +361,7 @@ static bool DigitGen(DiyFp low,
// that is smaller than integrals.
while (*kappa > 0) {
int digit = integrals / divisor;
- ASSERT(digit <= 9);
+ DOUBLE_CONVERSION_ASSERT(digit <= 9);
buffer[*length] = static_cast('0' + digit);
(*length)++;
integrals %= divisor;
@@ -388,16 +388,16 @@ static bool DigitGen(DiyFp low,
// data (like the interval or 'unit'), too.
// Note that the multiplication by 10 does not overflow, because w.e >= -60
// and thus one.e >= -60.
- ASSERT(one.e() >= -60);
- ASSERT(fractionals < one.f());
- ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());
+ DOUBLE_CONVERSION_ASSERT(one.e() >= -60);
+ DOUBLE_CONVERSION_ASSERT(fractionals < one.f());
+ DOUBLE_CONVERSION_ASSERT(DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());
for (;;) {
fractionals *= 10;
unit *= 10;
unsafe_interval.set_f(unsafe_interval.f() * 10);
// Integer division by one.
int digit = static_cast(fractionals >> -one.e());
- ASSERT(digit <= 9);
+ DOUBLE_CONVERSION_ASSERT(digit <= 9);
buffer[*length] = static_cast('0' + digit);
(*length)++;
fractionals &= one.f() - 1; // Modulo by one.
@@ -444,9 +444,9 @@ static bool DigitGenCounted(DiyFp w,
Vector buffer,
int* length,
int* kappa) {
- ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);
- ASSERT(kMinimalTargetExponent >= -60);
- ASSERT(kMaximalTargetExponent <= -32);
+ DOUBLE_CONVERSION_ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);
+ DOUBLE_CONVERSION_ASSERT(kMinimalTargetExponent >= -60);
+ DOUBLE_CONVERSION_ASSERT(kMaximalTargetExponent <= -32);
// w is assumed to have an error less than 1 unit. Whenever w is scaled we
// also scale its error.
uint64_t w_error = 1;
@@ -472,7 +472,7 @@ static bool DigitGenCounted(DiyFp w,
// that is smaller than 'integrals'.
while (*kappa > 0) {
int digit = integrals / divisor;
- ASSERT(digit <= 9);
+ DOUBLE_CONVERSION_ASSERT(digit <= 9);
buffer[*length] = static_cast('0' + digit);
(*length)++;
requested_digits--;
@@ -498,15 +498,15 @@ static bool DigitGenCounted(DiyFp w,
// data (the 'unit'), too.
// Note that the multiplication by 10 does not overflow, because w.e >= -60
// and thus one.e >= -60.
- ASSERT(one.e() >= -60);
- ASSERT(fractionals < one.f());
- ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());
+ DOUBLE_CONVERSION_ASSERT(one.e() >= -60);
+ DOUBLE_CONVERSION_ASSERT(fractionals < one.f());
+ DOUBLE_CONVERSION_ASSERT(DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());
while (requested_digits > 0 && fractionals > w_error) {
fractionals *= 10;
w_error *= 10;
// Integer division by one.
int digit = static_cast(fractionals >> -one.e());
- ASSERT(digit <= 9);
+ DOUBLE_CONVERSION_ASSERT(digit <= 9);
buffer[*length] = static_cast('0' + digit);
(*length)++;
requested_digits--;
@@ -544,11 +544,11 @@ static bool Grisu3(double v,
if (mode == FAST_DTOA_SHORTEST) {
Double(v).NormalizedBoundaries(&boundary_minus, &boundary_plus);
} else {
- ASSERT(mode == FAST_DTOA_SHORTEST_SINGLE);
+ DOUBLE_CONVERSION_ASSERT(mode == FAST_DTOA_SHORTEST_SINGLE);
float single_v = static_cast(v);
Single(single_v).NormalizedBoundaries(&boundary_minus, &boundary_plus);
}
- ASSERT(boundary_plus.e() == w.e());
+ DOUBLE_CONVERSION_ASSERT(boundary_plus.e() == w.e());
DiyFp ten_mk; // Cached power of ten: 10^-k
int mk; // -k
int ten_mk_minimal_binary_exponent =
@@ -559,7 +559,7 @@ static bool Grisu3(double v,
ten_mk_minimal_binary_exponent,
ten_mk_maximal_binary_exponent,
&ten_mk, &mk);
- ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
+ DOUBLE_CONVERSION_ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
DiyFp::kSignificandSize) &&
(kMaximalTargetExponent >= w.e() + ten_mk.e() +
DiyFp::kSignificandSize));
@@ -573,7 +573,7 @@ static bool Grisu3(double v,
// In other words: let f = scaled_w.f() and e = scaled_w.e(), then
// (f-1) * 2^e < w*10^k < (f+1) * 2^e
DiyFp scaled_w = DiyFp::Times(w, ten_mk);
- ASSERT(scaled_w.e() ==
+ DOUBLE_CONVERSION_ASSERT(scaled_w.e() ==
boundary_plus.e() + ten_mk.e() + DiyFp::kSignificandSize);
// In theory it would be possible to avoid some recomputations by computing
// the difference between w and boundary_minus/plus (a power of 2) and to
@@ -618,7 +618,7 @@ static bool Grisu3Counted(double v,
ten_mk_minimal_binary_exponent,
ten_mk_maximal_binary_exponent,
&ten_mk, &mk);
- ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
+ DOUBLE_CONVERSION_ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
DiyFp::kSignificandSize) &&
(kMaximalTargetExponent >= w.e() + ten_mk.e() +
DiyFp::kSignificandSize));
@@ -652,8 +652,8 @@ bool FastDtoa(double v,
Vector buffer,
int* length,
int* decimal_point) {
- ASSERT(v > 0);
- ASSERT(!Double(v).IsSpecial());
+ DOUBLE_CONVERSION_ASSERT(v > 0);
+ DOUBLE_CONVERSION_ASSERT(!Double(v).IsSpecial());
bool result = false;
int decimal_exponent = 0;
@@ -667,7 +667,7 @@ bool FastDtoa(double v,
buffer, length, &decimal_exponent);
break;
default:
- UNREACHABLE();
+ DOUBLE_CONVERSION_UNREACHABLE();
}
if (result) {
*decimal_point = *length + decimal_exponent;
diff --git a/deps/icu-small/source/i18n/double-conversion-ieee.h b/deps/icu-small/source/i18n/double-conversion-ieee.h
index c83c8d9abbb46e..f4c62a9a9f8d99 100644
--- a/deps/icu-small/source/i18n/double-conversion-ieee.h
+++ b/deps/icu-small/source/i18n/double-conversion-ieee.h
@@ -55,12 +55,14 @@ static float uint32_to_float(uint32_t d32) { return BitCast(d32); }
// Helper functions for doubles.
class Double {
public:
- static const uint64_t kSignMask = UINT64_2PART_C(0x80000000, 00000000);
- static const uint64_t kExponentMask = UINT64_2PART_C(0x7FF00000, 00000000);
- static const uint64_t kSignificandMask = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
- static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000);
+ static const uint64_t kSignMask = DOUBLE_CONVERSION_UINT64_2PART_C(0x80000000, 00000000);
+ static const uint64_t kExponentMask = DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF00000, 00000000);
+ static const uint64_t kSignificandMask = DOUBLE_CONVERSION_UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
+ static const uint64_t kHiddenBit = DOUBLE_CONVERSION_UINT64_2PART_C(0x00100000, 00000000);
static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit.
static const int kSignificandSize = 53;
+ static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
+ static const int kMaxExponent = 0x7FF - kExponentBias;
Double() : d64_(0) {}
explicit Double(double d) : d64_(double_to_uint64(d)) {}
@@ -71,14 +73,14 @@ class Double {
// The value encoded by this Double must be greater or equal to +0.0.
// It must not be special (infinity, or NaN).
DiyFp AsDiyFp() const {
- ASSERT(Sign() > 0);
- ASSERT(!IsSpecial());
+ DOUBLE_CONVERSION_ASSERT(Sign() > 0);
+ DOUBLE_CONVERSION_ASSERT(!IsSpecial());
return DiyFp(Significand(), Exponent());
}
// The value encoded by this Double must be strictly greater than 0.
DiyFp AsNormalizedDiyFp() const {
- ASSERT(value() > 0.0);
+ DOUBLE_CONVERSION_ASSERT(value() > 0.0);
uint64_t f = Significand();
int e = Exponent();
@@ -174,7 +176,7 @@ class Double {
// Precondition: the value encoded by this Double must be greater or equal
// than +0.0.
DiyFp UpperBoundary() const {
- ASSERT(Sign() > 0);
+ DOUBLE_CONVERSION_ASSERT(Sign() > 0);
return DiyFp(Significand() * 2 + 1, Exponent() - 1);
}
@@ -183,7 +185,7 @@ class Double {
// exponent as m_plus.
// Precondition: the value encoded by this Double must be greater than 0.
void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
- ASSERT(value() > 0.0);
+ DOUBLE_CONVERSION_ASSERT(value() > 0.0);
DiyFp v = this->AsDiyFp();
DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
DiyFp m_minus;
@@ -236,11 +238,9 @@ class Double {
}
private:
- static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
static const int kDenormalExponent = -kExponentBias + 1;
- static const int kMaxExponent = 0x7FF - kExponentBias;
- static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000);
- static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000);
+ static const uint64_t kInfinity = DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF00000, 00000000);
+ static const uint64_t kNaN = DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF80000, 00000000);
const uint64_t d64_;
@@ -271,7 +271,7 @@ class Double {
(biased_exponent << kPhysicalSignificandSize);
}
- DC_DISALLOW_COPY_AND_ASSIGN(Double);
+ DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(Double);
};
class Single {
@@ -290,8 +290,8 @@ class Single {
// The value encoded by this Single must be greater or equal to +0.0.
// It must not be special (infinity, or NaN).
DiyFp AsDiyFp() const {
- ASSERT(Sign() > 0);
- ASSERT(!IsSpecial());
+ DOUBLE_CONVERSION_ASSERT(Sign() > 0);
+ DOUBLE_CONVERSION_ASSERT(!IsSpecial());
return DiyFp(Significand(), Exponent());
}
@@ -354,7 +354,7 @@ class Single {
// exponent as m_plus.
// Precondition: the value encoded by this Single must be greater than 0.
void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
- ASSERT(value() > 0.0);
+ DOUBLE_CONVERSION_ASSERT(value() > 0.0);
DiyFp v = this->AsDiyFp();
DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
DiyFp m_minus;
@@ -372,7 +372,7 @@ class Single {
// Precondition: the value encoded by this Single must be greater or equal
// than +0.0.
DiyFp UpperBoundary() const {
- ASSERT(Sign() > 0);
+ DOUBLE_CONVERSION_ASSERT(Sign() > 0);
return DiyFp(Significand() * 2 + 1, Exponent() - 1);
}
@@ -408,7 +408,7 @@ class Single {
const uint32_t d32_;
- DC_DISALLOW_COPY_AND_ASSIGN(Single);
+ DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(Single);
};
} // namespace double_conversion
diff --git a/deps/icu-small/source/i18n/double-conversion.cpp b/deps/icu-small/source/i18n/double-conversion-string-to-double.cpp
similarity index 63%
rename from deps/icu-small/source/i18n/double-conversion.cpp
rename to deps/icu-small/source/i18n/double-conversion-string-to-double.cpp
index 1a60afbd64b6b7..946b2b26e77aa4 100644
--- a/deps/icu-small/source/i18n/double-conversion.cpp
+++ b/deps/icu-small/source/i18n/double-conversion-string-to-double.cpp
@@ -37,16 +37,13 @@
// ICU PATCH: Do not include std::locale.
#include
-//#include
+// #include
#include
// ICU PATCH: Customize header file paths for ICU.
-// The file fixed-dtoa.h is not needed.
-#include "double-conversion.h"
+#include "double-conversion-string-to-double.h"
-#include "double-conversion-bignum-dtoa.h"
-#include "double-conversion-fast-dtoa.h"
#include "double-conversion-ieee.h"
#include "double-conversion-strtod.h"
#include "double-conversion-utils.h"
@@ -56,385 +53,6 @@ U_NAMESPACE_BEGIN
namespace double_conversion {
-#if 0 // not needed for ICU
-const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
- int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;
- static DoubleToStringConverter converter(flags,
- "Infinity",
- "NaN",
- 'e',
- -6, 21,
- 6, 0);
- return converter;
-}
-
-
-bool DoubleToStringConverter::HandleSpecialValues(
- double value,
- StringBuilder* result_builder) const {
- Double double_inspect(value);
- if (double_inspect.IsInfinite()) {
- if (infinity_symbol_ == NULL) return false;
- if (value < 0) {
- result_builder->AddCharacter('-');
- }
- result_builder->AddString(infinity_symbol_);
- return true;
- }
- if (double_inspect.IsNan()) {
- if (nan_symbol_ == NULL) return false;
- result_builder->AddString(nan_symbol_);
- return true;
- }
- return false;
-}
-
-
-void DoubleToStringConverter::CreateExponentialRepresentation(
- const char* decimal_digits,
- int length,
- int exponent,
- StringBuilder* result_builder) const {
- ASSERT(length != 0);
- result_builder->AddCharacter(decimal_digits[0]);
- if (length != 1) {
- result_builder->AddCharacter('.');
- result_builder->AddSubstring(&decimal_digits[1], length-1);
- }
- result_builder->AddCharacter(exponent_character_);
- if (exponent < 0) {
- result_builder->AddCharacter('-');
- exponent = -exponent;
- } else {
- if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
- result_builder->AddCharacter('+');
- }
- }
- if (exponent == 0) {
- result_builder->AddCharacter('0');
- return;
- }
- ASSERT(exponent < 1e4);
- const int kMaxExponentLength = 5;
- char buffer[kMaxExponentLength + 1];
- buffer[kMaxExponentLength] = '\0';
- int first_char_pos = kMaxExponentLength;
- while (exponent > 0) {
- buffer[--first_char_pos] = '0' + (exponent % 10);
- exponent /= 10;
- }
- result_builder->AddSubstring(&buffer[first_char_pos],
- kMaxExponentLength - first_char_pos);
-}
-
-
-void DoubleToStringConverter::CreateDecimalRepresentation(
- const char* decimal_digits,
- int length,
- int decimal_point,
- int digits_after_point,
- StringBuilder* result_builder) const {
- // Create a representation that is padded with zeros if needed.
- if (decimal_point <= 0) {
- // "0.00000decimal_rep" or "0.000decimal_rep00".
- result_builder->AddCharacter('0');
- if (digits_after_point > 0) {
- result_builder->AddCharacter('.');
- result_builder->AddPadding('0', -decimal_point);
- ASSERT(length <= digits_after_point - (-decimal_point));
- result_builder->AddSubstring(decimal_digits, length);
- int remaining_digits = digits_after_point - (-decimal_point) - length;
- result_builder->AddPadding('0', remaining_digits);
- }
- } else if (decimal_point >= length) {
- // "decimal_rep0000.00000" or "decimal_rep.0000".
- result_builder->AddSubstring(decimal_digits, length);
- result_builder->AddPadding('0', decimal_point - length);
- if (digits_after_point > 0) {
- result_builder->AddCharacter('.');
- result_builder->AddPadding('0', digits_after_point);
- }
- } else {
- // "decima.l_rep000".
- ASSERT(digits_after_point > 0);
- result_builder->AddSubstring(decimal_digits, decimal_point);
- result_builder->AddCharacter('.');
- ASSERT(length - decimal_point <= digits_after_point);
- result_builder->AddSubstring(&decimal_digits[decimal_point],
- length - decimal_point);
- int remaining_digits = digits_after_point - (length - decimal_point);
- result_builder->AddPadding('0', remaining_digits);
- }
- if (digits_after_point == 0) {
- if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
- result_builder->AddCharacter('.');
- }
- if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
- result_builder->AddCharacter('0');
- }
- }
-}
-
-
-bool DoubleToStringConverter::ToShortestIeeeNumber(
- double value,
- StringBuilder* result_builder,
- DoubleToStringConverter::DtoaMode mode) const {
- ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE);
- if (Double(value).IsSpecial()) {
- return HandleSpecialValues(value, result_builder);
- }
-
- int decimal_point;
- bool sign;
- const int kDecimalRepCapacity = kBase10MaximalLength + 1;
- char decimal_rep[kDecimalRepCapacity];
- int decimal_rep_length;
-
- DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity,
- &sign, &decimal_rep_length, &decimal_point);
-
- bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
- if (sign && (value != 0.0 || !unique_zero)) {
- result_builder->AddCharacter('-');
- }
-
- int exponent = decimal_point - 1;
- if ((decimal_in_shortest_low_ <= exponent) &&
- (exponent < decimal_in_shortest_high_)) {
- CreateDecimalRepresentation(decimal_rep, decimal_rep_length,
- decimal_point,
- Max(0, decimal_rep_length - decimal_point),
- result_builder);
- } else {
- CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
- result_builder);
- }
- return true;
-}
-
-
-bool DoubleToStringConverter::ToFixed(double value,
- int requested_digits,
- StringBuilder* result_builder) const {
- ASSERT(kMaxFixedDigitsBeforePoint == 60);
- const double kFirstNonFixed = 1e60;
-
- if (Double(value).IsSpecial()) {
- return HandleSpecialValues(value, result_builder);
- }
-
- if (requested_digits > kMaxFixedDigitsAfterPoint) return false;
- if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false;
-
- // Find a sufficiently precise decimal representation of n.
- int decimal_point;
- bool sign;
- // Add space for the '\0' byte.
- const int kDecimalRepCapacity =
- kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
- char decimal_rep[kDecimalRepCapacity];
- int decimal_rep_length;
- DoubleToAscii(value, FIXED, requested_digits,
- decimal_rep, kDecimalRepCapacity,
- &sign, &decimal_rep_length, &decimal_point);
-
- bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
- if (sign && (value != 0.0 || !unique_zero)) {
- result_builder->AddCharacter('-');
- }
-
- CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
- requested_digits, result_builder);
- return true;
-}
-
-
-bool DoubleToStringConverter::ToExponential(
- double value,
- int requested_digits,
- StringBuilder* result_builder) const {
- if (Double(value).IsSpecial()) {
- return HandleSpecialValues(value, result_builder);
- }
-
- if (requested_digits < -1) return false;
- if (requested_digits > kMaxExponentialDigits) return false;
-
- int decimal_point;
- bool sign;
- // Add space for digit before the decimal point and the '\0' character.
- const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
- ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
- char decimal_rep[kDecimalRepCapacity];
- int decimal_rep_length;
-
- if (requested_digits == -1) {
- DoubleToAscii(value, SHORTEST, 0,
- decimal_rep, kDecimalRepCapacity,
- &sign, &decimal_rep_length, &decimal_point);
- } else {
- DoubleToAscii(value, PRECISION, requested_digits + 1,
- decimal_rep, kDecimalRepCapacity,
- &sign, &decimal_rep_length, &decimal_point);
- ASSERT(decimal_rep_length <= requested_digits + 1);
-
- for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
- decimal_rep[i] = '0';
- }
- decimal_rep_length = requested_digits + 1;
- }
-
- bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
- if (sign && (value != 0.0 || !unique_zero)) {
- result_builder->AddCharacter('-');
- }
-
- int exponent = decimal_point - 1;
- CreateExponentialRepresentation(decimal_rep,
- decimal_rep_length,
- exponent,
- result_builder);
- return true;
-}
-
-
-bool DoubleToStringConverter::ToPrecision(double value,
- int precision,
- StringBuilder* result_builder) const {
- if (Double(value).IsSpecial()) {
- return HandleSpecialValues(value, result_builder);
- }
-
- if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
- return false;
- }
-
- // Find a sufficiently precise decimal representation of n.
- int decimal_point;
- bool sign;
- // Add one for the terminating null character.
- const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;
- char decimal_rep[kDecimalRepCapacity];
- int decimal_rep_length;
-
- DoubleToAscii(value, PRECISION, precision,
- decimal_rep, kDecimalRepCapacity,
- &sign, &decimal_rep_length, &decimal_point);
- ASSERT(decimal_rep_length <= precision);
-
- bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
- if (sign && (value != 0.0 || !unique_zero)) {
- result_builder->AddCharacter('-');
- }
-
- // The exponent if we print the number as x.xxeyyy. That is with the
- // decimal point after the first digit.
- int exponent = decimal_point - 1;
-
- int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
- if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
- (decimal_point - precision + extra_zero >
- max_trailing_padding_zeroes_in_precision_mode_)) {
- // Fill buffer to contain 'precision' digits.
- // Usually the buffer is already at the correct length, but 'DoubleToAscii'
- // is allowed to return less characters.
- for (int i = decimal_rep_length; i < precision; ++i) {
- decimal_rep[i] = '0';
- }
-
- CreateExponentialRepresentation(decimal_rep,
- precision,
- exponent,
- result_builder);
- } else {
- CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
- Max(0, precision - decimal_point),
- result_builder);
- }
- return true;
-}
-#endif // not needed for ICU
-
-
-static BignumDtoaMode DtoaToBignumDtoaMode(
- DoubleToStringConverter::DtoaMode dtoa_mode) {
- switch (dtoa_mode) {
- case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST;
- case DoubleToStringConverter::SHORTEST_SINGLE:
- return BIGNUM_DTOA_SHORTEST_SINGLE;
- case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED;
- case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
- default:
- UNREACHABLE();
- }
-}
-
-
-void DoubleToStringConverter::DoubleToAscii(double v,
- DtoaMode mode,
- int requested_digits,
- char* buffer,
- int buffer_length,
- bool* sign,
- int* length,
- int* point) {
- Vector vector(buffer, buffer_length);
- ASSERT(!Double(v).IsSpecial());
- ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0);
-
- if (Double(v).Sign() < 0) {
- *sign = true;
- v = -v;
- } else {
- *sign = false;
- }
-
- if (mode == PRECISION && requested_digits == 0) {
- vector[0] = '\0';
- *length = 0;
- return;
- }
-
- if (v == 0) {
- vector[0] = '0';
- vector[1] = '\0';
- *length = 1;
- *point = 1;
- return;
- }
-
- bool fast_worked;
- switch (mode) {
- case SHORTEST:
- fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
- break;
-#if 0 // not needed for ICU
- case SHORTEST_SINGLE:
- fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0,
- vector, length, point);
- break;
- case FIXED:
- fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
- break;
- case PRECISION:
- fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
- vector, length, point);
- break;
-#endif // not needed for ICU
- default:
- fast_worked = false;
- UNREACHABLE();
- }
- if (fast_worked) return;
-
- // If the fast dtoa didn't succeed use the slower bignum version.
- BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
- BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
- vector[*length] = '\0';
-}
-
-
namespace {
inline char ToLower(char ch) {
@@ -444,7 +62,7 @@ inline char ToLower(char ch) {
return cType.tolower(ch);
#else
(void)ch;
- UNREACHABLE();
+ DOUBLE_CONVERSION_UNREACHABLE();
#endif
}
@@ -457,7 +75,7 @@ static inline bool ConsumeSubStringImpl(Iterator* current,
Iterator end,
const char* substring,
Converter converter) {
- ASSERT(converter(**current) == *substring);
+ DOUBLE_CONVERSION_ASSERT(converter(**current) == *substring);
for (substring++; *substring != '\0'; substring++) {
++*current;
if (*current == end || converter(**current) != *substring) {
@@ -474,8 +92,8 @@ template
static bool ConsumeSubString(Iterator* current,
Iterator end,
const char* substring,
- bool allow_case_insensibility) {
- if (allow_case_insensibility) {
+ bool allow_case_insensitivity) {
+ if (allow_case_insensitivity) {
return ConsumeSubStringImpl(current, end, substring, ToLower);
} else {
return ConsumeSubStringImpl(current, end, substring, Pass);
@@ -485,8 +103,8 @@ static bool ConsumeSubString(Iterator* current,
// Consumes first character of the str is equal to ch
inline bool ConsumeFirstCharacter(char ch,
const char* str,
- bool case_insensibility) {
- return case_insensibility ? ToLower(ch) == str[0] : ch == str[0];
+ bool case_insensitivity) {
+ return case_insensitivity ? ToLower(ch) == str[0] : ch == str[0];
}
} // namespace
@@ -501,15 +119,14 @@ const int kMaxSignificantDigits = 772;
static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 };
-static const int kWhitespaceTable7Length = ARRAY_SIZE(kWhitespaceTable7);
+static const int kWhitespaceTable7Length = DOUBLE_CONVERSION_ARRAY_SIZE(kWhitespaceTable7);
static const uc16 kWhitespaceTable16[] = {
160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195,
8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279
};
-static const int kWhitespaceTable16Length = ARRAY_SIZE(kWhitespaceTable16);
-
+static const int kWhitespaceTable16Length = DOUBLE_CONVERSION_ARRAY_SIZE(kWhitespaceTable16);
static bool isWhitespace(int x) {
@@ -609,7 +226,7 @@ static bool IsHexFloatString(Iterator start,
Iterator end,
uc16 separator,
bool allow_trailing_junk) {
- ASSERT(start != end);
+ DOUBLE_CONVERSION_ASSERT(start != end);
Iterator current = start;
@@ -624,8 +241,8 @@ static bool IsHexFloatString(Iterator start,
saw_digit = true;
if (Advance(¤t, separator, 16, end)) return false;
}
- if (!saw_digit) return false; // Only the '.', but no digits.
}
+ if (!saw_digit) return false;
if (*current != 'p' && *current != 'P') return false;
if (Advance(¤t, separator, 16, end)) return false;
if (*current == '+' || *current == '-') {
@@ -654,8 +271,8 @@ static double RadixStringToIeee(Iterator* current,
double junk_string_value,
bool read_as_double,
bool* result_is_junk) {
- ASSERT(*current != end);
- ASSERT(!parse_as_hex_float ||
+ DOUBLE_CONVERSION_ASSERT(*current != end);
+ DOUBLE_CONVERSION_ASSERT(!parse_as_hex_float ||
IsHexFloatString(*current, end, separator, allow_trailing_junk));
const int kDoubleSize = Double::kSignificandSize;
@@ -693,7 +310,7 @@ static double RadixStringToIeee(Iterator* current,
} else if (parse_as_hex_float && **current == '.') {
post_decimal = true;
Advance(current, separator, radix, end);
- ASSERT(*current != end);
+ DOUBLE_CONVERSION_ASSERT(*current != end);
continue;
} else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) {
break;
@@ -728,7 +345,7 @@ static double RadixStringToIeee(Iterator* current,
// Just run over the '.'. We are just trying to see whether there is
// a non-zero digit somewhere.
Advance(current, separator, radix, end);
- ASSERT(*current != end);
+ DOUBLE_CONVERSION_ASSERT(*current != end);
post_decimal = true;
}
if (!isDigit(**current, radix)) break;
@@ -763,27 +380,31 @@ static double RadixStringToIeee(Iterator* current,
if (Advance(current, separator, radix, end)) break;
}
- ASSERT(number < ((int64_t)1 << kSignificandSize));
- ASSERT(static_cast(static_cast(number)) == number);
+ DOUBLE_CONVERSION_ASSERT(number < ((int64_t)1 << kSignificandSize));
+ DOUBLE_CONVERSION_ASSERT(static_cast(static_cast(number)) == number);
*result_is_junk = false;
if (parse_as_hex_float) {
- ASSERT(**current == 'p' || **current == 'P');
+ DOUBLE_CONVERSION_ASSERT(**current == 'p' || **current == 'P');
Advance(current, separator, radix, end);
- ASSERT(*current != end);
+ DOUBLE_CONVERSION_ASSERT(*current != end);
bool is_negative = false;
if (**current == '+') {
Advance(current, separator, radix, end);
- ASSERT(*current != end);
+ DOUBLE_CONVERSION_ASSERT(*current != end);
} else if (**current == '-') {
is_negative = true;
Advance(current, separator, radix, end);
- ASSERT(*current != end);
+ DOUBLE_CONVERSION_ASSERT(*current != end);
}
int written_exponent = 0;
while (IsDecimalDigitForRadix(**current, 10)) {
- written_exponent = 10 * written_exponent + **current - '0';
+ // No need to read exponents if they are too big. That could potentially overflow
+ // the `written_exponent` variable.
+ if (abs(written_exponent) <= 100 * Double::kMaxExponent) {
+ written_exponent = 10 * written_exponent + **current - '0';
+ }
if (Advance(current, separator, radix, end)) break;
}
if (is_negative) written_exponent = -written_exponent;
@@ -798,7 +419,7 @@ static double RadixStringToIeee(Iterator* current,
return static_cast(number);
}
- ASSERT(number != 0);
+ DOUBLE_CONVERSION_ASSERT(number != 0);
double result = Double(DiyFp(number, exponent)).value();
return sign ? -result : result;
}
@@ -818,7 +439,7 @@ double StringToDoubleConverter::StringToIeee(
const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;
const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;
const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;
- const bool allow_case_insensibility = (flags_ & ALLOW_CASE_INSENSIBILITY) != 0;
+ const bool allow_case_insensitivity = (flags_ & ALLOW_CASE_INSENSITIVITY) != 0;
// To make sure that iterator dereferencing is valid the following
// convention is used:
@@ -868,8 +489,8 @@ double StringToDoubleConverter::StringToIeee(
}
if (infinity_symbol_ != NULL) {
- if (ConsumeFirstCharacter(*current, infinity_symbol_, allow_case_insensibility)) {
- if (!ConsumeSubString(¤t, end, infinity_symbol_, allow_case_insensibility)) {
+ if (ConsumeFirstCharacter(*current, infinity_symbol_, allow_case_insensitivity)) {
+ if (!ConsumeSubString(¤t, end, infinity_symbol_, allow_case_insensitivity)) {
return junk_string_value_;
}
@@ -880,15 +501,15 @@ double StringToDoubleConverter::StringToIeee(
return junk_string_value_;
}
- ASSERT(buffer_pos == 0);
+ DOUBLE_CONVERSION_ASSERT(buffer_pos == 0);
*processed_characters_count = static_cast(current - input);
return sign ? -Double::Infinity() : Double::Infinity();
}
}
if (nan_symbol_ != NULL) {
- if (ConsumeFirstCharacter(*current, nan_symbol_, allow_case_insensibility)) {
- if (!ConsumeSubString(¤t, end, nan_symbol_, allow_case_insensibility)) {
+ if (ConsumeFirstCharacter(*current, nan_symbol_, allow_case_insensitivity)) {
+ if (!ConsumeSubString(¤t, end, nan_symbol_, allow_case_insensitivity)) {
return junk_string_value_;
}
@@ -899,7 +520,7 @@ double StringToDoubleConverter::StringToIeee(
return junk_string_value_;
}
- ASSERT(buffer_pos == 0);
+ DOUBLE_CONVERSION_ASSERT(buffer_pos == 0);
*processed_characters_count = static_cast(current - input);
return sign ? -Double::NaN() : Double::NaN();
}
@@ -919,10 +540,11 @@ double StringToDoubleConverter::StringToIeee(
(*current == 'x' || *current == 'X')) {
++current;
+ if (current == end) return junk_string_value_; // "0x"
+
bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) &&
IsHexFloatString(current, end, separator_, allow_trailing_junk);
- if (current == end) return junk_string_value_; // "0x"
if (!parse_as_hex_float && !isDigit(*current, 16)) {
return junk_string_value_;
}
@@ -958,7 +580,7 @@ double StringToDoubleConverter::StringToIeee(
// Copy significant digits of the integer part (if any) to the buffer.
while (*current >= '0' && *current <= '9') {
if (significant_digits < kMaxSignificantDigits) {
- ASSERT(buffer_pos < kBufferSize);
+ DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos++] = static_cast(*current);
significant_digits++;
// Will later check if it's an octal in the buffer.
@@ -1003,7 +625,7 @@ double StringToDoubleConverter::StringToIeee(
// We don't emit a '.', but adjust the exponent instead.
while (*current >= '0' && *current <= '9') {
if (significant_digits < kMaxSignificantDigits) {
- ASSERT(buffer_pos < kBufferSize);
+ DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos++] = static_cast(*current);
significant_digits++;
exponent--;
@@ -1061,7 +683,7 @@ double StringToDoubleConverter::StringToIeee(
}
const int max_exponent = INT_MAX / 2;
- ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
+ DOUBLE_CONVERSION_ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
int num = 0;
do {
// Check overflow.
@@ -1104,7 +726,7 @@ double StringToDoubleConverter::StringToIeee(
junk_string_value_,
read_as_double,
&result_is_junk);
- ASSERT(!result_is_junk);
+ DOUBLE_CONVERSION_ASSERT(!result_is_junk);
*processed_characters_count = static_cast(current - input);
return result;
}
@@ -1114,7 +736,7 @@ double StringToDoubleConverter::StringToIeee(
exponent--;
}
- ASSERT(buffer_pos < kBufferSize);
+ DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos] = '\0';
double converted;
diff --git a/deps/icu-small/source/i18n/double-conversion-string-to-double.h b/deps/icu-small/source/i18n/double-conversion-string-to-double.h
new file mode 100644
index 00000000000000..2eb0c1f8979838
--- /dev/null
+++ b/deps/icu-small/source/i18n/double-conversion-string-to-double.h
@@ -0,0 +1,244 @@
+// © 2018 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+//
+// From the double-conversion library. Original license:
+//
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ICU PATCH: ifdef around UCONFIG_NO_FORMATTING
+#include "unicode/utypes.h"
+#if !UCONFIG_NO_FORMATTING
+
+#ifndef DOUBLE_CONVERSION_STRING_TO_DOUBLE_H_
+#define DOUBLE_CONVERSION_STRING_TO_DOUBLE_H_
+
+// ICU PATCH: Customize header file paths for ICU.
+
+#include "double-conversion-utils.h"
+
+// ICU PATCH: Wrap in ICU namespace
+U_NAMESPACE_BEGIN
+
+namespace double_conversion {
+
+class StringToDoubleConverter {
+ public:
+ // Enumeration for allowing octals and ignoring junk when converting
+ // strings to numbers.
+ enum Flags {
+ NO_FLAGS = 0,
+ ALLOW_HEX = 1,
+ ALLOW_OCTALS = 2,
+ ALLOW_TRAILING_JUNK = 4,
+ ALLOW_LEADING_SPACES = 8,
+ ALLOW_TRAILING_SPACES = 16,
+ ALLOW_SPACES_AFTER_SIGN = 32,
+ ALLOW_CASE_INSENSITIVITY = 64,
+ ALLOW_CASE_INSENSIBILITY = 64, // Deprecated
+ ALLOW_HEX_FLOATS = 128,
+ };
+
+ static const uc16 kNoSeparator = '\0';
+
+ // Flags should be a bit-or combination of the possible Flags-enum.
+ // - NO_FLAGS: no special flags.
+ // - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers.
+ // Ex: StringToDouble("0x1234") -> 4660.0
+ // In StringToDouble("0x1234.56") the characters ".56" are trailing
+ // junk. The result of the call is hence dependent on
+ // the ALLOW_TRAILING_JUNK flag and/or the junk value.
+ // With this flag "0x" is a junk-string. Even with ALLOW_TRAILING_JUNK,
+ // the string will not be parsed as "0" followed by junk.
+ //
+ // - ALLOW_OCTALS: recognizes the prefix "0" for octals:
+ // If a sequence of octal digits starts with '0', then the number is
+ // read as octal integer. Octal numbers may only be integers.
+ // Ex: StringToDouble("01234") -> 668.0
+ // StringToDouble("012349") -> 12349.0 // Not a sequence of octal
+ // // digits.
+ // In StringToDouble("01234.56") the characters ".56" are trailing
+ // junk. The result of the call is hence dependent on
+ // the ALLOW_TRAILING_JUNK flag and/or the junk value.
+ // In StringToDouble("01234e56") the characters "e56" are trailing
+ // junk, too.
+ // - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of
+ // a double literal.
+ // - ALLOW_LEADING_SPACES: skip over leading whitespace, including spaces,
+ // new-lines, and tabs.
+ // - ALLOW_TRAILING_SPACES: ignore trailing whitespace.
+ // - ALLOW_SPACES_AFTER_SIGN: ignore whitespace after the sign.
+ // Ex: StringToDouble("- 123.2") -> -123.2.
+ // StringToDouble("+ 123.2") -> 123.2
+ // - ALLOW_CASE_INSENSITIVITY: ignore case of characters for special values:
+ // infinity and nan.
+ // - ALLOW_HEX_FLOATS: allows hexadecimal float literals.
+ // This *must* start with "0x" and separate the exponent with "p".
+ // Examples: 0x1.2p3 == 9.0
+ // 0x10.1p0 == 16.0625
+ // ALLOW_HEX and ALLOW_HEX_FLOATS are indendent.
+ //
+ // empty_string_value is returned when an empty string is given as input.
+ // If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string
+ // containing only spaces is converted to the 'empty_string_value', too.
+ //
+ // junk_string_value is returned when
+ // a) ALLOW_TRAILING_JUNK is not set, and a junk character (a character not
+ // part of a double-literal) is found.
+ // b) ALLOW_TRAILING_JUNK is set, but the string does not start with a
+ // double literal.
+ //
+ // infinity_symbol and nan_symbol are strings that are used to detect
+ // inputs that represent infinity and NaN. They can be null, in which case
+ // they are ignored.
+ // The conversion routine first reads any possible signs. Then it compares the
+ // following character of the input-string with the first character of
+ // the infinity, and nan-symbol. If either matches, the function assumes, that
+ // a match has been found, and expects the following input characters to match
+ // the remaining characters of the special-value symbol.
+ // This means that the following restrictions apply to special-value symbols:
+ // - they must not start with signs ('+', or '-'),
+ // - they must not have the same first character.
+ // - they must not start with digits.
+ //
+ // If the separator character is not kNoSeparator, then that specific
+ // character is ignored when in between two valid digits of the significant.
+ // It is not allowed to appear in the exponent.
+ // It is not allowed to lead or trail the number.
+ // It is not allowed to appear twice next to each other.
+ //
+ // Examples:
+ // flags = ALLOW_HEX | ALLOW_TRAILING_JUNK,
+ // empty_string_value = 0.0,
+ // junk_string_value = NaN,
+ // infinity_symbol = "infinity",
+ // nan_symbol = "nan":
+ // StringToDouble("0x1234") -> 4660.0.
+ // StringToDouble("0x1234K") -> 4660.0.
+ // StringToDouble("") -> 0.0 // empty_string_value.
+ // StringToDouble(" ") -> NaN // junk_string_value.
+ // StringToDouble(" 1") -> NaN // junk_string_value.
+ // StringToDouble("0x") -> NaN // junk_string_value.
+ // StringToDouble("-123.45") -> -123.45.
+ // StringToDouble("--123.45") -> NaN // junk_string_value.
+ // StringToDouble("123e45") -> 123e45.
+ // StringToDouble("123E45") -> 123e45.
+ // StringToDouble("123e+45") -> 123e45.
+ // StringToDouble("123E-45") -> 123e-45.
+ // StringToDouble("123e") -> 123.0 // trailing junk ignored.
+ // StringToDouble("123e-") -> 123.0 // trailing junk ignored.
+ // StringToDouble("+NaN") -> NaN // NaN string literal.
+ // StringToDouble("-infinity") -> -inf. // infinity literal.
+ // StringToDouble("Infinity") -> NaN // junk_string_value.
+ //
+ // flags = ALLOW_OCTAL | ALLOW_LEADING_SPACES,
+ // empty_string_value = 0.0,
+ // junk_string_value = NaN,
+ // infinity_symbol = NULL,
+ // nan_symbol = NULL:
+ // StringToDouble("0x1234") -> NaN // junk_string_value.
+ // StringToDouble("01234") -> 668.0.
+ // StringToDouble("") -> 0.0 // empty_string_value.
+ // StringToDouble(" ") -> 0.0 // empty_string_value.
+ // StringToDouble(" 1") -> 1.0
+ // StringToDouble("0x") -> NaN // junk_string_value.
+ // StringToDouble("0123e45") -> NaN // junk_string_value.
+ // StringToDouble("01239E45") -> 1239e45.
+ // StringToDouble("-infinity") -> NaN // junk_string_value.
+ // StringToDouble("NaN") -> NaN // junk_string_value.
+ //
+ // flags = NO_FLAGS,
+ // separator = ' ':
+ // StringToDouble("1 2 3 4") -> 1234.0
+ // StringToDouble("1 2") -> NaN // junk_string_value
+ // StringToDouble("1 000 000.0") -> 1000000.0
+ // StringToDouble("1.000 000") -> 1.0
+ // StringToDouble("1.0e1 000") -> NaN // junk_string_value
+ StringToDoubleConverter(int flags,
+ double empty_string_value,
+ double junk_string_value,
+ const char* infinity_symbol,
+ const char* nan_symbol,
+ uc16 separator = kNoSeparator)
+ : flags_(flags),
+ empty_string_value_(empty_string_value),
+ junk_string_value_(junk_string_value),
+ infinity_symbol_(infinity_symbol),
+ nan_symbol_(nan_symbol),
+ separator_(separator) {
+ }
+
+ // Performs the conversion.
+ // The output parameter 'processed_characters_count' is set to the number
+ // of characters that have been processed to read the number.
+ // Spaces than are processed with ALLOW_{LEADING|TRAILING}_SPACES are included
+ // in the 'processed_characters_count'. Trailing junk is never included.
+ double StringToDouble(const char* buffer,
+ int length,
+ int* processed_characters_count) const;
+
+ // Same as StringToDouble above but for 16 bit characters.
+ double StringToDouble(const uc16* buffer,
+ int length,
+ int* processed_characters_count) const;
+
+ // Same as StringToDouble but reads a float.
+ // Note that this is not equivalent to static_cast(StringToDouble(...))
+ // due to potential double-rounding.
+ float StringToFloat(const char* buffer,
+ int length,
+ int* processed_characters_count) const;
+
+ // Same as StringToFloat above but for 16 bit characters.
+ float StringToFloat(const uc16* buffer,
+ int length,
+ int* processed_characters_count) const;
+
+ private:
+ const int flags_;
+ const double empty_string_value_;
+ const double junk_string_value_;
+ const char* const infinity_symbol_;
+ const char* const nan_symbol_;
+ const uc16 separator_;
+
+ template
+ double StringToIeee(Iterator start_pointer,
+ int length,
+ bool read_as_double,
+ int* processed_characters_count) const;
+
+ DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
+};
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+
+#endif // DOUBLE_CONVERSION_STRING_TO_DOUBLE_H_
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/deps/icu-small/source/i18n/double-conversion-strtod.cpp b/deps/icu-small/source/i18n/double-conversion-strtod.cpp
index be9b0b3bce0e76..9cf4854426756c 100644
--- a/deps/icu-small/source/i18n/double-conversion-strtod.cpp
+++ b/deps/icu-small/source/i18n/double-conversion-strtod.cpp
@@ -34,16 +34,15 @@
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
-#include
-#include
+#include
+#include
// ICU PATCH: Customize header file paths for ICU.
-// The file fixed-dtoa.h is not needed.
-#include "double-conversion-strtod.h"
#include "double-conversion-bignum.h"
#include "double-conversion-cached-powers.h"
#include "double-conversion-ieee.h"
+#include "double-conversion-strtod.h"
// ICU PATCH: Wrap in ICU namespace
U_NAMESPACE_BEGIN
@@ -67,7 +66,7 @@ static const int kMaxDecimalPower = 309;
static const int kMinDecimalPower = -324;
// 2^64 = 18446744073709551616
-static const uint64_t kMaxUint64 = UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF);
+static const uint64_t kMaxUint64 = DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF);
static const double exact_powers_of_ten[] = {
@@ -96,7 +95,7 @@ static const double exact_powers_of_ten[] = {
// 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22
10000000000000000000000.0
};
-static const int kExactPowersOfTenSize = ARRAY_SIZE(exact_powers_of_ten);
+static const int kExactPowersOfTenSize = DOUBLE_CONVERSION_ARRAY_SIZE(exact_powers_of_ten);
// Maximum number of significant digits in the decimal representation.
// In fact the value is 772 (see conversions.cc), but to give us some margin
@@ -132,7 +131,7 @@ static void CutToMaxSignificantDigits(Vector buffer,
}
// The input buffer has been trimmed. Therefore the last digit must be
// different from '0'.
- ASSERT(buffer[buffer.length() - 1] != '0');
+ DOUBLE_CONVERSION_ASSERT(buffer[buffer.length() - 1] != '0');
// Set the last digit to be non-zero. This is sufficient to guarantee
// correct rounding.
significant_buffer[kMaxSignificantDecimalDigits - 1] = '1';
@@ -153,7 +152,7 @@ static void TrimAndCut(Vector buffer, int exponent,
exponent += left_trimmed.length() - right_trimmed.length();
if (right_trimmed.length() > kMaxSignificantDecimalDigits) {
(void) space_size; // Mark variable as used.
- ASSERT(space_size >= kMaxSignificantDecimalDigits);
+ DOUBLE_CONVERSION_ASSERT(space_size >= kMaxSignificantDecimalDigits);
CutToMaxSignificantDigits(right_trimmed, exponent,
buffer_copy_space, updated_exponent);
*trimmed = Vector(buffer_copy_space,
@@ -176,7 +175,7 @@ static uint64_t ReadUint64(Vector buffer,
int i = 0;
while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) {
int digit = buffer[i++] - '0';
- ASSERT(0 <= digit && digit <= 9);
+ DOUBLE_CONVERSION_ASSERT(0 <= digit && digit <= 9);
result = 10 * result + digit;
}
*number_of_read_digits = i;
@@ -220,7 +219,7 @@ static bool DoubleStrtod(Vector trimmed,
// Note that the ARM simulator is compiled for 32bits. It therefore exhibits
// the same problem.
return false;
-#endif
+#else
if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
int read_digits;
// The trimmed input fits into a double.
@@ -232,14 +231,14 @@ static bool DoubleStrtod(Vector trimmed,
if (exponent < 0 && -exponent < kExactPowersOfTenSize) {
// 10^-exponent fits into a double.
*result = static_cast(ReadUint64(trimmed, &read_digits));
- ASSERT(read_digits == trimmed.length());
+ DOUBLE_CONVERSION_ASSERT(read_digits == trimmed.length());
*result /= exact_powers_of_ten[-exponent];
return true;
}
if (0 <= exponent && exponent < kExactPowersOfTenSize) {
// 10^exponent fits into a double.
*result = static_cast(ReadUint64(trimmed, &read_digits));
- ASSERT(read_digits == trimmed.length());
+ DOUBLE_CONVERSION_ASSERT(read_digits == trimmed.length());
*result *= exact_powers_of_ten[exponent];
return true;
}
@@ -251,34 +250,35 @@ static bool DoubleStrtod(Vector trimmed,
// 10^remaining_digits. As a result the remaining exponent now fits
// into a double too.
*result = static_cast(ReadUint64(trimmed, &read_digits));
- ASSERT(read_digits == trimmed.length());
+ DOUBLE_CONVERSION_ASSERT(read_digits == trimmed.length());
*result *= exact_powers_of_ten[remaining_digits];
*result *= exact_powers_of_ten[exponent - remaining_digits];
return true;
}
}
return false;
+#endif
}
// Returns 10^exponent as an exact DiyFp.
// The given exponent must be in the range [1; kDecimalExponentDistance[.
static DiyFp AdjustmentPowerOfTen(int exponent) {
- ASSERT(0 < exponent);
- ASSERT(exponent < PowersOfTenCache::kDecimalExponentDistance);
+ DOUBLE_CONVERSION_ASSERT(0 < exponent);
+ DOUBLE_CONVERSION_ASSERT(exponent < PowersOfTenCache::kDecimalExponentDistance);
// Simply hardcode the remaining powers for the given decimal exponent
// distance.
- ASSERT(PowersOfTenCache::kDecimalExponentDistance == 8);
+ DOUBLE_CONVERSION_ASSERT(PowersOfTenCache::kDecimalExponentDistance == 8);
switch (exponent) {
- case 1: return DiyFp(UINT64_2PART_C(0xa0000000, 00000000), -60);
- case 2: return DiyFp(UINT64_2PART_C(0xc8000000, 00000000), -57);
- case 3: return DiyFp(UINT64_2PART_C(0xfa000000, 00000000), -54);
- case 4: return DiyFp(UINT64_2PART_C(0x9c400000, 00000000), -50);
- case 5: return DiyFp(UINT64_2PART_C(0xc3500000, 00000000), -47);
- case 6: return DiyFp(UINT64_2PART_C(0xf4240000, 00000000), -44);
- case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40);
+ case 1: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xa0000000, 00000000), -60);
+ case 2: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xc8000000, 00000000), -57);
+ case 3: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xfa000000, 00000000), -54);
+ case 4: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0x9c400000, 00000000), -50);
+ case 5: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xc3500000, 00000000), -47);
+ case 6: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xf4240000, 00000000), -44);
+ case 7: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0x98968000, 00000000), -40);
default:
- UNREACHABLE();
+ DOUBLE_CONVERSION_UNREACHABLE();
}
}
@@ -307,7 +307,7 @@ static bool DiyFpStrtod(Vector buffer,
input.Normalize();
error <<= old_e - input.e();
- ASSERT(exponent <= PowersOfTenCache::kMaxDecimalExponent);
+ DOUBLE_CONVERSION_ASSERT(exponent <= PowersOfTenCache::kMaxDecimalExponent);
if (exponent < PowersOfTenCache::kMinDecimalExponent) {
*result = 0.0;
return true;
@@ -325,7 +325,7 @@ static bool DiyFpStrtod(Vector buffer,
if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) {
// The product of input with the adjustment power fits into a 64 bit
// integer.
- ASSERT(DiyFp::kSignificandSize == 64);
+ DOUBLE_CONVERSION_ASSERT(DiyFp::kSignificandSize == 64);
} else {
// The adjustment power is exact. There is hence only an error of 0.5.
error += kDenominator / 2;
@@ -367,8 +367,8 @@ static bool DiyFpStrtod(Vector buffer,
precision_digits_count -= shift_amount;
}
// We use uint64_ts now. This only works if the DiyFp uses uint64_ts too.
- ASSERT(DiyFp::kSignificandSize == 64);
- ASSERT(precision_digits_count < 64);
+ DOUBLE_CONVERSION_ASSERT(DiyFp::kSignificandSize == 64);
+ DOUBLE_CONVERSION_ASSERT(precision_digits_count < 64);
uint64_t one64 = 1;
uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1;
uint64_t precision_bits = input.f() & precision_bits_mask;
@@ -407,14 +407,14 @@ static bool DiyFpStrtod(Vector buffer,
static int CompareBufferWithDiyFp(Vector buffer,
int exponent,
DiyFp diy_fp) {
- ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1);
- ASSERT(buffer.length() + exponent > kMinDecimalPower);
- ASSERT(buffer.length() <= kMaxSignificantDecimalDigits);
+ DOUBLE_CONVERSION_ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1);
+ DOUBLE_CONVERSION_ASSERT(buffer.length() + exponent > kMinDecimalPower);
+ DOUBLE_CONVERSION_ASSERT(buffer.length() <= kMaxSignificantDecimalDigits);
// Make sure that the Bignum will be able to hold all our numbers.
// Our Bignum implementation has a separate field for exponents. Shifts will
// consume at most one bigit (< 64 bits).
// ln(10) == 3.3219...
- ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits);
+ DOUBLE_CONVERSION_ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits);
Bignum buffer_bignum;
Bignum diy_fp_bignum;
buffer_bignum.AssignDecimalString(buffer);
@@ -460,18 +460,33 @@ static bool ComputeGuess(Vector trimmed, int exponent,
return false;
}
-double Strtod(Vector buffer, int exponent) {
- char copy_buffer[kMaxSignificantDecimalDigits];
- Vector trimmed;
- int updated_exponent;
- TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits,
- &trimmed, &updated_exponent);
- exponent = updated_exponent;
+#if U_DEBUG // needed for ICU only in debug mode
+static bool IsDigit(const char d) {
+ return ('0' <= d) && (d <= '9');
+}
- double guess;
- bool is_correct = ComputeGuess(trimmed, exponent, &guess);
- if (is_correct) return guess;
+static bool IsNonZeroDigit(const char d) {
+ return ('1' <= d) && (d <= '9');
+}
+
+static bool AssertTrimmedDigits(const Vector& buffer) {
+ for(int i = 0; i < buffer.length(); ++i) {
+ if(!IsDigit(buffer[i])) {
+ return false;
+ }
+ }
+ return (buffer.length() == 0) || (IsNonZeroDigit(buffer[0]) && IsNonZeroDigit(buffer[buffer.length()-1]));
+}
+#endif // needed for ICU only in debug mode
+double StrtodTrimmed(Vector trimmed, int exponent) {
+ DOUBLE_CONVERSION_ASSERT(trimmed.length() <= kMaxSignificantDecimalDigits);
+ DOUBLE_CONVERSION_ASSERT(AssertTrimmedDigits(trimmed));
+ double guess;
+ const bool is_correct = ComputeGuess(trimmed, exponent, &guess);
+ if (is_correct) {
+ return guess;
+ }
DiyFp upper_boundary = Double(guess).UpperBoundary();
int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary);
if (comparison < 0) {
@@ -486,6 +501,39 @@ double Strtod(Vector buffer, int exponent) {
}
}
+double Strtod(Vector buffer, int exponent) {
+ char copy_buffer[kMaxSignificantDecimalDigits];
+ Vector trimmed;
+ int updated_exponent;
+ TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits,
+ &trimmed, &updated_exponent);
+ return StrtodTrimmed(trimmed, updated_exponent);
+}
+
+static float SanitizedDoubletof(double d) {
+ DOUBLE_CONVERSION_ASSERT(d >= 0.0);
+ // ASAN has a sanitize check that disallows casting doubles to floats if
+ // they are too big.
+ // https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#available-checks
+ // The behavior should be covered by IEEE 754, but some projects use this
+ // flag, so work around it.
+ float max_finite = 3.4028234663852885981170418348451692544e+38;
+ // The half-way point between the max-finite and infinity value.
+ // Since infinity has an even significand everything equal or greater than
+ // this value should become infinity.
+ double half_max_finite_infinity =
+ 3.40282356779733661637539395458142568448e+38;
+ if (d >= max_finite) {
+ if (d >= half_max_finite_infinity) {
+ return Single::Infinity();
+ } else {
+ return max_finite;
+ }
+ } else {
+ return static_cast(d);
+ }
+}
+
float Strtof(Vector buffer, int exponent) {
char copy_buffer[kMaxSignificantDecimalDigits];
Vector trimmed;
@@ -497,7 +545,7 @@ float Strtof(Vector buffer, int exponent) {
double double_guess;
bool is_correct = ComputeGuess(trimmed, exponent, &double_guess);
- float float_guess = static_cast(double_guess);
+ float float_guess = SanitizedDoubletof(double_guess);
if (float_guess == double_guess) {
// This shortcut triggers for integer values.
return float_guess;
@@ -520,18 +568,18 @@ float Strtof(Vector buffer, int exponent) {
double double_next = Double(double_guess).NextDouble();
double double_previous = Double(double_guess).PreviousDouble();
- float f1 = static_cast(double_previous);
+ float f1 = SanitizedDoubletof(double_previous);
float f2 = float_guess;
- float f3 = static_cast(double_next);
+ float f3 = SanitizedDoubletof(double_next);
float f4;
if (is_correct) {
f4 = f3;
} else {
double double_next2 = Double(double_next).NextDouble();
- f4 = static_cast(double_next2);
+ f4 = SanitizedDoubletof(double_next2);
}
(void) f2; // Mark variable as used.
- ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4);
+ DOUBLE_CONVERSION_ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4);
// If the guess doesn't lie near a single-precision boundary we can simply
// return its float-value.
@@ -539,11 +587,11 @@ float Strtof(Vector buffer, int exponent) {
return float_guess;
}
- ASSERT((f1 != f2 && f2 == f3 && f3 == f4) ||
+ DOUBLE_CONVERSION_ASSERT((f1 != f2 && f2 == f3 && f3 == f4) ||
(f1 == f2 && f2 != f3 && f3 == f4) ||
(f1 == f2 && f2 == f3 && f3 != f4));
- // guess and next are the two possible canditates (in the same way that
+ // guess and next are the two possible candidates (in the same way that
// double_guess was the lower candidate for a double-precision guess).
float guess = f1;
float next = f4;
diff --git a/deps/icu-small/source/i18n/double-conversion-strtod.h b/deps/icu-small/source/i18n/double-conversion-strtod.h
index e2d6d3c2fe5d7d..50ef746401a908 100644
--- a/deps/icu-small/source/i18n/double-conversion-strtod.h
+++ b/deps/icu-small/source/i18n/double-conversion-strtod.h
@@ -54,6 +54,11 @@ double Strtod(Vector buffer, int exponent);
// contain a dot or a sign. It must not start with '0', and must not be empty.
float Strtof(Vector buffer, int exponent);
+// For special use cases, the heart of the Strtod() function is also available
+// separately, it assumes that 'trimmed' is as produced by TrimAndCut(), i.e.
+// no leading or trailing zeros, also no lone zero, and not 'too many' digits.
+double StrtodTrimmed(Vector trimmed, int exponent);
+
} // namespace double_conversion
// ICU PATCH: Close ICU namespace
diff --git a/deps/icu-small/source/i18n/double-conversion-utils.h b/deps/icu-small/source/i18n/double-conversion-utils.h
index 1e44fcaa0e398d..099298460c63d9 100644
--- a/deps/icu-small/source/i18n/double-conversion-utils.h
+++ b/deps/icu-small/source/i18n/double-conversion-utils.h
@@ -42,10 +42,12 @@
// ICU PATCH: Use U_ASSERT instead of
#include "uassert.h"
-#define ASSERT U_ASSERT
-
-#ifndef UNIMPLEMENTED
-#define UNIMPLEMENTED() (abort())
+#ifndef DOUBLE_CONVERSION_ASSERT
+#define DOUBLE_CONVERSION_ASSERT(condition) \
+ U_ASSERT(condition);
+#endif
+#ifndef DOUBLE_CONVERSION_UNIMPLEMENTED
+#define DOUBLE_CONVERSION_UNIMPLEMENTED() (abort())
#endif
#ifndef DOUBLE_CONVERSION_NO_RETURN
#ifdef _MSC_VER
@@ -54,16 +56,23 @@
#define DOUBLE_CONVERSION_NO_RETURN __attribute__((noreturn))
#endif
#endif
-#ifndef UNREACHABLE
+#ifndef DOUBLE_CONVERSION_UNREACHABLE
#ifdef _MSC_VER
void DOUBLE_CONVERSION_NO_RETURN abort_noreturn();
inline void abort_noreturn() { abort(); }
-#define UNREACHABLE() (abort_noreturn())
+#define DOUBLE_CONVERSION_UNREACHABLE() (abort_noreturn())
#else
-#define UNREACHABLE() (abort())
+#define DOUBLE_CONVERSION_UNREACHABLE() (abort())
#endif
#endif
+#ifndef DOUBLE_CONVERSION_UNUSED
+#ifdef __GNUC__
+#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
+#else
+#define DOUBLE_CONVERSION_UNUSED
+#endif
+#endif
// Double operations detection based on target architecture.
// Linux uses a 80bit wide floating point stack on x86. This induces double
@@ -99,9 +108,9 @@ int main(int argc, char** argv) {
defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
defined(__SH4__) || defined(__alpha__) || \
- defined(_MIPS_ARCH_MIPS32R2) || \
+ defined(_MIPS_ARCH_MIPS32R2) || defined(__ARMEB__) ||\
defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \
- defined(__riscv) || \
+ defined(__riscv) || defined(__e2k__) || \
defined(__or1k__) || defined(__arc__) || \
defined(__EMSCRIPTEN__)
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
@@ -141,24 +150,24 @@ typedef uint16_t uc16;
// The following macro works on both 32 and 64-bit platforms.
// Usage: instead of writing 0x1234567890123456
-// write UINT64_2PART_C(0x12345678,90123456);
-#define UINT64_2PART_C(a, b) (((static_cast(a) << 32) + 0x##b##u))
+// write DOUBLE_CONVERSION_UINT64_2PART_C(0x12345678,90123456);
+#define DOUBLE_CONVERSION_UINT64_2PART_C(a, b) (((static_cast(a) << 32) + 0x##b##u))
-// The expression ARRAY_SIZE(a) is a compile-time constant of type
+// The expression DOUBLE_CONVERSION_ARRAY_SIZE(a) is a compile-time constant of type
// size_t which represents the number of elements of the given
-// array. You should only use ARRAY_SIZE on statically allocated
+// array. You should only use DOUBLE_CONVERSION_ARRAY_SIZE on statically allocated
// arrays.
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(a) \
+#ifndef DOUBLE_CONVERSION_ARRAY_SIZE
+#define DOUBLE_CONVERSION_ARRAY_SIZE(a) \
((sizeof(a) / sizeof(*(a))) / \
static_cast(!(sizeof(a) % sizeof(*(a)))))
#endif
// A macro to disallow the evil copy constructor and operator= functions
// This should be used in the private: declarations for a class
-#ifndef DC_DISALLOW_COPY_AND_ASSIGN
-#define DC_DISALLOW_COPY_AND_ASSIGN(TypeName) \
+#ifndef DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN
+#define DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
#endif
@@ -169,10 +178,10 @@ typedef uint16_t uc16;
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
-#ifndef DC_DISALLOW_IMPLICIT_CONSTRUCTORS
-#define DC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+#ifndef DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS
+#define DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName(); \
- DC_DISALLOW_COPY_AND_ASSIGN(TypeName)
+ DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(TypeName)
#endif
// ICU PATCH: Wrap in ICU namespace
@@ -180,25 +189,9 @@ U_NAMESPACE_BEGIN
namespace double_conversion {
-static const int kCharSize = sizeof(char);
-
-// Returns the maximum of the two parameters.
-template
-static T Max(T a, T b) {
- return a < b ? b : a;
-}
-
-
-// Returns the minimum of the two parameters.
-template
-static T Min(T a, T b) {
- return a < b ? a : b;
-}
-
-
inline int StrLength(const char* string) {
size_t length = strlen(string);
- ASSERT(length == static_cast(static_cast(length)));
+ DOUBLE_CONVERSION_ASSERT(length == static_cast(static_cast(length)));
return static_cast(length);
}
@@ -208,15 +201,15 @@ class Vector {
public:
Vector() : start_(NULL), length_(0) {}
Vector(T* data, int len) : start_(data), length_(len) {
- ASSERT(len == 0 || (len > 0 && data != NULL));
+ DOUBLE_CONVERSION_ASSERT(len == 0 || (len > 0 && data != NULL));
}
// Returns a vector using the same backing storage as this one,
// spanning from and including 'from', to but not including 'to'.
Vector SubVector(int from, int to) {
- ASSERT(to <= length_);
- ASSERT(from < to);
- ASSERT(0 <= from);
+ DOUBLE_CONVERSION_ASSERT(to <= length_);
+ DOUBLE_CONVERSION_ASSERT(from < to);
+ DOUBLE_CONVERSION_ASSERT(0 <= from);
return Vector(start() + from, to - from);
}
@@ -231,7 +224,7 @@ class Vector {
// Access individual vector elements - checks bounds in debug mode.
T& operator[](int index) const {
- ASSERT(0 <= index && index < length_);
+ DOUBLE_CONVERSION_ASSERT(0 <= index && index < length_);
return start_[index];
}
@@ -239,6 +232,11 @@ class Vector {
T& last() { return start_[length_ - 1]; }
+ void pop_back() {
+ DOUBLE_CONVERSION_ASSERT(!is_empty());
+ --length_;
+ }
+
private:
T* start_;
int length_;
@@ -259,7 +257,7 @@ class StringBuilder {
// Get the current position in the builder.
int position() const {
- ASSERT(!is_finalized());
+ DOUBLE_CONVERSION_ASSERT(!is_finalized());
return position_;
}
@@ -270,8 +268,8 @@ class StringBuilder {
// 0-characters; use the Finalize() method to terminate the string
// instead.
void AddCharacter(char c) {
- ASSERT(c != '\0');
- ASSERT(!is_finalized() && position_ < buffer_.length());
+ DOUBLE_CONVERSION_ASSERT(c != '\0');
+ DOUBLE_CONVERSION_ASSERT(!is_finalized() && position_ < buffer_.length());
buffer_[position_++] = c;
}
@@ -284,9 +282,9 @@ class StringBuilder {
// Add the first 'n' characters of the given string 's' to the
// builder. The input string must have enough characters.
void AddSubstring(const char* s, int n) {
- ASSERT(!is_finalized() && position_ + n < buffer_.length());
- ASSERT(static_cast(n) <= strlen(s));
- memmove(&buffer_[position_], s, n * kCharSize);
+ DOUBLE_CONVERSION_ASSERT(!is_finalized() && position_ + n < buffer_.length());
+ DOUBLE_CONVERSION_ASSERT(static_cast(n) <= strlen(s));
+ memmove(&buffer_[position_], s, n);
position_ += n;
}
@@ -301,13 +299,13 @@ class StringBuilder {
// Finalize the string by 0-terminating it and returning the buffer.
char* Finalize() {
- ASSERT(!is_finalized() && position_ < buffer_.length());
+ DOUBLE_CONVERSION_ASSERT(!is_finalized() && position_ < buffer_.length());
buffer_[position_] = '\0';
// Make sure nobody managed to add a 0-character to the
// buffer while building the string.
- ASSERT(strlen(buffer_.start()) == static_cast(position_));
+ DOUBLE_CONVERSION_ASSERT(strlen(buffer_.start()) == static_cast(position_));
position_ = -1;
- ASSERT(is_finalized());
+ DOUBLE_CONVERSION_ASSERT(is_finalized());
return buffer_.start();
}
@@ -317,7 +315,7 @@ class StringBuilder {
bool is_finalized() const { return position_ < 0; }
- DC_DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
+ DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
};
// The type-based aliasing rule allows the compiler to assume that pointers of
@@ -345,13 +343,14 @@ class StringBuilder {
// enough that it can no longer see that you have cast one pointer type to
// another thus avoiding the warning.
template
-inline Dest BitCast(const Source& source) {
+Dest BitCast(const Source& source) {
// Compile time assertion: sizeof(Dest) == sizeof(Source)
// A compile error here means your Dest and Source have different sizes.
#if __cplusplus >= 201103L
static_assert(sizeof(Dest) == sizeof(Source),
"source and destination size mismatch");
#else
+ DOUBLE_CONVERSION_UNUSED
typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
#endif
@@ -361,7 +360,7 @@ inline Dest BitCast(const Source& source) {
}
template
-inline Dest BitCast(Source* source) {
+Dest BitCast(Source* source) {
return BitCast(reinterpret_cast(source));
}
diff --git a/deps/icu-small/source/i18n/double-conversion.h b/deps/icu-small/source/i18n/double-conversion.h
index 377c710bf791e7..eddc38763becdc 100644
--- a/deps/icu-small/source/i18n/double-conversion.h
+++ b/deps/icu-small/source/i18n/double-conversion.h
@@ -39,561 +39,8 @@
// ICU PATCH: Customize header file paths for ICU.
-#include "double-conversion-utils.h"
-
-// ICU PATCH: Wrap in ICU namespace
-U_NAMESPACE_BEGIN
-
-namespace double_conversion {
-
-class DoubleToStringConverter {
- public:
-#if 0 // not needed for ICU
- // When calling ToFixed with a double > 10^kMaxFixedDigitsBeforePoint
- // or a requested_digits parameter > kMaxFixedDigitsAfterPoint then the
- // function returns false.
- static const int kMaxFixedDigitsBeforePoint = 60;
- static const int kMaxFixedDigitsAfterPoint = 60;
-
- // When calling ToExponential with a requested_digits
- // parameter > kMaxExponentialDigits then the function returns false.
- static const int kMaxExponentialDigits = 120;
-
- // When calling ToPrecision with a requested_digits
- // parameter < kMinPrecisionDigits or requested_digits > kMaxPrecisionDigits
- // then the function returns false.
- static const int kMinPrecisionDigits = 1;
- static const int kMaxPrecisionDigits = 120;
-
- enum Flags {
- NO_FLAGS = 0,
- EMIT_POSITIVE_EXPONENT_SIGN = 1,
- EMIT_TRAILING_DECIMAL_POINT = 2,
- EMIT_TRAILING_ZERO_AFTER_POINT = 4,
- UNIQUE_ZERO = 8
- };
-
- // Flags should be a bit-or combination of the possible Flags-enum.
- // - NO_FLAGS: no special flags.
- // - EMIT_POSITIVE_EXPONENT_SIGN: when the number is converted into exponent
- // form, emits a '+' for positive exponents. Example: 1.2e+2.
- // - EMIT_TRAILING_DECIMAL_POINT: when the input number is an integer and is
- // converted into decimal format then a trailing decimal point is appended.
- // Example: 2345.0 is converted to "2345.".
- // - EMIT_TRAILING_ZERO_AFTER_POINT: in addition to a trailing decimal point
- // emits a trailing '0'-character. This flag requires the
- // EXMIT_TRAILING_DECIMAL_POINT flag.
- // Example: 2345.0 is converted to "2345.0".
- // - UNIQUE_ZERO: "-0.0" is converted to "0.0".
- //
- // Infinity symbol and nan_symbol provide the string representation for these
- // special values. If the string is NULL and the special value is encountered
- // then the conversion functions return false.
- //
- // The exponent_character is used in exponential representations. It is
- // usually 'e' or 'E'.
- //
- // When converting to the shortest representation the converter will
- // represent input numbers in decimal format if they are in the interval
- // [10^decimal_in_shortest_low; 10^decimal_in_shortest_high[
- // (lower boundary included, greater boundary excluded).
- // Example: with decimal_in_shortest_low = -6 and
- // decimal_in_shortest_high = 21:
- // ToShortest(0.000001) -> "0.000001"
- // ToShortest(0.0000001) -> "1e-7"
- // ToShortest(111111111111111111111.0) -> "111111111111111110000"
- // ToShortest(100000000000000000000.0) -> "100000000000000000000"
- // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"
- //
- // When converting to precision mode the converter may add
- // max_leading_padding_zeroes before returning the number in exponential
- // format.
- // Example with max_leading_padding_zeroes_in_precision_mode = 6.
- // ToPrecision(0.0000012345, 2) -> "0.0000012"
- // ToPrecision(0.00000012345, 2) -> "1.2e-7"
- // Similarily the converter may add up to
- // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
- // returning an exponential representation. A zero added by the
- // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
- // Examples for max_trailing_padding_zeroes_in_precision_mode = 1:
- // ToPrecision(230.0, 2) -> "230"
- // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT.
- // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
- DoubleToStringConverter(int flags,
- const char* infinity_symbol,
- const char* nan_symbol,
- char exponent_character,
- int decimal_in_shortest_low,
- int decimal_in_shortest_high,
- int max_leading_padding_zeroes_in_precision_mode,
- int max_trailing_padding_zeroes_in_precision_mode)
- : flags_(flags),
- infinity_symbol_(infinity_symbol),
- nan_symbol_(nan_symbol),
- exponent_character_(exponent_character),
- decimal_in_shortest_low_(decimal_in_shortest_low),
- decimal_in_shortest_high_(decimal_in_shortest_high),
- max_leading_padding_zeroes_in_precision_mode_(
- max_leading_padding_zeroes_in_precision_mode),
- max_trailing_padding_zeroes_in_precision_mode_(
- max_trailing_padding_zeroes_in_precision_mode) {
- // When 'trailing zero after the point' is set, then 'trailing point'
- // must be set too.
- ASSERT(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) ||
- !((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0));
- }
-
- // Returns a converter following the EcmaScript specification.
- static const DoubleToStringConverter& EcmaScriptConverter();
-
- // Computes the shortest string of digits that correctly represent the input
- // number. Depending on decimal_in_shortest_low and decimal_in_shortest_high
- // (see constructor) it then either returns a decimal representation, or an
- // exponential representation.
- // Example with decimal_in_shortest_low = -6,
- // decimal_in_shortest_high = 21,
- // EMIT_POSITIVE_EXPONENT_SIGN activated, and
- // EMIT_TRAILING_DECIMAL_POINT deactived:
- // ToShortest(0.000001) -> "0.000001"
- // ToShortest(0.0000001) -> "1e-7"
- // ToShortest(111111111111111111111.0) -> "111111111111111110000"
- // ToShortest(100000000000000000000.0) -> "100000000000000000000"
- // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"
- //
- // Note: the conversion may round the output if the returned string
- // is accurate enough to uniquely identify the input-number.
- // For example the most precise representation of the double 9e59 equals
- // "899999999999999918767229449717619953810131273674690656206848", but
- // the converter will return the shorter (but still correct) "9e59".
- //
- // Returns true if the conversion succeeds. The conversion always succeeds
- // except when the input value is special and no infinity_symbol or
- // nan_symbol has been given to the constructor.
- bool ToShortest(double value, StringBuilder* result_builder) const {
- return ToShortestIeeeNumber(value, result_builder, SHORTEST);
- }
-
- // Same as ToShortest, but for single-precision floats.
- bool ToShortestSingle(float value, StringBuilder* result_builder) const {
- return ToShortestIeeeNumber(value, result_builder, SHORTEST_SINGLE);
- }
-
-
- // Computes a decimal representation with a fixed number of digits after the
- // decimal point. The last emitted digit is rounded.
- //
- // Examples:
- // ToFixed(3.12, 1) -> "3.1"
- // ToFixed(3.1415, 3) -> "3.142"
- // ToFixed(1234.56789, 4) -> "1234.5679"
- // ToFixed(1.23, 5) -> "1.23000"
- // ToFixed(0.1, 4) -> "0.1000"
- // ToFixed(1e30, 2) -> "1000000000000000019884624838656.00"
- // ToFixed(0.1, 30) -> "0.100000000000000005551115123126"
- // ToFixed(0.1, 17) -> "0.10000000000000001"
- //
- // If requested_digits equals 0, then the tail of the result depends on
- // the EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT.
- // Examples, for requested_digits == 0,
- // let EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT be
- // - false and false: then 123.45 -> 123
- // 0.678 -> 1
- // - true and false: then 123.45 -> 123.
- // 0.678 -> 1.
- // - true and true: then 123.45 -> 123.0
- // 0.678 -> 1.0
- //
- // Returns true if the conversion succeeds. The conversion always succeeds
- // except for the following cases:
- // - the input value is special and no infinity_symbol or nan_symbol has
- // been provided to the constructor,
- // - 'value' > 10^kMaxFixedDigitsBeforePoint, or
- // - 'requested_digits' > kMaxFixedDigitsAfterPoint.
- // The last two conditions imply that the result will never contain more than
- // 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters
- // (one additional character for the sign, and one for the decimal point).
- bool ToFixed(double value,
- int requested_digits,
- StringBuilder* result_builder) const;
-
- // Computes a representation in exponential format with requested_digits
- // after the decimal point. The last emitted digit is rounded.
- // If requested_digits equals -1, then the shortest exponential representation
- // is computed.
- //
- // Examples with EMIT_POSITIVE_EXPONENT_SIGN deactivated, and
- // exponent_character set to 'e'.
- // ToExponential(3.12, 1) -> "3.1e0"
- // ToExponential(5.0, 3) -> "5.000e0"
- // ToExponential(0.001, 2) -> "1.00e-3"
- // ToExponential(3.1415, -1) -> "3.1415e0"
- // ToExponential(3.1415, 4) -> "3.1415e0"
- // ToExponential(3.1415, 3) -> "3.142e0"
- // ToExponential(123456789000000, 3) -> "1.235e14"
- // ToExponential(1000000000000000019884624838656.0, -1) -> "1e30"
- // ToExponential(1000000000000000019884624838656.0, 32) ->
- // "1.00000000000000001988462483865600e30"
- // ToExponential(1234, 0) -> "1e3"
- //
- // Returns true if the conversion succeeds. The conversion always succeeds
- // except for the following cases:
- // - the input value is special and no infinity_symbol or nan_symbol has
- // been provided to the constructor,
- // - 'requested_digits' > kMaxExponentialDigits.
- // The last condition implies that the result will never contain more than
- // kMaxExponentialDigits + 8 characters (the sign, the digit before the
- // decimal point, the decimal point, the exponent character, the
- // exponent's sign, and at most 3 exponent digits).
- bool ToExponential(double value,
- int requested_digits,
- StringBuilder* result_builder) const;
-
- // Computes 'precision' leading digits of the given 'value' and returns them
- // either in exponential or decimal format, depending on
- // max_{leading|trailing}_padding_zeroes_in_precision_mode (given to the
- // constructor).
- // The last computed digit is rounded.
- //
- // Example with max_leading_padding_zeroes_in_precision_mode = 6.
- // ToPrecision(0.0000012345, 2) -> "0.0000012"
- // ToPrecision(0.00000012345, 2) -> "1.2e-7"
- // Similarily the converter may add up to
- // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
- // returning an exponential representation. A zero added by the
- // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
- // Examples for max_trailing_padding_zeroes_in_precision_mode = 1:
- // ToPrecision(230.0, 2) -> "230"
- // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT.
- // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
- // Examples for max_trailing_padding_zeroes_in_precision_mode = 3, and no
- // EMIT_TRAILING_ZERO_AFTER_POINT:
- // ToPrecision(123450.0, 6) -> "123450"
- // ToPrecision(123450.0, 5) -> "123450"
- // ToPrecision(123450.0, 4) -> "123500"
- // ToPrecision(123450.0, 3) -> "123000"
- // ToPrecision(123450.0, 2) -> "1.2e5"
- //
- // Returns true if the conversion succeeds. The conversion always succeeds
- // except for the following cases:
- // - the input value is special and no infinity_symbol or nan_symbol has
- // been provided to the constructor,
- // - precision < kMinPericisionDigits
- // - precision > kMaxPrecisionDigits
- // The last condition implies that the result will never contain more than
- // kMaxPrecisionDigits + 7 characters (the sign, the decimal point, the
- // exponent character, the exponent's sign, and at most 3 exponent digits).
- bool ToPrecision(double value,
- int precision,
- StringBuilder* result_builder) const;
-#endif // not needed for ICU
-
- enum DtoaMode {
- // Produce the shortest correct representation.
- // For example the output of 0.299999999999999988897 is (the less accurate
- // but correct) 0.3.
- SHORTEST,
- // Same as SHORTEST, but for single-precision floats.
- SHORTEST_SINGLE,
- // Produce a fixed number of digits after the decimal point.
- // For instance fixed(0.1, 4) becomes 0.1000
- // If the input number is big, the output will be big.
- FIXED,
- // Fixed number of digits (independent of the decimal point).
- PRECISION
- };
-
- // The maximal number of digits that are needed to emit a double in base 10.
- // A higher precision can be achieved by using more digits, but the shortest
- // accurate representation of any double will never use more digits than
- // kBase10MaximalLength.
- // Note that DoubleToAscii null-terminates its input. So the given buffer
- // should be at least kBase10MaximalLength + 1 characters long.
- static const int kBase10MaximalLength = 17;
-
- // Converts the given double 'v' to digit characters. 'v' must not be NaN,
- // +Infinity, or -Infinity. In SHORTEST_SINGLE-mode this restriction also
- // applies to 'v' after it has been casted to a single-precision float. That
- // is, in this mode static_cast(v) must not be NaN, +Infinity or
- // -Infinity.
- //
- // The result should be interpreted as buffer * 10^(point-length).
- //
- // The digits are written to the buffer in the platform's charset, which is
- // often UTF-8 (with ASCII-range digits) but may be another charset, such
- // as EBCDIC.
- //
- // The output depends on the given mode:
- // - SHORTEST: produce the least amount of digits for which the internal
- // identity requirement is still satisfied. If the digits are printed
- // (together with the correct exponent) then reading this number will give
- // 'v' again. The buffer will choose the representation that is closest to
- // 'v'. If there are two at the same distance, than the one farther away
- // from 0 is chosen (halfway cases - ending with 5 - are rounded up).
- // In this mode the 'requested_digits' parameter is ignored.
- // - SHORTEST_SINGLE: same as SHORTEST but with single-precision.
- // - FIXED: produces digits necessary to print a given number with
- // 'requested_digits' digits after the decimal point. The produced digits
- // might be too short in which case the caller has to fill the remainder
- // with '0's.
- // Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.
- // Halfway cases are rounded towards +/-Infinity (away from 0). The call
- // toFixed(0.15, 2) thus returns buffer="2", point=0.
- // The returned buffer may contain digits that would be truncated from the
- // shortest representation of the input.
- // - PRECISION: produces 'requested_digits' where the first digit is not '0'.
- // Even though the length of produced digits usually equals
- // 'requested_digits', the function is allowed to return fewer digits, in
- // which case the caller has to fill the missing digits with '0's.
- // Halfway cases are again rounded away from 0.
- // DoubleToAscii expects the given buffer to be big enough to hold all
- // digits and a terminating null-character. In SHORTEST-mode it expects a
- // buffer of at least kBase10MaximalLength + 1. In all other modes the
- // requested_digits parameter and the padding-zeroes limit the size of the
- // output. Don't forget the decimal point, the exponent character and the
- // terminating null-character when computing the maximal output size.
- // The given length is only used in debug mode to ensure the buffer is big
- // enough.
- // ICU PATCH: Export this as U_I18N_API for unit tests.
- static void U_I18N_API DoubleToAscii(double v,
- DtoaMode mode,
- int requested_digits,
- char* buffer,
- int buffer_length,
- bool* sign,
- int* length,
- int* point);
-
-#if 0 // not needed for ICU
- private:
- // Implementation for ToShortest and ToShortestSingle.
- bool ToShortestIeeeNumber(double value,
- StringBuilder* result_builder,
- DtoaMode mode) const;
-
- // If the value is a special value (NaN or Infinity) constructs the
- // corresponding string using the configured infinity/nan-symbol.
- // If either of them is NULL or the value is not special then the
- // function returns false.
- bool HandleSpecialValues(double value, StringBuilder* result_builder) const;
- // Constructs an exponential representation (i.e. 1.234e56).
- // The given exponent assumes a decimal point after the first decimal digit.
- void CreateExponentialRepresentation(const char* decimal_digits,
- int length,
- int exponent,
- StringBuilder* result_builder) const;
- // Creates a decimal representation (i.e 1234.5678).
- void CreateDecimalRepresentation(const char* decimal_digits,
- int length,
- int decimal_point,
- int digits_after_point,
- StringBuilder* result_builder) const;
-
- const int flags_;
- const char* const infinity_symbol_;
- const char* const nan_symbol_;
- const char exponent_character_;
- const int decimal_in_shortest_low_;
- const int decimal_in_shortest_high_;
- const int max_leading_padding_zeroes_in_precision_mode_;
- const int max_trailing_padding_zeroes_in_precision_mode_;
-#endif // not needed for ICU
-
- DC_DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
-};
-
-
-class StringToDoubleConverter {
- public:
- // Enumeration for allowing octals and ignoring junk when converting
- // strings to numbers.
- enum Flags {
- NO_FLAGS = 0,
- ALLOW_HEX = 1,
- ALLOW_OCTALS = 2,
- ALLOW_TRAILING_JUNK = 4,
- ALLOW_LEADING_SPACES = 8,
- ALLOW_TRAILING_SPACES = 16,
- ALLOW_SPACES_AFTER_SIGN = 32,
- ALLOW_CASE_INSENSIBILITY = 64,
- ALLOW_HEX_FLOATS = 128,
- };
-
- static const uc16 kNoSeparator = '\0';
-
- // Flags should be a bit-or combination of the possible Flags-enum.
- // - NO_FLAGS: no special flags.
- // - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers.
- // Ex: StringToDouble("0x1234") -> 4660.0
- // In StringToDouble("0x1234.56") the characters ".56" are trailing
- // junk. The result of the call is hence dependent on
- // the ALLOW_TRAILING_JUNK flag and/or the junk value.
- // With this flag "0x" is a junk-string. Even with ALLOW_TRAILING_JUNK,
- // the string will not be parsed as "0" followed by junk.
- //
- // - ALLOW_OCTALS: recognizes the prefix "0" for octals:
- // If a sequence of octal digits starts with '0', then the number is
- // read as octal integer. Octal numbers may only be integers.
- // Ex: StringToDouble("01234") -> 668.0
- // StringToDouble("012349") -> 12349.0 // Not a sequence of octal
- // // digits.
- // In StringToDouble("01234.56") the characters ".56" are trailing
- // junk. The result of the call is hence dependent on
- // the ALLOW_TRAILING_JUNK flag and/or the junk value.
- // In StringToDouble("01234e56") the characters "e56" are trailing
- // junk, too.
- // - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of
- // a double literal.
- // - ALLOW_LEADING_SPACES: skip over leading whitespace, including spaces,
- // new-lines, and tabs.
- // - ALLOW_TRAILING_SPACES: ignore trailing whitespace.
- // - ALLOW_SPACES_AFTER_SIGN: ignore whitespace after the sign.
- // Ex: StringToDouble("- 123.2") -> -123.2.
- // StringToDouble("+ 123.2") -> 123.2
- // - ALLOW_CASE_INSENSIBILITY: ignore case of characters for special values:
- // infinity and nan.
- // - ALLOW_HEX_FLOATS: allows hexadecimal float literals.
- // This *must* start with "0x" and separate the exponent with "p".
- // Examples: 0x1.2p3 == 9.0
- // 0x10.1p0 == 16.0625
- // ALLOW_HEX and ALLOW_HEX_FLOATS are indendent.
- //
- // empty_string_value is returned when an empty string is given as input.
- // If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string
- // containing only spaces is converted to the 'empty_string_value', too.
- //
- // junk_string_value is returned when
- // a) ALLOW_TRAILING_JUNK is not set, and a junk character (a character not
- // part of a double-literal) is found.
- // b) ALLOW_TRAILING_JUNK is set, but the string does not start with a
- // double literal.
- //
- // infinity_symbol and nan_symbol are strings that are used to detect
- // inputs that represent infinity and NaN. They can be null, in which case
- // they are ignored.
- // The conversion routine first reads any possible signs. Then it compares the
- // following character of the input-string with the first character of
- // the infinity, and nan-symbol. If either matches, the function assumes, that
- // a match has been found, and expects the following input characters to match
- // the remaining characters of the special-value symbol.
- // This means that the following restrictions apply to special-value symbols:
- // - they must not start with signs ('+', or '-'),
- // - they must not have the same first character.
- // - they must not start with digits.
- //
- // If the separator character is not kNoSeparator, then that specific
- // character is ignored when in between two valid digits of the significant.
- // It is not allowed to appear in the exponent.
- // It is not allowed to lead or trail the number.
- // It is not allowed to appear twice next to each other.
- //
- // Examples:
- // flags = ALLOW_HEX | ALLOW_TRAILING_JUNK,
- // empty_string_value = 0.0,
- // junk_string_value = NaN,
- // infinity_symbol = "infinity",
- // nan_symbol = "nan":
- // StringToDouble("0x1234") -> 4660.0.
- // StringToDouble("0x1234K") -> 4660.0.
- // StringToDouble("") -> 0.0 // empty_string_value.
- // StringToDouble(" ") -> NaN // junk_string_value.
- // StringToDouble(" 1") -> NaN // junk_string_value.
- // StringToDouble("0x") -> NaN // junk_string_value.
- // StringToDouble("-123.45") -> -123.45.
- // StringToDouble("--123.45") -> NaN // junk_string_value.
- // StringToDouble("123e45") -> 123e45.
- // StringToDouble("123E45") -> 123e45.
- // StringToDouble("123e+45") -> 123e45.
- // StringToDouble("123E-45") -> 123e-45.
- // StringToDouble("123e") -> 123.0 // trailing junk ignored.
- // StringToDouble("123e-") -> 123.0 // trailing junk ignored.
- // StringToDouble("+NaN") -> NaN // NaN string literal.
- // StringToDouble("-infinity") -> -inf. // infinity literal.
- // StringToDouble("Infinity") -> NaN // junk_string_value.
- //
- // flags = ALLOW_OCTAL | ALLOW_LEADING_SPACES,
- // empty_string_value = 0.0,
- // junk_string_value = NaN,
- // infinity_symbol = NULL,
- // nan_symbol = NULL:
- // StringToDouble("0x1234") -> NaN // junk_string_value.
- // StringToDouble("01234") -> 668.0.
- // StringToDouble("") -> 0.0 // empty_string_value.
- // StringToDouble(" ") -> 0.0 // empty_string_value.
- // StringToDouble(" 1") -> 1.0
- // StringToDouble("0x") -> NaN // junk_string_value.
- // StringToDouble("0123e45") -> NaN // junk_string_value.
- // StringToDouble("01239E45") -> 1239e45.
- // StringToDouble("-infinity") -> NaN // junk_string_value.
- // StringToDouble("NaN") -> NaN // junk_string_value.
- //
- // flags = NO_FLAGS,
- // separator = ' ':
- // StringToDouble("1 2 3 4") -> 1234.0
- // StringToDouble("1 2") -> NaN // junk_string_value
- // StringToDouble("1 000 000.0") -> 1000000.0
- // StringToDouble("1.000 000") -> 1.0
- // StringToDouble("1.0e1 000") -> NaN // junk_string_value
- StringToDoubleConverter(int flags,
- double empty_string_value,
- double junk_string_value,
- const char* infinity_symbol,
- const char* nan_symbol,
- uc16 separator = kNoSeparator)
- : flags_(flags),
- empty_string_value_(empty_string_value),
- junk_string_value_(junk_string_value),
- infinity_symbol_(infinity_symbol),
- nan_symbol_(nan_symbol),
- separator_(separator) {
- }
-
- // Performs the conversion.
- // The output parameter 'processed_characters_count' is set to the number
- // of characters that have been processed to read the number.
- // Spaces than are processed with ALLOW_{LEADING|TRAILING}_SPACES are included
- // in the 'processed_characters_count'. Trailing junk is never included.
- double StringToDouble(const char* buffer,
- int length,
- int* processed_characters_count) const;
-
- // Same as StringToDouble above but for 16 bit characters.
- double StringToDouble(const uc16* buffer,
- int length,
- int* processed_characters_count) const;
-
- // Same as StringToDouble but reads a float.
- // Note that this is not equivalent to static_cast(StringToDouble(...))
- // due to potential double-rounding.
- float StringToFloat(const char* buffer,
- int length,
- int* processed_characters_count) const;
-
- // Same as StringToFloat above but for 16 bit characters.
- float StringToFloat(const uc16* buffer,
- int length,
- int* processed_characters_count) const;
-
- private:
- const int flags_;
- const double empty_string_value_;
- const double junk_string_value_;
- const char* const infinity_symbol_;
- const char* const nan_symbol_;
- const uc16 separator_;
-
- template
- double StringToIeee(Iterator start_pointer,
- int length,
- bool read_as_double,
- int* processed_characters_count) const;
-
- DC_DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
-};
-
-} // namespace double_conversion
-
-// ICU PATCH: Close ICU namespace
-U_NAMESPACE_END
+#include "double-conversion-string-to-double.h"
+#include "double-conversion-double-to-string.h"
#endif // DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/deps/icu-small/source/i18n/dtfmtsym.cpp b/deps/icu-small/source/i18n/dtfmtsym.cpp
index 04aa01eb4c2459..9dde66c1fba419 100644
--- a/deps/icu-small/source/i18n/dtfmtsym.cpp
+++ b/deps/icu-small/source/i18n/dtfmtsym.cpp
@@ -1246,7 +1246,7 @@ const UnicodeString**
DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const
{
const UnicodeString **result = NULL;
- static UMutex LOCK = U_MUTEX_INITIALIZER;
+ static UMutex LOCK;
umtx_lock(&LOCK);
if (fZoneStrings == NULL) {
@@ -2177,16 +2177,16 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
// The ordering of the following statements is important.
if (fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].isEmpty()) {
fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
- };
+ }
if (fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].isEmpty()) {
fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].setTo(fLeapMonthPatterns[kLeapMonthPatternStandaloneNarrow]);
- };
+ }
if (fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].isEmpty()) {
fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
- };
+ }
if (fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].isEmpty()) {
fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev]);
- };
+ }
// end of hack
fLeapMonthPatternsCount = kMonthPatternsCount;
} else {
@@ -2338,11 +2338,21 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fShortMonths, fShortMonthsCount);
}
- // Load AM/PM markers
+ // Load AM/PM markers; if wide or narrow not available, use short
+ UErrorCode ampmStatus = U_ZERO_ERROR;
initField(&fAmPms, fAmPmsCount, calendarSink,
- buildResourcePath(path, gAmPmMarkersTag, status), status);
+ buildResourcePath(path, gAmPmMarkersTag, ampmStatus), ampmStatus);
+ if (U_FAILURE(ampmStatus)) {
+ initField(&fAmPms, fAmPmsCount, calendarSink,
+ buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
+ }
+ ampmStatus = U_ZERO_ERROR;
initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
- buildResourcePath(path, gAmPmMarkersNarrowTag, status), status);
+ buildResourcePath(path, gAmPmMarkersNarrowTag, ampmStatus), ampmStatus);
+ if (U_FAILURE(ampmStatus)) {
+ initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
+ buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
+ }
// Load quarters
initField(&fQuarters, fQuartersCount, calendarSink,
diff --git a/deps/icu-small/source/i18n/dtitv_impl.h b/deps/icu-small/source/i18n/dtitv_impl.h
index 18fe0b8c9b527d..7c4d8a72148919 100644
--- a/deps/icu-small/source/i18n/dtitv_impl.h
+++ b/deps/icu-small/source/i18n/dtitv_impl.h
@@ -88,7 +88,7 @@
#define MAX_E_COUNT 5
#define MAX_M_COUNT 5
//#define MAX_INTERVAL_INDEX 4
-#define MAX_POSITIVE_INT 56632;
+#define MAX_POSITIVE_INT 56632
#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/deps/icu-small/source/i18n/dtitvfmt.cpp b/deps/icu-small/source/i18n/dtitvfmt.cpp
index 0e124f5624002b..f47e7708ccc128 100644
--- a/deps/icu-small/source/i18n/dtitvfmt.cpp
+++ b/deps/icu-small/source/i18n/dtitvfmt.cpp
@@ -82,10 +82,7 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateIntervalFormat)
// Mutex, protects access to fDateFormat, fFromCalendar and fToCalendar.
// Needed because these data members are modified by const methods of DateIntervalFormat.
-static UMutex *gFormatterMutex() {
- static UMutex m = U_MUTEX_INITIALIZER;
- return &m;
-}
+static UMutex gFormatterMutex;
DateIntervalFormat* U_EXPORT2
DateIntervalFormat::createInstance(const UnicodeString& skeleton,
@@ -171,9 +168,9 @@ DateIntervalFormat::operator=(const DateIntervalFormat& itvfmt) {
delete fTimePattern;
delete fDateTimeFormat;
{
- Mutex lock(gFormatterMutex());
+ Mutex lock(&gFormatterMutex);
if ( itvfmt.fDateFormat ) {
- fDateFormat = (SimpleDateFormat*)itvfmt.fDateFormat->clone();
+ fDateFormat = itvfmt.fDateFormat->clone();
} else {
fDateFormat = NULL;
}
@@ -199,9 +196,9 @@ DateIntervalFormat::operator=(const DateIntervalFormat& itvfmt) {
fIntervalPatterns[i] = itvfmt.fIntervalPatterns[i];
}
fLocale = itvfmt.fLocale;
- fDatePattern = (itvfmt.fDatePattern)? (UnicodeString*)itvfmt.fDatePattern->clone(): NULL;
- fTimePattern = (itvfmt.fTimePattern)? (UnicodeString*)itvfmt.fTimePattern->clone(): NULL;
- fDateTimeFormat = (itvfmt.fDateTimeFormat)? (UnicodeString*)itvfmt.fDateTimeFormat->clone(): NULL;
+ fDatePattern = (itvfmt.fDatePattern)? itvfmt.fDatePattern->clone(): NULL;
+ fTimePattern = (itvfmt.fTimePattern)? itvfmt.fTimePattern->clone(): NULL;
+ fDateTimeFormat = (itvfmt.fDateTimeFormat)? itvfmt.fDateTimeFormat->clone(): NULL;
}
return *this;
}
@@ -218,8 +215,8 @@ DateIntervalFormat::~DateIntervalFormat() {
}
-Format*
-DateIntervalFormat::clone(void) const {
+DateIntervalFormat*
+DateIntervalFormat::clone() const {
return new DateIntervalFormat(*this);
}
@@ -233,7 +230,7 @@ DateIntervalFormat::operator==(const Format& other) const {
if ((fInfo != fmt->fInfo) && (fInfo == NULL || fmt->fInfo == NULL)) {return FALSE;}
if (fInfo && fmt->fInfo && (*fInfo != *fmt->fInfo )) {return FALSE;}
{
- Mutex lock(gFormatterMutex());
+ Mutex lock(&gFormatterMutex);
if (fDateFormat != fmt->fDateFormat && (fDateFormat == NULL || fmt->fDateFormat == NULL)) {return FALSE;}
if (fDateFormat && fmt->fDateFormat && (*fDateFormat != *fmt->fDateFormat)) {return FALSE;}
}
@@ -295,7 +292,7 @@ DateIntervalFormat::format(const DateInterval* dtInterval,
handler.setAcceptFirstOnly(TRUE);
int8_t ignore;
- Mutex lock(gFormatterMutex());
+ Mutex lock(&gFormatterMutex);
return formatIntervalImpl(*dtInterval, appendTo, ignore, handler, status);
}
@@ -312,7 +309,7 @@ FormattedDateInterval DateIntervalFormat::formatToValue(
auto handler = result->getHandler(status);
handler.setCategory(UFIELD_CATEGORY_DATE);
{
- Mutex lock(gFormatterMutex());
+ Mutex lock(&gFormatterMutex);
formatIntervalImpl(dtInterval, string, firstIndex, handler, status);
}
handler.getError(status);
@@ -344,7 +341,7 @@ DateIntervalFormat::format(Calendar& fromCalendar,
handler.setAcceptFirstOnly(TRUE);
int8_t ignore;
- Mutex lock(gFormatterMutex());
+ Mutex lock(&gFormatterMutex);
return formatImpl(fromCalendar, toCalendar, appendTo, ignore, handler, status);
}
@@ -362,7 +359,7 @@ FormattedDateInterval DateIntervalFormat::formatToValue(
auto handler = result->getHandler(status);
handler.setCategory(UFIELD_CATEGORY_DATE);
{
- Mutex lock(gFormatterMutex());
+ Mutex lock(&gFormatterMutex);
formatImpl(fromCalendar, toCalendar, string, firstIndex, handler, status);
}
handler.getError(status);
@@ -600,7 +597,7 @@ const TimeZone&
DateIntervalFormat::getTimeZone() const
{
if (fDateFormat != NULL) {
- Mutex lock(gFormatterMutex());
+ Mutex lock(&gFormatterMutex);
return fDateFormat->getTimeZone();
}
// If fDateFormat is NULL (unexpected), create default timezone.
diff --git a/deps/icu-small/source/i18n/dtitvinf.cpp b/deps/icu-small/source/i18n/dtitvinf.cpp
index c0a6980e5567bc..35ee8c16261934 100644
--- a/deps/icu-small/source/i18n/dtitvinf.cpp
+++ b/deps/icu-small/source/i18n/dtitvinf.cpp
@@ -42,7 +42,9 @@ U_NAMESPACE_BEGIN
#ifdef DTITVINF_DEBUG
-#define PRINTMESG(msg) { std::cout << "(" << __FILE__ << ":" << __LINE__ << ") " << msg << "\n"; }
+#define PRINTMESG(msg) UPRV_BLOCK_MACRO_BEGIN { \
+ std::cout << "(" << __FILE__ << ":" << __LINE__ << ") " << msg << "\n"; \
+} UPRV_BLOCK_MACRO_END
#endif
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateIntervalInfo)
diff --git a/deps/icu-small/source/i18n/dtptngen.cpp b/deps/icu-small/source/i18n/dtptngen.cpp
index 9ca29a3cc7e608..50a377259aa80e 100644
--- a/deps/icu-small/source/i18n/dtptngen.cpp
+++ b/deps/icu-small/source/i18n/dtptngen.cpp
@@ -28,6 +28,7 @@
#include "unicode/ures.h"
#include "unicode/ustring.h"
#include "unicode/rep.h"
+#include "unicode/region.h"
#include "cpputils.h"
#include "mutex.h"
#include "umutex.h"
@@ -613,29 +614,56 @@ U_CFUNC void U_CALLCONV DateTimePatternGenerator::loadAllowedHourFormatsData(UEr
ures_getAllItemsWithFallback(rb.getAlias(), "timeData", sink, status);
}
-void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErrorCode &status) {
- if (U_FAILURE(status)) { return; }
- Locale maxLocale(locale);
- maxLocale.addLikelySubtags(status);
- if (U_FAILURE(status)) {
- return;
- }
-
- const char *country = maxLocale.getCountry();
- if (*country == '\0') { country = "001"; }
- const char *language = maxLocale.getLanguage();
-
+static int32_t* getAllowedHourFormatsLangCountry(const char* language, const char* country, UErrorCode& status) {
CharString langCountry;
- langCountry.append(language, static_cast(uprv_strlen(language)), status);
+ langCountry.append(language, status);
langCountry.append('_', status);
- langCountry.append(country, static_cast(uprv_strlen(country)), status);
+ langCountry.append(country, status);
- int32_t *allowedFormats;
+ int32_t* allowedFormats;
allowedFormats = (int32_t *)uhash_get(localeToAllowedHourFormatsMap, langCountry.data());
if (allowedFormats == nullptr) {
allowedFormats = (int32_t *)uhash_get(localeToAllowedHourFormatsMap, const_cast(country));
}
+ return allowedFormats;
+}
+
+void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErrorCode &status) {
+ if (U_FAILURE(status)) { return; }
+
+ const char *language = locale.getLanguage();
+ const char *country = locale.getCountry();
+ Locale maxLocale; // must be here for correct lifetime
+ if (*language == '\0' || *country == '\0') {
+ maxLocale = locale;
+ UErrorCode localStatus = U_ZERO_ERROR;
+ maxLocale.addLikelySubtags(localStatus);
+ if (U_SUCCESS(localStatus)) {
+ language = maxLocale.getLanguage();
+ country = maxLocale.getCountry();
+ }
+ }
+ if (*language == '\0') {
+ // Unexpected, but fail gracefully
+ language = "und";
+ }
+ if (*country == '\0') {
+ country = "001";
+ }
+
+ int32_t* allowedFormats = getAllowedHourFormatsLangCountry(language, country, status);
+
+ // Check if the region has an alias
+ if (allowedFormats == nullptr) {
+ UErrorCode localStatus = U_ZERO_ERROR;
+ const Region* region = Region::getInstance(country, localStatus);
+ if (U_SUCCESS(localStatus)) {
+ country = region->getRegionCode(); // the real region code
+ allowedFormats = getAllowedHourFormatsLangCountry(language, country, status);
+ }
+ }
+
if (allowedFormats != nullptr) { // Lookup is successful
// Here allowedFormats points to a list consisting of key for preferredFormat,
// followed by one or more keys for allowedFormats, then followed by ALLOWED_HOUR_FORMAT_UNKNOWN.
@@ -787,6 +815,7 @@ void
DateTimePatternGenerator::getCalendarTypeToUse(const Locale& locale, CharString& destination, UErrorCode& err) {
destination.clear().append(DT_DateTimeGregorianTag, -1, err); // initial default
if ( U_SUCCESS(err) ) {
+ UErrorCode localStatus = U_ZERO_ERROR;
char localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY];
// obtain a locale that always has the calendar key value that should be used
ures_getFunctionalEquivalent(
@@ -798,8 +827,7 @@ DateTimePatternGenerator::getCalendarTypeToUse(const Locale& locale, CharString&
locale.getName(),
nullptr,
FALSE,
- &err);
- if (U_FAILURE(err)) { return; }
+ &localStatus);
localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination
// now get the calendar key value from that locale
char calendarType[ULOC_KEYWORDS_CAPACITY];
@@ -808,13 +836,17 @@ DateTimePatternGenerator::getCalendarTypeToUse(const Locale& locale, CharString&
"calendar",
calendarType,
ULOC_KEYWORDS_CAPACITY,
- &err);
- if (U_FAILURE(err)) { return; }
+ &localStatus);
+ // If the input locale was invalid, don't fail with missing resource error, instead
+ // continue with default of Gregorian.
+ if (U_FAILURE(localStatus) && localStatus != U_MISSING_RESOURCE_ERROR) {
+ err = localStatus;
+ return;
+ }
if (calendarTypeLen < ULOC_KEYWORDS_CAPACITY) {
destination.clear().append(calendarType, -1, err);
if (U_FAILURE(err)) { return; }
}
- err = U_ZERO_ERROR;
}
}
@@ -2543,7 +2575,8 @@ UChar SkeletonFields::getFirstChar() const {
}
-PtnSkeleton::PtnSkeleton() {
+PtnSkeleton::PtnSkeleton()
+ : addedDefaultDayPeriod(FALSE) {
}
PtnSkeleton::PtnSkeleton(const PtnSkeleton& other) {
@@ -2554,6 +2587,7 @@ void PtnSkeleton::copyFrom(const PtnSkeleton& other) {
uprv_memcpy(type, other.type, sizeof(type));
original.copyFrom(other.original);
baseOriginal.copyFrom(other.baseOriginal);
+ addedDefaultDayPeriod = other.addedDefaultDayPeriod;
}
void PtnSkeleton::clear() {
diff --git a/deps/icu-small/source/i18n/esctrn.cpp b/deps/icu-small/source/i18n/esctrn.cpp
index 900bed7e45734b..ba0e4c2c7bb618 100644
--- a/deps/icu-small/source/i18n/esctrn.cpp
+++ b/deps/icu-small/source/i18n/esctrn.cpp
@@ -122,7 +122,7 @@ EscapeTransliterator::~EscapeTransliterator() {
/**
* Transliterator API.
*/
-Transliterator* EscapeTransliterator::clone() const {
+EscapeTransliterator* EscapeTransliterator::clone() const {
return new EscapeTransliterator(*this);
}
diff --git a/deps/icu-small/source/i18n/esctrn.h b/deps/icu-small/source/i18n/esctrn.h
index 60ecc74b498456..2a2c6dcfe9af10 100644
--- a/deps/icu-small/source/i18n/esctrn.h
+++ b/deps/icu-small/source/i18n/esctrn.h
@@ -115,7 +115,7 @@ class EscapeTransliterator : public Transliterator {
/**
* Transliterator API.
*/
- virtual Transliterator* clone() const;
+ virtual EscapeTransliterator* clone() const;
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
diff --git a/deps/icu-small/source/i18n/ethpccal.cpp b/deps/icu-small/source/i18n/ethpccal.cpp
index 4377c59b325a1b..0b8ad0e81488c3 100644
--- a/deps/icu-small/source/i18n/ethpccal.cpp
+++ b/deps/icu-small/source/i18n/ethpccal.cpp
@@ -46,7 +46,7 @@ EthiopicCalendar::~EthiopicCalendar()
{
}
-Calendar*
+EthiopicCalendar*
EthiopicCalendar::clone() const
{
return new EthiopicCalendar(*this);
diff --git a/deps/icu-small/source/i18n/ethpccal.h b/deps/icu-small/source/i18n/ethpccal.h
index 5fae2fb1bea2c7..179a20e85302fb 100644
--- a/deps/icu-small/source/i18n/ethpccal.h
+++ b/deps/icu-small/source/i18n/ethpccal.h
@@ -141,7 +141,7 @@ class EthiopicCalendar : public CECalendar {
* @return return a polymorphic copy of this calendar.
* @internal
*/
- virtual Calendar* clone() const;
+ virtual EthiopicCalendar* clone() const;
/**
* return the calendar type, "ethiopic"
diff --git a/deps/icu-small/source/i18n/fmtable.cpp b/deps/icu-small/source/i18n/fmtable.cpp
index 9baa5ff480db6a..10a6fdb0ff3441 100644
--- a/deps/icu-small/source/i18n/fmtable.cpp
+++ b/deps/icu-small/source/i18n/fmtable.cpp
@@ -736,7 +736,7 @@ CharString *Formattable::internalGetCharString(UErrorCode &status) {
fDecimalStr->append("Infinity", status);
} else if (fDecimalQuantity->isNaN()) {
fDecimalStr->append("NaN", status);
- } else if (fDecimalQuantity->isZero()) {
+ } else if (fDecimalQuantity->isZeroish()) {
fDecimalStr->append("0", -1, status);
} else if (fType==kLong || fType==kInt64 || // use toPlainString for integer types
(fDecimalQuantity->getMagnitude() != INT32_MIN && std::abs(fDecimalQuantity->getMagnitude()) < 5)) {
diff --git a/deps/icu-small/source/i18n/number_stringbuilder.cpp b/deps/icu-small/source/i18n/formatted_string_builder.cpp
similarity index 58%
rename from deps/icu-small/source/i18n/number_stringbuilder.cpp
rename to deps/icu-small/source/i18n/formatted_string_builder.cpp
index 03300b33ac5e21..3024bff6addacc 100644
--- a/deps/icu-small/source/i18n/number_stringbuilder.cpp
+++ b/deps/icu-small/source/i18n/formatted_string_builder.cpp
@@ -5,14 +5,9 @@
#if !UCONFIG_NO_FORMATTING
-#include "number_stringbuilder.h"
-#include "static_unicode_sets.h"
+#include "formatted_string_builder.h"
+#include "unicode/ustring.h"
#include "unicode/utf16.h"
-#include "number_utils.h"
-
-using namespace icu;
-using namespace icu::number;
-using namespace icu::number::impl;
namespace {
@@ -34,7 +29,10 @@ inline void uprv_memmove2(void* dest, const void* src, size_t len) {
} // namespace
-NumberStringBuilder::NumberStringBuilder() {
+
+U_NAMESPACE_BEGIN
+
+FormattedStringBuilder::FormattedStringBuilder() {
#if U_DEBUG
// Initializing the memory to non-zero helps catch some bugs that involve
// reading from an improperly terminated string.
@@ -44,18 +42,18 @@ NumberStringBuilder::NumberStringBuilder() {
#endif
}
-NumberStringBuilder::~NumberStringBuilder() {
+FormattedStringBuilder::~FormattedStringBuilder() {
if (fUsingHeap) {
uprv_free(fChars.heap.ptr);
uprv_free(fFields.heap.ptr);
}
}
-NumberStringBuilder::NumberStringBuilder(const NumberStringBuilder &other) {
+FormattedStringBuilder::FormattedStringBuilder(const FormattedStringBuilder &other) {
*this = other;
}
-NumberStringBuilder &NumberStringBuilder::operator=(const NumberStringBuilder &other) {
+FormattedStringBuilder &FormattedStringBuilder::operator=(const FormattedStringBuilder &other) {
// Check for self-assignment
if (this == &other) {
return *this;
@@ -78,7 +76,7 @@ NumberStringBuilder &NumberStringBuilder::operator=(const NumberStringBuilder &o
// UErrorCode is not available; fail silently.
uprv_free(newChars);
uprv_free(newFields);
- *this = NumberStringBuilder(); // can't fail
+ *this = FormattedStringBuilder(); // can't fail
return *this;
}
@@ -97,15 +95,15 @@ NumberStringBuilder &NumberStringBuilder::operator=(const NumberStringBuilder &o
return *this;
}
-int32_t NumberStringBuilder::length() const {
+int32_t FormattedStringBuilder::length() const {
return fLength;
}
-int32_t NumberStringBuilder::codePointCount() const {
+int32_t FormattedStringBuilder::codePointCount() const {
return u_countChar32(getCharPtr() + fZero, fLength);
}
-UChar32 NumberStringBuilder::getFirstCodePoint() const {
+UChar32 FormattedStringBuilder::getFirstCodePoint() const {
if (fLength == 0) {
return -1;
}
@@ -114,7 +112,7 @@ UChar32 NumberStringBuilder::getFirstCodePoint() const {
return cp;
}
-UChar32 NumberStringBuilder::getLastCodePoint() const {
+UChar32 FormattedStringBuilder::getLastCodePoint() const {
if (fLength == 0) {
return -1;
}
@@ -125,13 +123,13 @@ UChar32 NumberStringBuilder::getLastCodePoint() const {
return cp;
}
-UChar32 NumberStringBuilder::codePointAt(int32_t index) const {
+UChar32 FormattedStringBuilder::codePointAt(int32_t index) const {
UChar32 cp;
U16_GET(getCharPtr() + fZero, 0, index, fLength, cp);
return cp;
}
-UChar32 NumberStringBuilder::codePointBefore(int32_t index) const {
+UChar32 FormattedStringBuilder::codePointBefore(int32_t index) const {
int32_t offset = index;
U16_BACK_1(getCharPtr() + fZero, 0, offset);
UChar32 cp;
@@ -139,19 +137,15 @@ UChar32 NumberStringBuilder::codePointBefore(int32_t index) const {
return cp;
}
-NumberStringBuilder &NumberStringBuilder::clear() {
+FormattedStringBuilder &FormattedStringBuilder::clear() {
// TODO: Reset the heap here?
fZero = getCapacity() / 2;
fLength = 0;
return *this;
}
-int32_t NumberStringBuilder::appendCodePoint(UChar32 codePoint, Field field, UErrorCode &status) {
- return insertCodePoint(fLength, codePoint, field, status);
-}
-
int32_t
-NumberStringBuilder::insertCodePoint(int32_t index, UChar32 codePoint, Field field, UErrorCode &status) {
+FormattedStringBuilder::insertCodePoint(int32_t index, UChar32 codePoint, Field field, UErrorCode &status) {
int32_t count = U16_LENGTH(codePoint);
int32_t position = prepareForInsert(index, count, status);
if (U_FAILURE(status)) {
@@ -168,11 +162,7 @@ NumberStringBuilder::insertCodePoint(int32_t index, UChar32 codePoint, Field fie
return count;
}
-int32_t NumberStringBuilder::append(const UnicodeString &unistr, Field field, UErrorCode &status) {
- return insert(fLength, unistr, field, status);
-}
-
-int32_t NumberStringBuilder::insert(int32_t index, const UnicodeString &unistr, Field field,
+int32_t FormattedStringBuilder::insert(int32_t index, const UnicodeString &unistr, Field field,
UErrorCode &status) {
if (unistr.length() == 0) {
// Nothing to insert.
@@ -186,7 +176,7 @@ int32_t NumberStringBuilder::insert(int32_t index, const UnicodeString &unistr,
}
int32_t
-NumberStringBuilder::insert(int32_t index, const UnicodeString &unistr, int32_t start, int32_t end,
+FormattedStringBuilder::insert(int32_t index, const UnicodeString &unistr, int32_t start, int32_t end,
Field field, UErrorCode &status) {
int32_t count = end - start;
int32_t position = prepareForInsert(index, count, status);
@@ -201,7 +191,7 @@ NumberStringBuilder::insert(int32_t index, const UnicodeString &unistr, int32_t
}
int32_t
-NumberStringBuilder::splice(int32_t startThis, int32_t endThis, const UnicodeString &unistr,
+FormattedStringBuilder::splice(int32_t startThis, int32_t endThis, const UnicodeString &unistr,
int32_t startOther, int32_t endOther, Field field, UErrorCode& status) {
int32_t thisLength = endThis - startThis;
int32_t otherLength = endOther - startOther;
@@ -224,12 +214,12 @@ NumberStringBuilder::splice(int32_t startThis, int32_t endThis, const UnicodeSt
return count;
}
-int32_t NumberStringBuilder::append(const NumberStringBuilder &other, UErrorCode &status) {
+int32_t FormattedStringBuilder::append(const FormattedStringBuilder &other, UErrorCode &status) {
return insert(fLength, other, status);
}
int32_t
-NumberStringBuilder::insert(int32_t index, const NumberStringBuilder &other, UErrorCode &status) {
+FormattedStringBuilder::insert(int32_t index, const FormattedStringBuilder &other, UErrorCode &status) {
if (this == &other) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
@@ -250,7 +240,7 @@ NumberStringBuilder::insert(int32_t index, const NumberStringBuilder &other, UEr
return count;
}
-void NumberStringBuilder::writeTerminator(UErrorCode& status) {
+void FormattedStringBuilder::writeTerminator(UErrorCode& status) {
int32_t position = prepareForInsert(fLength, 1, status);
if (U_FAILURE(status)) {
return;
@@ -260,7 +250,7 @@ void NumberStringBuilder::writeTerminator(UErrorCode& status) {
fLength--;
}
-int32_t NumberStringBuilder::prepareForInsert(int32_t index, int32_t count, UErrorCode &status) {
+int32_t FormattedStringBuilder::prepareForInsert(int32_t index, int32_t count, UErrorCode &status) {
U_ASSERT(index >= 0);
U_ASSERT(index <= fLength);
U_ASSERT(count >= 0);
@@ -279,7 +269,7 @@ int32_t NumberStringBuilder::prepareForInsert(int32_t index, int32_t count, UErr
}
}
-int32_t NumberStringBuilder::prepareForInsertHelper(int32_t index, int32_t count, UErrorCode &status) {
+int32_t FormattedStringBuilder::prepareForInsertHelper(int32_t index, int32_t count, UErrorCode &status) {
int32_t oldCapacity = getCapacity();
int32_t oldZero = fZero;
char16_t *oldChars = getCharPtr();
@@ -342,7 +332,7 @@ int32_t NumberStringBuilder::prepareForInsertHelper(int32_t index, int32_t count
return fZero + index;
}
-int32_t NumberStringBuilder::remove(int32_t index, int32_t count) {
+int32_t FormattedStringBuilder::remove(int32_t index, int32_t count) {
// TODO: Reset the heap here? (If the string after removal can fit on stack?)
int32_t position = index + fZero;
uprv_memmove2(getCharPtr() + position,
@@ -355,18 +345,18 @@ int32_t NumberStringBuilder::remove(int32_t index, int32_t count) {
return position;
}
-UnicodeString NumberStringBuilder::toUnicodeString() const {
+UnicodeString FormattedStringBuilder::toUnicodeString() const {
return UnicodeString(getCharPtr() + fZero, fLength);
}
-const UnicodeString NumberStringBuilder::toTempUnicodeString() const {
+const UnicodeString FormattedStringBuilder::toTempUnicodeString() const {
// Readonly-alias constructor:
return UnicodeString(FALSE, getCharPtr() + fZero, fLength);
}
-UnicodeString NumberStringBuilder::toDebugString() const {
+UnicodeString FormattedStringBuilder::toDebugString() const {
UnicodeString sb;
- sb.append(u"= UNUM_FIELD_COUNT) {
- status = U_ILLEGAL_ARGUMENT_ERROR;
- return FALSE;
- }
-
- ConstrainedFieldPosition cfpos;
- cfpos.constrainField(UFIELD_CATEGORY_NUMBER, rawField);
- cfpos.setState(UFIELD_CATEGORY_NUMBER, rawField, fp.getBeginIndex(), fp.getEndIndex());
- if (nextPosition(cfpos, 0, status)) {
- fp.setBeginIndex(cfpos.getStart());
- fp.setEndIndex(cfpos.getLimit());
- return true;
- }
-
- // Special case: fraction should start after integer if fraction is not present
- if (rawField == UNUM_FRACTION_FIELD && fp.getEndIndex() == 0) {
- bool inside = false;
- int32_t i = fZero;
- for (; i < fZero + fLength; i++) {
- if (isIntOrGroup(getFieldPtr()[i]) || getFieldPtr()[i] == UNUM_DECIMAL_SEPARATOR_FIELD) {
- inside = true;
- } else if (inside) {
- break;
- }
- }
- fp.setBeginIndex(i - fZero);
- fp.setEndIndex(i - fZero);
- }
-
- return false;
-}
-
-void NumberStringBuilder::getAllFieldPositions(FieldPositionIteratorHandler& fpih,
- UErrorCode& status) const {
- ConstrainedFieldPosition cfpos;
- while (nextPosition(cfpos, 0, status)) {
- fpih.addAttribute(cfpos.getField(), cfpos.getStart(), cfpos.getLimit());
- }
-}
-
-// Signal the end of the string using a field that doesn't exist and that is
-// different from UNUM_FIELD_COUNT, which is used for "null number field".
-static constexpr Field kEndField = 0xff;
-
-bool NumberStringBuilder::nextPosition(ConstrainedFieldPosition& cfpos, Field numericField, UErrorCode& /*status*/) const {
- auto numericCAF = NumFieldUtils::expand(numericField);
- int32_t fieldStart = -1;
- Field currField = UNUM_FIELD_COUNT;
- for (int32_t i = fZero + cfpos.getLimit(); i <= fZero + fLength; i++) {
- Field _field = (i < fZero + fLength) ? getFieldPtr()[i] : kEndField;
- // Case 1: currently scanning a field.
- if (currField != UNUM_FIELD_COUNT) {
- if (currField != _field) {
- int32_t end = i - fZero;
- // Grouping separators can be whitespace; don't throw them out!
- if (currField != UNUM_GROUPING_SEPARATOR_FIELD) {
- end = trimBack(i - fZero);
- }
- if (end <= fieldStart) {
- // Entire field position is ignorable; skip.
- fieldStart = -1;
- currField = UNUM_FIELD_COUNT;
- i--; // look at this index again
- continue;
- }
- int32_t start = fieldStart;
- if (currField != UNUM_GROUPING_SEPARATOR_FIELD) {
- start = trimFront(start);
- }
- auto caf = NumFieldUtils::expand(currField);
- cfpos.setState(caf.category, caf.field, start, end);
- return true;
- }
- continue;
- }
- // Special case: coalesce the INTEGER if we are pointing at the end of the INTEGER.
- if (cfpos.matchesField(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD)
- && i > fZero
- // don't return the same field twice in a row:
- && i - fZero > cfpos.getLimit()
- && isIntOrGroup(getFieldPtr()[i - 1])
- && !isIntOrGroup(_field)) {
- int j = i - 1;
- for (; j >= fZero && isIntOrGroup(getFieldPtr()[j]); j--) {}
- cfpos.setState(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD, j - fZero + 1, i - fZero);
- return true;
- }
- // Special case: coalesce NUMERIC if we are pointing at the end of the NUMERIC.
- if (numericField != 0
- && cfpos.matchesField(numericCAF.category, numericCAF.field)
- && i > fZero
- // don't return the same field twice in a row:
- && (i - fZero > cfpos.getLimit()
- || cfpos.getCategory() != numericCAF.category
- || cfpos.getField() != numericCAF.field)
- && isNumericField(getFieldPtr()[i - 1])
- && !isNumericField(_field)) {
- int j = i - 1;
- for (; j >= fZero && isNumericField(getFieldPtr()[j]); j--) {}
- cfpos.setState(numericCAF.category, numericCAF.field, j - fZero + 1, i - fZero);
- return true;
- }
- // Special case: skip over INTEGER; will be coalesced later.
- if (_field == UNUM_INTEGER_FIELD) {
- _field = UNUM_FIELD_COUNT;
- }
- // Case 2: no field starting at this position.
- if (_field == UNUM_FIELD_COUNT || _field == kEndField) {
- continue;
- }
- // Case 3: check for field starting at this position
- auto caf = NumFieldUtils::expand(_field);
- if (cfpos.matchesField(caf.category, caf.field)) {
- fieldStart = i - fZero;
- currField = _field;
- }
- }
-
- U_ASSERT(currField == UNUM_FIELD_COUNT);
- return false;
-}
-
-bool NumberStringBuilder::containsField(Field field) const {
+bool FormattedStringBuilder::containsField(Field field) const {
for (int32_t i = 0; i < fLength; i++) {
if (field == fieldAt(i)) {
return true;
@@ -573,27 +434,6 @@ bool NumberStringBuilder::containsField(Field field) const {
return false;
}
-bool NumberStringBuilder::isIntOrGroup(Field field) {
- return field == UNUM_INTEGER_FIELD
- || field == UNUM_GROUPING_SEPARATOR_FIELD;
-}
-
-bool NumberStringBuilder::isNumericField(Field field) {
- return NumFieldUtils::isNumericField(field);
-}
-
-int32_t NumberStringBuilder::trimBack(int32_t limit) const {
- return unisets::get(unisets::DEFAULT_IGNORABLES)->spanBack(
- getCharPtr() + fZero,
- limit,
- USET_SPAN_CONTAINED);
-}
-
-int32_t NumberStringBuilder::trimFront(int32_t start) const {
- return start + unisets::get(unisets::DEFAULT_IGNORABLES)->span(
- getCharPtr() + fZero + start,
- fLength - start,
- USET_SPAN_CONTAINED);
-}
+U_NAMESPACE_END
#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/deps/icu-small/source/i18n/formatted_string_builder.h b/deps/icu-small/source/i18n/formatted_string_builder.h
new file mode 100644
index 00000000000000..2949ae73e0ff9e
--- /dev/null
+++ b/deps/icu-small/source/i18n/formatted_string_builder.h
@@ -0,0 +1,253 @@
+// © 2017 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+#ifndef __NUMBER_STRINGBUILDER_H__
+#define __NUMBER_STRINGBUILDER_H__
+
+
+#include
+#include "unicode/unum.h" // for UNUM_FIELD_COUNT
+#include "cstring.h"
+#include "uassert.h"
+#include "fphdlimp.h"
+
+U_NAMESPACE_BEGIN
+
+class FormattedValueStringBuilderImpl;
+
+/**
+ * A StringBuilder optimized for formatting. It implements the following key
+ * features beyond a UnicodeString:
+ *
+ *
+ * - Efficient prepend as well as append.
+ *
- Keeps tracks of Fields in an efficient manner.
+ *
+ *
+ * See also FormattedValueStringBuilderImpl.
+ *
+ * @author sffc (Shane Carr)
+ */
+class U_I18N_API FormattedStringBuilder : public UMemory {
+ private:
+ static const int32_t DEFAULT_CAPACITY = 40;
+
+ template
+ union ValueOrHeapArray {
+ T value[DEFAULT_CAPACITY];
+ struct {
+ T *ptr;
+ int32_t capacity;
+ } heap;
+ };
+
+ public:
+ FormattedStringBuilder();
+
+ ~FormattedStringBuilder();
+
+ FormattedStringBuilder(const FormattedStringBuilder &other);
+
+ // Convention: bottom 4 bits for field, top 4 bits for field category.
+ // Field category 0 implies the number category so that the number field
+ // literals can be directly passed as a Field type.
+ // See the helper functions in "StringBuilderFieldUtils" below.
+ typedef uint8_t Field;
+
+ FormattedStringBuilder &operator=(const FormattedStringBuilder &other);
+
+ int32_t length() const;
+
+ int32_t codePointCount() const;
+
+ inline char16_t charAt(int32_t index) const {
+ U_ASSERT(index >= 0);
+ U_ASSERT(index < fLength);
+ return getCharPtr()[fZero + index];
+ }
+
+ inline Field fieldAt(int32_t index) const {
+ U_ASSERT(index >= 0);
+ U_ASSERT(index < fLength);
+ return getFieldPtr()[fZero + index];
+ }
+
+ UChar32 getFirstCodePoint() const;
+
+ UChar32 getLastCodePoint() const;
+
+ UChar32 codePointAt(int32_t index) const;
+
+ UChar32 codePointBefore(int32_t index) const;
+
+ FormattedStringBuilder &clear();
+
+ /** Appends a UTF-16 code unit. */
+ inline int32_t appendChar16(char16_t codeUnit, Field field, UErrorCode& status) {
+ // appendCodePoint handles both code units and code points.
+ return insertCodePoint(fLength, codeUnit, field, status);
+ }
+
+ /** Inserts a UTF-16 code unit. Note: insert at index 0 is very efficient. */
+ inline int32_t insertChar16(int32_t index, char16_t codeUnit, Field field, UErrorCode& status) {
+ // insertCodePoint handles both code units and code points.
+ return insertCodePoint(index, codeUnit, field, status);
+ }
+
+ /** Appends a Unicode code point. */
+ inline int32_t appendCodePoint(UChar32 codePoint, Field field, UErrorCode &status) {
+ return insertCodePoint(fLength, codePoint, field, status);
+ }
+
+ /** Inserts a Unicode code point. Note: insert at index 0 is very efficient. */
+ int32_t insertCodePoint(int32_t index, UChar32 codePoint, Field field, UErrorCode &status);
+
+ /** Appends a string. */
+ inline int32_t append(const UnicodeString &unistr, Field field, UErrorCode &status) {
+ return insert(fLength, unistr, field, status);
+ }
+
+ /** Inserts a string. Note: insert at index 0 is very efficient. */
+ int32_t insert(int32_t index, const UnicodeString &unistr, Field field, UErrorCode &status);
+
+ /** Inserts a substring. Note: insert at index 0 is very efficient.
+ *
+ * @param start Start index of the substring of unistr to be inserted.
+ * @param end End index of the substring of unistr to be inserted (exclusive).
+ */
+ int32_t insert(int32_t index, const UnicodeString &unistr, int32_t start, int32_t end, Field field,
+ UErrorCode &status);
+
+ /** Deletes a substring and then inserts a string at that same position.
+ * Similar to JavaScript Array.prototype.splice().
+ *
+ * @param startThis Start of the span to delete.
+ * @param endThis End of the span to delete (exclusive).
+ * @param unistr The string to insert at the deletion position.
+ * @param startOther Start index of the substring of unistr to be inserted.
+ * @param endOther End index of the substring of unistr to be inserted (exclusive).
+ */
+ int32_t splice(int32_t startThis, int32_t endThis, const UnicodeString &unistr,
+ int32_t startOther, int32_t endOther, Field field, UErrorCode& status);
+
+ /** Appends a formatted string. */
+ int32_t append(const FormattedStringBuilder &other, UErrorCode &status);
+
+ /** Inserts a formatted string. Note: insert at index 0 is very efficient. */
+ int32_t insert(int32_t index, const FormattedStringBuilder &other, UErrorCode &status);
+
+ /**
+ * Ensures that the string buffer contains a NUL terminator. The NUL terminator does
+ * not count toward the string length. Any further changes to the string (insert or
+ * append) may invalidate the NUL terminator.
+ *
+ * You should call this method after the formatted string is completely built if you
+ * plan to return a pointer to the string from a C API.
+ */
+ void writeTerminator(UErrorCode& status);
+
+ /**
+ * Gets a "safe" UnicodeString that can be used even after the FormattedStringBuilder is destructed.
+ */
+ UnicodeString toUnicodeString() const;
+
+ /**
+ * Gets an "unsafe" UnicodeString that is valid only as long as the FormattedStringBuilder is alive and
+ * unchanged. Slightly faster than toUnicodeString().
+ */
+ const UnicodeString toTempUnicodeString() const;
+
+ UnicodeString toDebugString() const;
+
+ const char16_t *chars() const;
+
+ bool contentEquals(const FormattedStringBuilder &other) const;
+
+ bool containsField(Field field) const;
+
+ private:
+ bool fUsingHeap = false;
+ ValueOrHeapArray fChars;
+ ValueOrHeapArray fFields;
+ int32_t fZero = DEFAULT_CAPACITY / 2;
+ int32_t fLength = 0;
+
+ inline char16_t *getCharPtr() {
+ return fUsingHeap ? fChars.heap.ptr : fChars.value;
+ }
+
+ inline const char16_t *getCharPtr() const {
+ return fUsingHeap ? fChars.heap.ptr : fChars.value;
+ }
+
+ inline Field *getFieldPtr() {
+ return fUsingHeap ? fFields.heap.ptr : fFields.value;
+ }
+
+ inline const Field *getFieldPtr() const {
+ return fUsingHeap ? fFields.heap.ptr : fFields.value;
+ }
+
+ inline int32_t getCapacity() const {
+ return fUsingHeap ? fChars.heap.capacity : DEFAULT_CAPACITY;
+ }
+
+ int32_t prepareForInsert(int32_t index, int32_t count, UErrorCode &status);
+
+ int32_t prepareForInsertHelper(int32_t index, int32_t count, UErrorCode &status);
+
+ int32_t remove(int32_t index, int32_t count);
+
+ friend class FormattedValueStringBuilderImpl;
+};
+
+/**
+ * Helper functions for dealing with the Field typedef, which stores fields
+ * in a compressed format.
+ */
+class StringBuilderFieldUtils {
+public:
+ struct CategoryFieldPair {
+ int32_t category;
+ int32_t field;
+ };
+
+ /** Compile-time function to construct a Field from a category and a field */
+ template
+ static constexpr FormattedStringBuilder::Field compress() {
+ static_assert(category != 0, "cannot use Undefined category in FieldUtils");
+ static_assert(category <= 0xf, "only 4 bits for category");
+ static_assert(field <= 0xf, "only 4 bits for field");
+ return static_cast((category << 4) | field);
+ }
+
+ /** Runtime inline function to unpack the category and field from the Field */
+ static inline CategoryFieldPair expand(FormattedStringBuilder::Field field) {
+ if (field == UNUM_FIELD_COUNT) {
+ return {UFIELD_CATEGORY_UNDEFINED, 0};
+ }
+ CategoryFieldPair ret = {
+ (field >> 4),
+ (field & 0xf)
+ };
+ if (ret.category == 0) {
+ ret.category = UFIELD_CATEGORY_NUMBER;
+ }
+ return ret;
+ }
+
+ static inline bool isNumericField(FormattedStringBuilder::Field field) {
+ int8_t category = field >> 4;
+ return category == 0 || category == UFIELD_CATEGORY_NUMBER;
+ }
+};
+
+U_NAMESPACE_END
+
+
+#endif //__NUMBER_STRINGBUILDER_H__
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/deps/icu-small/source/i18n/formattedval_impl.h b/deps/icu-small/source/i18n/formattedval_impl.h
index 69ba0922edc81f..4ee53e4589b2e9 100644
--- a/deps/icu-small/source/i18n/formattedval_impl.h
+++ b/deps/icu-small/source/i18n/formattedval_impl.h
@@ -18,7 +18,7 @@
#include "fphdlimp.h"
#include "util.h"
#include "uvectr32.h"
-#include "number_stringbuilder.h"
+#include "formatted_string_builder.h"
/**
@@ -67,7 +67,9 @@ typedef enum UCFPosConstraintType {
U_NAMESPACE_BEGIN
-/** Implementation using FieldPositionHandler to accept fields. */
+/**
+ * Implementation of FormattedValue using FieldPositionHandler to accept fields.
+ */
class FormattedValueFieldPositionIteratorImpl : public UMemory, public FormattedValue {
public:
@@ -112,12 +114,21 @@ class FormattedValueFieldPositionIteratorImpl : public UMemory, public Formatted
};
-class FormattedValueNumberStringBuilderImpl : public UMemory, public FormattedValue {
+/**
+ * Implementation of FormattedValue based on FormattedStringBuilder.
+ *
+ * The implementation currently revolves around numbers and number fields.
+ * However, it can be generalized in the future when there is a need.
+ *
+ * @author sffc (Shane Carr)
+ */
+// Exported as U_I18N_API for tests
+class U_I18N_API FormattedValueStringBuilderImpl : public UMemory, public FormattedValue {
public:
- FormattedValueNumberStringBuilderImpl(number::impl::Field numericField);
+ FormattedValueStringBuilderImpl(FormattedStringBuilder::Field numericField);
- virtual ~FormattedValueNumberStringBuilderImpl();
+ virtual ~FormattedValueStringBuilderImpl();
// Implementation of FormattedValue (const):
@@ -126,17 +137,25 @@ class FormattedValueNumberStringBuilderImpl : public UMemory, public FormattedVa
Appendable& appendTo(Appendable& appendable, UErrorCode& status) const U_OVERRIDE;
UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE;
- inline number::impl::NumberStringBuilder& getStringRef() {
+ // Additional helper functions:
+ UBool nextFieldPosition(FieldPosition& fp, UErrorCode& status) const;
+ void getAllFieldPositions(FieldPositionIteratorHandler& fpih, UErrorCode& status) const;
+ inline FormattedStringBuilder& getStringRef() {
return fString;
}
-
- inline const number::impl::NumberStringBuilder& getStringRef() const {
+ inline const FormattedStringBuilder& getStringRef() const {
return fString;
}
private:
- number::impl::NumberStringBuilder fString;
- number::impl::Field fNumericField;
+ FormattedStringBuilder fString;
+ FormattedStringBuilder::Field fNumericField;
+
+ bool nextPositionImpl(ConstrainedFieldPosition& cfpos, FormattedStringBuilder::Field numericField, UErrorCode& status) const;
+ static bool isIntOrGroup(FormattedStringBuilder::Field field);
+ static bool isNumericField(FormattedStringBuilder::Field field);
+ int32_t trimBack(int32_t limit) const;
+ int32_t trimFront(int32_t start) const;
};
diff --git a/deps/icu-small/source/i18n/formattedval_sbimpl.cpp b/deps/icu-small/source/i18n/formattedval_sbimpl.cpp
index 1fbecf25ac6bb6..ca28f222813afc 100644
--- a/deps/icu-small/source/i18n/formattedval_sbimpl.cpp
+++ b/deps/icu-small/source/i18n/formattedval_sbimpl.cpp
@@ -9,35 +9,203 @@
// Other independent implementations should go into their own cpp file for
// better dependency modularization.
+#include "unicode/ustring.h"
#include "formattedval_impl.h"
+#include "number_types.h"
+#include "formatted_string_builder.h"
+#include "number_utils.h"
+#include "static_unicode_sets.h"
U_NAMESPACE_BEGIN
-FormattedValueNumberStringBuilderImpl::FormattedValueNumberStringBuilderImpl(number::impl::Field numericField)
+typedef FormattedStringBuilder::Field Field;
+
+
+FormattedValueStringBuilderImpl::FormattedValueStringBuilderImpl(Field numericField)
: fNumericField(numericField) {
}
-FormattedValueNumberStringBuilderImpl::~FormattedValueNumberStringBuilderImpl() {
+FormattedValueStringBuilderImpl::~FormattedValueStringBuilderImpl() {
}
-UnicodeString FormattedValueNumberStringBuilderImpl::toString(UErrorCode&) const {
+UnicodeString FormattedValueStringBuilderImpl::toString(UErrorCode&) const {
return fString.toUnicodeString();
}
-UnicodeString FormattedValueNumberStringBuilderImpl::toTempString(UErrorCode&) const {
+UnicodeString FormattedValueStringBuilderImpl::toTempString(UErrorCode&) const {
return fString.toTempUnicodeString();
}
-Appendable& FormattedValueNumberStringBuilderImpl::appendTo(Appendable& appendable, UErrorCode&) const {
+Appendable& FormattedValueStringBuilderImpl::appendTo(Appendable& appendable, UErrorCode&) const {
appendable.appendString(fString.chars(), fString.length());
return appendable;
}
-UBool FormattedValueNumberStringBuilderImpl::nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const {
+UBool FormattedValueStringBuilderImpl::nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const {
// NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
- return fString.nextPosition(cfpos, fNumericField, status) ? TRUE : FALSE;
+ return nextPositionImpl(cfpos, fNumericField, status) ? TRUE : FALSE;
+}
+
+UBool FormattedValueStringBuilderImpl::nextFieldPosition(FieldPosition& fp, UErrorCode& status) const {
+ int32_t rawField = fp.getField();
+
+ if (rawField == FieldPosition::DONT_CARE) {
+ return FALSE;
+ }
+
+ if (rawField < 0 || rawField >= UNUM_FIELD_COUNT) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return FALSE;
+ }
+
+ ConstrainedFieldPosition cfpos;
+ cfpos.constrainField(UFIELD_CATEGORY_NUMBER, rawField);
+ cfpos.setState(UFIELD_CATEGORY_NUMBER, rawField, fp.getBeginIndex(), fp.getEndIndex());
+ if (nextPositionImpl(cfpos, 0, status)) {
+ fp.setBeginIndex(cfpos.getStart());
+ fp.setEndIndex(cfpos.getLimit());
+ return TRUE;
+ }
+
+ // Special case: fraction should start after integer if fraction is not present
+ if (rawField == UNUM_FRACTION_FIELD && fp.getEndIndex() == 0) {
+ bool inside = false;
+ int32_t i = fString.fZero;
+ for (; i < fString.fZero + fString.fLength; i++) {
+ if (isIntOrGroup(fString.getFieldPtr()[i]) || fString.getFieldPtr()[i] == UNUM_DECIMAL_SEPARATOR_FIELD) {
+ inside = true;
+ } else if (inside) {
+ break;
+ }
+ }
+ fp.setBeginIndex(i - fString.fZero);
+ fp.setEndIndex(i - fString.fZero);
+ }
+
+ return FALSE;
+}
+
+void FormattedValueStringBuilderImpl::getAllFieldPositions(FieldPositionIteratorHandler& fpih,
+ UErrorCode& status) const {
+ ConstrainedFieldPosition cfpos;
+ while (nextPositionImpl(cfpos, 0, status)) {
+ fpih.addAttribute(cfpos.getField(), cfpos.getStart(), cfpos.getLimit());
+ }
+}
+
+// Signal the end of the string using a field that doesn't exist and that is
+// different from UNUM_FIELD_COUNT, which is used for "null number field".
+static constexpr Field kEndField = 0xff;
+
+bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition& cfpos, Field numericField, UErrorCode& /*status*/) const {
+ auto numericCAF = StringBuilderFieldUtils::expand(numericField);
+ int32_t fieldStart = -1;
+ Field currField = UNUM_FIELD_COUNT;
+ for (int32_t i = fString.fZero + cfpos.getLimit(); i <= fString.fZero + fString.fLength; i++) {
+ Field _field = (i < fString.fZero + fString.fLength) ? fString.getFieldPtr()[i] : kEndField;
+ // Case 1: currently scanning a field.
+ if (currField != UNUM_FIELD_COUNT) {
+ if (currField != _field) {
+ int32_t end = i - fString.fZero;
+ // Grouping separators can be whitespace; don't throw them out!
+ if (currField != UNUM_GROUPING_SEPARATOR_FIELD) {
+ end = trimBack(i - fString.fZero);
+ }
+ if (end <= fieldStart) {
+ // Entire field position is ignorable; skip.
+ fieldStart = -1;
+ currField = UNUM_FIELD_COUNT;
+ i--; // look at this index again
+ continue;
+ }
+ int32_t start = fieldStart;
+ if (currField != UNUM_GROUPING_SEPARATOR_FIELD) {
+ start = trimFront(start);
+ }
+ auto caf = StringBuilderFieldUtils::expand(currField);
+ cfpos.setState(caf.category, caf.field, start, end);
+ return true;
+ }
+ continue;
+ }
+ // Special case: coalesce the INTEGER if we are pointing at the end of the INTEGER.
+ if (cfpos.matchesField(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD)
+ && i > fString.fZero
+ // don't return the same field twice in a row:
+ && i - fString.fZero > cfpos.getLimit()
+ && isIntOrGroup(fString.getFieldPtr()[i - 1])
+ && !isIntOrGroup(_field)) {
+ int j = i - 1;
+ for (; j >= fString.fZero && isIntOrGroup(fString.getFieldPtr()[j]); j--) {}
+ cfpos.setState(
+ UFIELD_CATEGORY_NUMBER,
+ UNUM_INTEGER_FIELD,
+ j - fString.fZero + 1,
+ i - fString.fZero);
+ return true;
+ }
+ // Special case: coalesce NUMERIC if we are pointing at the end of the NUMERIC.
+ if (numericField != 0
+ && cfpos.matchesField(numericCAF.category, numericCAF.field)
+ && i > fString.fZero
+ // don't return the same field twice in a row:
+ && (i - fString.fZero > cfpos.getLimit()
+ || cfpos.getCategory() != numericCAF.category
+ || cfpos.getField() != numericCAF.field)
+ && isNumericField(fString.getFieldPtr()[i - 1])
+ && !isNumericField(_field)) {
+ int j = i - 1;
+ for (; j >= fString.fZero && isNumericField(fString.getFieldPtr()[j]); j--) {}
+ cfpos.setState(
+ numericCAF.category,
+ numericCAF.field,
+ j - fString.fZero + 1,
+ i - fString.fZero);
+ return true;
+ }
+ // Special case: skip over INTEGER; will be coalesced later.
+ if (_field == UNUM_INTEGER_FIELD) {
+ _field = UNUM_FIELD_COUNT;
+ }
+ // Case 2: no field starting at this position.
+ if (_field == UNUM_FIELD_COUNT || _field == kEndField) {
+ continue;
+ }
+ // Case 3: check for field starting at this position
+ auto caf = StringBuilderFieldUtils::expand(_field);
+ if (cfpos.matchesField(caf.category, caf.field)) {
+ fieldStart = i - fString.fZero;
+ currField = _field;
+ }
+ }
+
+ U_ASSERT(currField == UNUM_FIELD_COUNT);
+ return false;
+}
+
+bool FormattedValueStringBuilderImpl::isIntOrGroup(Field field) {
+ return field == UNUM_INTEGER_FIELD
+ || field == UNUM_GROUPING_SEPARATOR_FIELD;
+}
+
+bool FormattedValueStringBuilderImpl::isNumericField(Field field) {
+ return StringBuilderFieldUtils::isNumericField(field);
+}
+
+int32_t FormattedValueStringBuilderImpl::trimBack(int32_t limit) const {
+ return unisets::get(unisets::DEFAULT_IGNORABLES)->spanBack(
+ fString.getCharPtr() + fString.fZero,
+ limit,
+ USET_SPAN_CONTAINED);
+}
+
+int32_t FormattedValueStringBuilderImpl::trimFront(int32_t start) const {
+ return start + unisets::get(unisets::DEFAULT_IGNORABLES)->span(
+ fString.getCharPtr() + fString.fZero + start,
+ fString.fLength - start,
+ USET_SPAN_CONTAINED);
}
diff --git a/deps/icu-small/source/i18n/funcrepl.cpp b/deps/icu-small/source/i18n/funcrepl.cpp
index 30bcebbf908794..ceb456e1afc50c 100644
--- a/deps/icu-small/source/i18n/funcrepl.cpp
+++ b/deps/icu-small/source/i18n/funcrepl.cpp
@@ -59,7 +59,7 @@ FunctionReplacer::~FunctionReplacer() {
/**
* Implement UnicodeFunctor
*/
-UnicodeFunctor* FunctionReplacer::clone() const {
+FunctionReplacer* FunctionReplacer::clone() const {
return new FunctionReplacer(*this);
}
diff --git a/deps/icu-small/source/i18n/funcrepl.h b/deps/icu-small/source/i18n/funcrepl.h
index a835d5be7c2173..fe41f6caaa6d10 100644
--- a/deps/icu-small/source/i18n/funcrepl.h
+++ b/deps/icu-small/source/i18n/funcrepl.h
@@ -70,7 +70,7 @@ class FunctionReplacer : public UnicodeFunctor, public UnicodeReplacer {
/**
* Implement UnicodeFunctor
*/
- virtual UnicodeFunctor* clone() const;
+ virtual FunctionReplacer* clone() const;
/**
* UnicodeFunctor API. Cast 'this' to a UnicodeReplacer* pointer
diff --git a/deps/icu-small/source/i18n/gender.cpp b/deps/icu-small/source/i18n/gender.cpp
index 106cf424c59d88..03c03cecad94ba 100644
--- a/deps/icu-small/source/i18n/gender.cpp
+++ b/deps/icu-small/source/i18n/gender.cpp
@@ -98,7 +98,7 @@ const GenderInfo* GenderInfo::getInstance(const Locale& locale, UErrorCode& stat
return NULL;
}
- static UMutex gGenderMetaLock = U_MUTEX_INITIALIZER;
+ static UMutex gGenderMetaLock;
const GenderInfo* result = NULL;
const char* key = locale.getName();
{
diff --git a/deps/icu-small/source/i18n/gregocal.cpp b/deps/icu-small/source/i18n/gregocal.cpp
index 4db66758df1f1f..028ab05aa9accc 100644
--- a/deps/icu-small/source/i18n/gregocal.cpp
+++ b/deps/icu-small/source/i18n/gregocal.cpp
@@ -286,7 +286,7 @@ fIsGregorian(source.fIsGregorian), fInvertGregorian(source.fInvertGregorian)
// -------------------------------------
-Calendar* GregorianCalendar::clone() const
+GregorianCalendar* GregorianCalendar::clone() const
{
return new GregorianCalendar(*this);
}
@@ -324,26 +324,26 @@ GregorianCalendar::setGregorianChange(UDate date, UErrorCode& status)
if (U_FAILURE(status))
return;
- fGregorianCutover = date;
-
// Precompute two internal variables which we use to do the actual
// cutover computations. These are the normalized cutover, which is the
// midnight at or before the cutover, and the cutover year. The
// normalized cutover is in pure date milliseconds; it contains no time
// of day or timezone component, and it used to compare against other
// pure date values.
- int32_t cutoverDay = (int32_t)ClockMath::floorDivide(fGregorianCutover, (double)kOneDay);
- fNormalizedGregorianCutover = cutoverDay * kOneDay;
-
- // Handle the rare case of numeric overflow. If the user specifies a
- // change of UDate(Long.MIN_VALUE), in order to get a pure Gregorian
- // calendar, then the epoch day is -106751991168, which when multiplied
- // by ONE_DAY gives 9223372036794351616 -- the negative value is too
- // large for 64 bits, and overflows into a positive value. We correct
- // this by using the next day, which for all intents is semantically
- // equivalent.
- if (cutoverDay < 0 && fNormalizedGregorianCutover > 0) {
- fNormalizedGregorianCutover = (cutoverDay + 1) * kOneDay;
+ double cutoverDay = ClockMath::floorDivide(date, (double)kOneDay);
+
+ // Handle the rare case of numeric overflow where the user specifies a time
+ // outside of INT32_MIN .. INT32_MAX number of days.
+
+ if (cutoverDay <= INT32_MIN) {
+ cutoverDay = INT32_MIN;
+ fGregorianCutover = fNormalizedGregorianCutover = cutoverDay * kOneDay;
+ } else if (cutoverDay >= INT32_MAX) {
+ cutoverDay = INT32_MAX;
+ fGregorianCutover = fNormalizedGregorianCutover = cutoverDay * kOneDay;
+ } else {
+ fNormalizedGregorianCutover = cutoverDay * kOneDay;
+ fGregorianCutover = date;
}
// Normalize the year so BC values are represented as 0 and negative
@@ -360,7 +360,7 @@ GregorianCalendar::setGregorianChange(UDate date, UErrorCode& status)
fGregorianCutoverYear = cal->get(UCAL_YEAR, status);
if (cal->get(UCAL_ERA, status) == BC)
fGregorianCutoverYear = 1 - fGregorianCutoverYear;
- fCutoverJulianDay = cutoverDay;
+ fCutoverJulianDay = (int32_t)cutoverDay;
delete cal;
}
diff --git a/deps/icu-small/source/i18n/hebrwcal.cpp b/deps/icu-small/source/i18n/hebrwcal.cpp
index 66a3e47a4f1e0f..085ded784651a6 100644
--- a/deps/icu-small/source/i18n/hebrwcal.cpp
+++ b/deps/icu-small/source/i18n/hebrwcal.cpp
@@ -169,7 +169,7 @@ const char *HebrewCalendar::getType() const {
return "hebrew";
}
-Calendar* HebrewCalendar::clone() const {
+HebrewCalendar* HebrewCalendar::clone() const {
return new HebrewCalendar(*this);
}
diff --git a/deps/icu-small/source/i18n/hebrwcal.h b/deps/icu-small/source/i18n/hebrwcal.h
index 9323ad62aa72fa..97e8511705e776 100644
--- a/deps/icu-small/source/i18n/hebrwcal.h
+++ b/deps/icu-small/source/i18n/hebrwcal.h
@@ -192,7 +192,7 @@ class U_I18N_API HebrewCalendar : public Calendar {
* @return return a polymorphic copy of this calendar.
* @internal
*/
- virtual Calendar* clone(void) const;
+ virtual HebrewCalendar* clone() const;
public:
/**
diff --git a/deps/icu-small/source/i18n/indiancal.cpp b/deps/icu-small/source/i18n/indiancal.cpp
index 667b6f2d7a32c5..f1266bb7757939 100644
--- a/deps/icu-small/source/i18n/indiancal.cpp
+++ b/deps/icu-small/source/i18n/indiancal.cpp
@@ -35,7 +35,7 @@ U_NAMESPACE_BEGIN
//-------------------------------------------------------------------------
-Calendar* IndianCalendar::clone() const {
+IndianCalendar* IndianCalendar::clone() const {
return new IndianCalendar(*this);
}
diff --git a/deps/icu-small/source/i18n/indiancal.h b/deps/icu-small/source/i18n/indiancal.h
index ffd4ae8b8a40cd..142597ce0e6b02 100644
--- a/deps/icu-small/source/i18n/indiancal.h
+++ b/deps/icu-small/source/i18n/indiancal.h
@@ -186,7 +186,7 @@ class U_I18N_API IndianCalendar : public Calendar {
// TODO: copy c'tor, etc
// clone
- virtual Calendar* clone() const;
+ virtual IndianCalendar* clone() const;
private:
/**
diff --git a/deps/icu-small/source/i18n/islamcal.cpp b/deps/icu-small/source/i18n/islamcal.cpp
index 8d6171af011e5d..4e4a6648048208 100644
--- a/deps/icu-small/source/i18n/islamcal.cpp
+++ b/deps/icu-small/source/i18n/islamcal.cpp
@@ -227,7 +227,7 @@ const char *IslamicCalendar::getType() const {
return sType;
}
-Calendar* IslamicCalendar::clone() const {
+IslamicCalendar* IslamicCalendar::clone() const {
return new IslamicCalendar(*this);
}
@@ -470,7 +470,7 @@ double IslamicCalendar::moonAge(UDate time, UErrorCode &status)
{
double age = 0;
- static UMutex astroLock = U_MUTEX_INITIALIZER; // pod bay door lock
+ static UMutex astroLock; // pod bay door lock
umtx_lock(&astroLock);
if(gIslamicCalendarAstro == NULL) {
gIslamicCalendarAstro = new CalendarAstronomer();
diff --git a/deps/icu-small/source/i18n/islamcal.h b/deps/icu-small/source/i18n/islamcal.h
index 17fb6687ef7b63..aad8f07be0f984 100644
--- a/deps/icu-small/source/i18n/islamcal.h
+++ b/deps/icu-small/source/i18n/islamcal.h
@@ -230,7 +230,7 @@ class U_I18N_API IslamicCalendar : public Calendar {
// TODO: copy c'tor, etc
// clone
- virtual Calendar* clone() const;
+ virtual IslamicCalendar* clone() const;
private:
/**
diff --git a/deps/icu-small/source/i18n/japancal.cpp b/deps/icu-small/source/i18n/japancal.cpp
index cc061fd1410d84..e7e5f4fc5174f6 100644
--- a/deps/icu-small/source/i18n/japancal.cpp
+++ b/deps/icu-small/source/i18n/japancal.cpp
@@ -136,7 +136,7 @@ JapaneseCalendar& JapaneseCalendar::operator= ( const JapaneseCalendar& right)
return *this;
}
-Calendar* JapaneseCalendar::clone(void) const
+JapaneseCalendar* JapaneseCalendar::clone() const
{
return new JapaneseCalendar(*this);
}
diff --git a/deps/icu-small/source/i18n/japancal.h b/deps/icu-small/source/i18n/japancal.h
index a32f3db5635473..ee86c4ed0e3b93 100644
--- a/deps/icu-small/source/i18n/japancal.h
+++ b/deps/icu-small/source/i18n/japancal.h
@@ -116,7 +116,7 @@ class JapaneseCalendar : public GregorianCalendar {
* @return return a polymorphic copy of this calendar.
* @internal
*/
- virtual Calendar* clone(void) const;
+ virtual JapaneseCalendar* clone() const;
/**
* Return the extended year defined by the current fields. In the
diff --git a/deps/icu-small/source/i18n/listformatter.cpp b/deps/icu-small/source/i18n/listformatter.cpp
index 64d2e36ae15059..35cc00de252aa7 100644
--- a/deps/icu-small/source/i18n/listformatter.cpp
+++ b/deps/icu-small/source/i18n/listformatter.cpp
@@ -144,7 +144,7 @@ const ListFormatInternal* ListFormatter::getListFormatInternal(
keyBuffer.append(':', errorCode).append(style, errorCode);
UnicodeString key(keyBuffer.data(), -1, US_INV);
ListFormatInternal* result = nullptr;
- static UMutex listFormatterMutex = U_MUTEX_INITIALIZER;
+ static UMutex listFormatterMutex;
{
Mutex m(&listFormatterMutex);
if (listPatternHash == nullptr) {
@@ -478,8 +478,8 @@ UnicodeString& ListFormatter::format_(
if (index == 0) {
offset = 0;
}
- int32_t offsetFirst;
- int32_t offsetSecond;
+ int32_t offsetFirst = 0;
+ int32_t offsetSecond = 0;
int32_t prefixLength = 0;
// for n items, there are 2 * (n + 1) boundary including 0 and the upper
// edge.
diff --git a/deps/icu-small/source/i18n/measfmt.cpp b/deps/icu-small/source/i18n/measfmt.cpp
index 03e4417e64da6a..47ffb140cf6712 100644
--- a/deps/icu-small/source/i18n/measfmt.cpp
+++ b/deps/icu-small/source/i18n/measfmt.cpp
@@ -55,28 +55,23 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MeasureFormat)
class NumericDateFormatters : public UMemory {
public:
// Formats like H:mm
- SimpleDateFormat hourMinute;
+ UnicodeString hourMinute;
// formats like M:ss
- SimpleDateFormat minuteSecond;
+ UnicodeString minuteSecond;
// formats like H:mm:ss
- SimpleDateFormat hourMinuteSecond;
+ UnicodeString hourMinuteSecond;
// Constructor that takes the actual patterns for hour-minute,
// minute-second, and hour-minute-second respectively.
NumericDateFormatters(
const UnicodeString &hm,
const UnicodeString &ms,
- const UnicodeString &hms,
- UErrorCode &status) :
- hourMinute(hm, status),
- minuteSecond(ms, status),
- hourMinuteSecond(hms, status) {
- const TimeZone *gmt = TimeZone::getGMT();
- hourMinute.setTimeZone(*gmt);
- minuteSecond.setTimeZone(*gmt);
- hourMinuteSecond.setTimeZone(*gmt);
+ const UnicodeString &hms) :
+ hourMinute(hm),
+ minuteSecond(ms),
+ hourMinuteSecond(hms) {
}
private:
NumericDateFormatters(const NumericDateFormatters &other);
@@ -233,8 +228,7 @@ static NumericDateFormatters *loadNumericDateFormatters(
NumericDateFormatters *result = new NumericDateFormatters(
loadNumericDateFormatterPattern(resource, "hm", status),
loadNumericDateFormatterPattern(resource, "ms", status),
- loadNumericDateFormatterPattern(resource, "hms", status),
- status);
+ loadNumericDateFormatterPattern(resource, "hms", status));
if (U_FAILURE(status)) {
delete result;
return NULL;
@@ -466,7 +460,7 @@ UBool MeasureFormat::operator==(const Format &other) const {
**numberFormat == **rhs.numberFormat);
}
-Format *MeasureFormat::clone() const {
+MeasureFormat *MeasureFormat::clone() const {
return new MeasureFormat(*this);
}
@@ -691,9 +685,19 @@ UnicodeString &MeasureFormat::formatMeasure(
}
auto* df = dynamic_cast(&nf);
if (df == nullptr) {
- // Don't know how to handle other types of NumberFormat
- status = U_UNSUPPORTED_ERROR;
- return appendTo;
+ // Handle other types of NumberFormat using the ICU 63 code, modified to
+ // get the unitPattern from LongNameHandler and handle fallback to OTHER.
+ UnicodeString formattedNumber;
+ StandardPlural::Form pluralForm = QuantityFormatter::selectPlural(
+ amtNumber, nf, **pluralRules, formattedNumber, pos, status);
+ UnicodeString pattern = number::impl::LongNameHandler::getUnitPattern(getLocale(status),
+ amtUnit, getUnitWidth(fWidth), pluralForm, status);
+ // The above handles fallback from other widths to short, and from other plural forms to OTHER
+ if (U_FAILURE(status)) {
+ return appendTo;
+ }
+ SimpleFormatter formatter(pattern, 0, 1, status);
+ return QuantityFormatter::format(formatter, formattedNumber, appendTo, pos, status);
}
number::FormattedNumber result;
if (auto* lnf = df->toNumberFormatter(status)) {
@@ -706,135 +710,112 @@ UnicodeString &MeasureFormat::formatMeasure(
return appendTo;
}
-// Formats hours-minutes-seconds as 5:37:23 or similar.
+
+// Formats numeric time duration as 5:00:47 or 3:54.
UnicodeString &MeasureFormat::formatNumeric(
const Formattable *hms, // always length 3
- int32_t bitMap, // 1=hourset, 2=minuteset, 4=secondset
+ int32_t bitMap, // 1=hour set, 2=minute set, 4=second set
UnicodeString &appendTo,
UErrorCode &status) const {
if (U_FAILURE(status)) {
return appendTo;
}
- UDate millis =
- (UDate) (((uprv_trunc(hms[0].getDouble(status)) * 60.0
- + uprv_trunc(hms[1].getDouble(status))) * 60.0
- + uprv_trunc(hms[2].getDouble(status))) * 1000.0);
- switch (bitMap) {
- case 5: // hs
- case 7: // hms
- return formatNumeric(
- millis,
- cache->getNumericDateFormatters()->hourMinuteSecond,
- UDAT_SECOND_FIELD,
- hms[2],
- appendTo,
- status);
- break;
- case 6: // ms
- return formatNumeric(
- millis,
- cache->getNumericDateFormatters()->minuteSecond,
- UDAT_SECOND_FIELD,
- hms[2],
- appendTo,
- status);
- break;
- case 3: // hm
- return formatNumeric(
- millis,
- cache->getNumericDateFormatters()->hourMinute,
- UDAT_MINUTE_FIELD,
- hms[1],
- appendTo,
- status);
- break;
- default:
- status = U_INTERNAL_PROGRAM_ERROR;
- return appendTo;
- break;
- }
-}
-
-static void appendRange(
- const UnicodeString &src,
- int32_t start,
- int32_t end,
- UnicodeString &dest) {
- dest.append(src, start, end - start);
-}
-static void appendRange(
- const UnicodeString &src,
- int32_t end,
- UnicodeString &dest) {
- dest.append(src, end, src.length() - end);
-}
+ UnicodeString pattern;
-// Formats time like 5:37:23
-UnicodeString &MeasureFormat::formatNumeric(
- UDate date, // Time since epoch 1:30:00 would be 5400000
- const DateFormat &dateFmt, // h:mm, m:ss, or h:mm:ss
- UDateFormatField smallestField, // seconds in 5:37:23.5
- const Formattable &smallestAmount, // 23.5 for 5:37:23.5
- UnicodeString &appendTo,
- UErrorCode &status) const {
+ double hours = hms[0].getDouble(status);
+ double minutes = hms[1].getDouble(status);
+ double seconds = hms[2].getDouble(status);
if (U_FAILURE(status)) {
return appendTo;
}
- // Format the smallest amount with this object's NumberFormat
- UnicodeString smallestAmountFormatted;
-
- // We keep track of the integer part of smallest amount so that
- // we can replace it later so that we get '0:00:09.3' instead of
- // '0:00:9.3'
- FieldPosition intFieldPosition(UNUM_INTEGER_FIELD);
- (*numberFormat)->format(
- smallestAmount, smallestAmountFormatted, intFieldPosition, status);
- if (
- intFieldPosition.getBeginIndex() == 0 &&
- intFieldPosition.getEndIndex() == 0) {
+
+ // All possible combinations: "h", "m", "s", "hm", "hs", "ms", "hms"
+ if (bitMap == 5 || bitMap == 7) { // "hms" & "hs" (we add minutes if "hs")
+ pattern = cache->getNumericDateFormatters()->hourMinuteSecond;
+ hours = uprv_trunc(hours);
+ minutes = uprv_trunc(minutes);
+ } else if (bitMap == 3) { // "hm"
+ pattern = cache->getNumericDateFormatters()->hourMinute;
+ hours = uprv_trunc(hours);
+ } else if (bitMap == 6) { // "ms"
+ pattern = cache->getNumericDateFormatters()->minuteSecond;
+ minutes = uprv_trunc(minutes);
+ } else { // h m s, handled outside formatNumeric. No value is also an error.
status = U_INTERNAL_PROGRAM_ERROR;
return appendTo;
}
- // Format time. draft becomes something like '5:30:45'
- // #13606: DateFormat is not thread-safe, but MeasureFormat advertises itself as thread-safe.
- FieldPosition smallestFieldPosition(smallestField);
- UnicodeString draft;
- static UMutex dateFmtMutex = U_MUTEX_INITIALIZER;
- umtx_lock(&dateFmtMutex);
- dateFmt.format(date, draft, smallestFieldPosition, status);
- umtx_unlock(&dateFmtMutex);
-
- // If we find field for smallest amount replace it with the formatted
- // smallest amount from above taking care to replace the integer part
- // with what is in original time. For example, If smallest amount
- // is 9.35s and the formatted time is 0:00:09 then 9.35 becomes 09.35
- // and replacing yields 0:00:09.35
- if (smallestFieldPosition.getBeginIndex() != 0 ||
- smallestFieldPosition.getEndIndex() != 0) {
- appendRange(draft, 0, smallestFieldPosition.getBeginIndex(), appendTo);
- appendRange(
- smallestAmountFormatted,
- 0,
- intFieldPosition.getBeginIndex(),
- appendTo);
- appendRange(
- draft,
- smallestFieldPosition.getBeginIndex(),
- smallestFieldPosition.getEndIndex(),
- appendTo);
- appendRange(
- smallestAmountFormatted,
- intFieldPosition.getEndIndex(),
- appendTo);
- appendRange(
- draft,
- smallestFieldPosition.getEndIndex(),
- appendTo);
+ const DecimalFormat *numberFormatter = dynamic_cast(numberFormat->get());
+ if (!numberFormatter) {
+ status = U_INTERNAL_PROGRAM_ERROR;
+ return appendTo;
+ }
+ number::LocalizedNumberFormatter numberFormatter2;
+ if (auto* lnf = numberFormatter->toNumberFormatter(status)) {
+ numberFormatter2 = lnf->integerWidth(number::IntegerWidth::zeroFillTo(2));
} else {
- appendTo.append(draft);
+ return appendTo;
}
+
+ FormattedStringBuilder fsb;
+
+ UBool protect = FALSE;
+ const int32_t patternLength = pattern.length();
+ for (int32_t i = 0; i < patternLength; i++) {
+ char16_t c = pattern[i];
+
+ // Also set the proper field in this switch
+ // We don't use DateFormat.Field because this is not a date / time, is a duration.
+ double value = 0;
+ switch (c) {
+ case u'H': value = hours; break;
+ case u'm': value = minutes; break;
+ case u's': value = seconds; break;
+ }
+
+ // For undefined field we use UNUM_FIELD_COUNT, for historical reasons.
+ // See cleanup bug: https://unicode-org.atlassian.net/browse/ICU-20665
+ // But we give it a clear name, to keep "the ugly part" in one place.
+ constexpr UNumberFormatFields undefinedField = UNUM_FIELD_COUNT;
+
+ // There is not enough info to add Field(s) for the unit because all we have are plain
+ // text patterns. For example in "21:51" there is no text for something like "hour",
+ // while in something like "21h51" there is ("h"). But we can't really tell...
+ switch (c) {
+ case u'H':
+ case u'm':
+ case u's':
+ if (protect) {
+ fsb.appendChar16(c, undefinedField, status);
+ } else {
+ UnicodeString tmp;
+ if ((i + 1 < patternLength) && pattern[i + 1] == c) { // doubled
+ tmp = numberFormatter2.formatDouble(value, status).toString(status);
+ i++;
+ } else {
+ numberFormatter->format(value, tmp, status);
+ }
+ // TODO: Use proper Field
+ fsb.append(tmp, undefinedField, status);
+ }
+ break;
+ case u'\'':
+ // '' is escaped apostrophe
+ if ((i + 1 < patternLength) && pattern[i + 1] == c) {
+ fsb.appendChar16(c, undefinedField, status);
+ i++;
+ } else {
+ protect = !protect;
+ }
+ break;
+ default:
+ fsb.appendChar16(c, undefinedField, status);
+ }
+ }
+
+ appendTo.append(fsb.toTempUnicodeString());
+
return appendTo;
}
diff --git a/deps/icu-small/source/i18n/measunit.cpp b/deps/icu-small/source/i18n/measunit.cpp
index 428283e6dda8d4..917c0cdfadf235 100644
--- a/deps/icu-small/source/i18n/measunit.cpp
+++ b/deps/icu-small/source/i18n/measunit.cpp
@@ -43,21 +43,22 @@ static const int32_t gOffsets[] = {
29,
328,
339,
- 354,
- 358,
- 366,
+ 355,
+ 359,
368,
- 372,
- 393,
- 395,
- 409,
- 412,
+ 370,
+ 374,
+ 381,
+ 402,
+ 404,
418,
- 426,
- 430,
- 434,
- 436,
- 463
+ 421,
+ 427,
+ 437,
+ 441,
+ 445,
+ 447,
+ 474
};
static const int32_t gIndexes[] = {
@@ -69,21 +70,22 @@ static const int32_t gIndexes[] = {
29,
29,
40,
- 55,
- 59,
- 67,
+ 56,
+ 60,
69,
- 73,
- 94,
- 96,
- 110,
- 113,
+ 71,
+ 75,
+ 82,
+ 103,
+ 105,
119,
- 127,
- 131,
- 135,
- 137,
- 164
+ 122,
+ 128,
+ 138,
+ 142,
+ 146,
+ 148,
+ 175
};
// Must be sorted alphabetically.
@@ -100,6 +102,7 @@ static const char * const gTypes[] = {
"energy",
"force",
"frequency",
+ "graphics",
"length",
"light",
"mass",
@@ -456,6 +459,7 @@ static const char * const gSubTypes[] = {
"century",
"day",
"day-person",
+ "decade",
"hour",
"microsecond",
"millisecond",
@@ -480,12 +484,20 @@ static const char * const gSubTypes[] = {
"kilocalorie",
"kilojoule",
"kilowatt-hour",
+ "therm-us",
"newton",
"pound-force",
"gigahertz",
"hertz",
"kilohertz",
"megahertz",
+ "dot-per-centimeter",
+ "dot-per-inch",
+ "em",
+ "megapixel",
+ "pixel",
+ "pixel-per-centimeter",
+ "pixel-per-inch",
"astronomical-unit",
"centimeter",
"decimeter",
@@ -533,12 +545,14 @@ static const char * const gSubTypes[] = {
"milliwatt",
"watt",
"atmosphere",
+ "bar",
"hectopascal",
"inch-hg",
"kilopascal",
"megapascal",
"millibar",
"millimeter-of-mercury",
+ "pascal",
"pound-per-square-inch",
"kilometer-per-hour",
"knot",
@@ -581,18 +595,20 @@ static const char * const gSubTypes[] = {
// Must be sorted by first value and then second value.
static int32_t unitPerUnitToSingleUnit[][4] = {
- {379, 342, 18, 0},
- {381, 349, 18, 2},
- {383, 342, 18, 3},
- {383, 452, 4, 2},
- {383, 453, 4, 3},
- {402, 449, 3, 1},
- {405, 12, 17, 7},
- {455, 379, 4, 1}
+ {378, 382, 12, 5},
+ {378, 387, 12, 6},
+ {388, 343, 19, 0},
+ {390, 350, 19, 2},
+ {392, 343, 19, 3},
+ {392, 463, 4, 2},
+ {392, 464, 4, 3},
+ {411, 460, 3, 1},
+ {414, 12, 18, 9},
+ {466, 388, 4, 1}
};
// Shortcuts to the base unit in order to make the default constructor fast
-static const int32_t kBaseTypeIdx = 15;
+static const int32_t kBaseTypeIdx = 16;
static const int32_t kBaseSubTypeIdx = 0;
MeasureUnit *MeasureUnit::createGForce(UErrorCode &status) {
@@ -939,102 +955,110 @@ MeasureUnit MeasureUnit::getDayPerson() {
return MeasureUnit(7, 2);
}
-MeasureUnit *MeasureUnit::createHour(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createDecade(UErrorCode &status) {
return MeasureUnit::create(7, 3, status);
}
-MeasureUnit MeasureUnit::getHour() {
+MeasureUnit MeasureUnit::getDecade() {
return MeasureUnit(7, 3);
}
-MeasureUnit *MeasureUnit::createMicrosecond(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createHour(UErrorCode &status) {
return MeasureUnit::create(7, 4, status);
}
-MeasureUnit MeasureUnit::getMicrosecond() {
+MeasureUnit MeasureUnit::getHour() {
return MeasureUnit(7, 4);
}
-MeasureUnit *MeasureUnit::createMillisecond(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createMicrosecond(UErrorCode &status) {
return MeasureUnit::create(7, 5, status);
}
-MeasureUnit MeasureUnit::getMillisecond() {
+MeasureUnit MeasureUnit::getMicrosecond() {
return MeasureUnit(7, 5);
}
-MeasureUnit *MeasureUnit::createMinute(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createMillisecond(UErrorCode &status) {
return MeasureUnit::create(7, 6, status);
}
-MeasureUnit MeasureUnit::getMinute() {
+MeasureUnit MeasureUnit::getMillisecond() {
return MeasureUnit(7, 6);
}
-MeasureUnit *MeasureUnit::createMonth(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createMinute(UErrorCode &status) {
return MeasureUnit::create(7, 7, status);
}
-MeasureUnit MeasureUnit::getMonth() {
+MeasureUnit MeasureUnit::getMinute() {
return MeasureUnit(7, 7);
}
-MeasureUnit *MeasureUnit::createMonthPerson(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createMonth(UErrorCode &status) {
return MeasureUnit::create(7, 8, status);
}
-MeasureUnit MeasureUnit::getMonthPerson() {
+MeasureUnit MeasureUnit::getMonth() {
return MeasureUnit(7, 8);
}
-MeasureUnit *MeasureUnit::createNanosecond(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createMonthPerson(UErrorCode &status) {
return MeasureUnit::create(7, 9, status);
}
-MeasureUnit MeasureUnit::getNanosecond() {
+MeasureUnit MeasureUnit::getMonthPerson() {
return MeasureUnit(7, 9);
}
-MeasureUnit *MeasureUnit::createSecond(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createNanosecond(UErrorCode &status) {
return MeasureUnit::create(7, 10, status);
}
-MeasureUnit MeasureUnit::getSecond() {
+MeasureUnit MeasureUnit::getNanosecond() {
return MeasureUnit(7, 10);
}
-MeasureUnit *MeasureUnit::createWeek(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createSecond(UErrorCode &status) {
return MeasureUnit::create(7, 11, status);
}
-MeasureUnit MeasureUnit::getWeek() {
+MeasureUnit MeasureUnit::getSecond() {
return MeasureUnit(7, 11);
}
-MeasureUnit *MeasureUnit::createWeekPerson(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createWeek(UErrorCode &status) {
return MeasureUnit::create(7, 12, status);
}
-MeasureUnit MeasureUnit::getWeekPerson() {
+MeasureUnit MeasureUnit::getWeek() {
return MeasureUnit(7, 12);
}
-MeasureUnit *MeasureUnit::createYear(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createWeekPerson(UErrorCode &status) {
return MeasureUnit::create(7, 13, status);
}
-MeasureUnit MeasureUnit::getYear() {
+MeasureUnit MeasureUnit::getWeekPerson() {
return MeasureUnit(7, 13);
}
-MeasureUnit *MeasureUnit::createYearPerson(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createYear(UErrorCode &status) {
return MeasureUnit::create(7, 14, status);
}
-MeasureUnit MeasureUnit::getYearPerson() {
+MeasureUnit MeasureUnit::getYear() {
return MeasureUnit(7, 14);
}
+MeasureUnit *MeasureUnit::createYearPerson(UErrorCode &status) {
+ return MeasureUnit::create(7, 15, status);
+}
+
+MeasureUnit MeasureUnit::getYearPerson() {
+ return MeasureUnit(7, 15);
+}
+
MeasureUnit *MeasureUnit::createAmpere(UErrorCode &status) {
return MeasureUnit::create(8, 0, status);
}
@@ -1131,6 +1155,14 @@ MeasureUnit MeasureUnit::getKilowattHour() {
return MeasureUnit(9, 7);
}
+MeasureUnit *MeasureUnit::createThermUs(UErrorCode &status) {
+ return MeasureUnit::create(9, 8, status);
+}
+
+MeasureUnit MeasureUnit::getThermUs() {
+ return MeasureUnit(9, 8);
+}
+
MeasureUnit *MeasureUnit::createNewton(UErrorCode &status) {
return MeasureUnit::create(10, 0, status);
}
@@ -1179,708 +1211,780 @@ MeasureUnit MeasureUnit::getMegahertz() {
return MeasureUnit(11, 3);
}
-MeasureUnit *MeasureUnit::createAstronomicalUnit(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createDotPerCentimeter(UErrorCode &status) {
return MeasureUnit::create(12, 0, status);
}
-MeasureUnit MeasureUnit::getAstronomicalUnit() {
+MeasureUnit MeasureUnit::getDotPerCentimeter() {
return MeasureUnit(12, 0);
}
-MeasureUnit *MeasureUnit::createCentimeter(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createDotPerInch(UErrorCode &status) {
return MeasureUnit::create(12, 1, status);
}
-MeasureUnit MeasureUnit::getCentimeter() {
+MeasureUnit MeasureUnit::getDotPerInch() {
return MeasureUnit(12, 1);
}
-MeasureUnit *MeasureUnit::createDecimeter(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createEm(UErrorCode &status) {
return MeasureUnit::create(12, 2, status);
}
-MeasureUnit MeasureUnit::getDecimeter() {
+MeasureUnit MeasureUnit::getEm() {
return MeasureUnit(12, 2);
}
-MeasureUnit *MeasureUnit::createFathom(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createMegapixel(UErrorCode &status) {
return MeasureUnit::create(12, 3, status);
}
-MeasureUnit MeasureUnit::getFathom() {
+MeasureUnit MeasureUnit::getMegapixel() {
return MeasureUnit(12, 3);
}
-MeasureUnit *MeasureUnit::createFoot(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createPixel(UErrorCode &status) {
return MeasureUnit::create(12, 4, status);
}
-MeasureUnit MeasureUnit::getFoot() {
+MeasureUnit MeasureUnit::getPixel() {
return MeasureUnit(12, 4);
}
-MeasureUnit *MeasureUnit::createFurlong(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createPixelPerCentimeter(UErrorCode &status) {
return MeasureUnit::create(12, 5, status);
}
-MeasureUnit MeasureUnit::getFurlong() {
+MeasureUnit MeasureUnit::getPixelPerCentimeter() {
return MeasureUnit(12, 5);
}
-MeasureUnit *MeasureUnit::createInch(UErrorCode &status) {
+MeasureUnit *MeasureUnit::createPixelPerInch(UErrorCode &status) {
return MeasureUnit::create(12, 6, status);
}
-MeasureUnit MeasureUnit::getInch() {
+MeasureUnit MeasureUnit::getPixelPerInch() {
return MeasureUnit(12, 6);
}
+MeasureUnit *MeasureUnit::createAstronomicalUnit(UErrorCode &status) {
+ return MeasureUnit::create(13, 0, status);
+}
+
+MeasureUnit MeasureUnit::getAstronomicalUnit() {
+ return MeasureUnit(13, 0);
+}
+
+MeasureUnit *MeasureUnit::createCentimeter(UErrorCode &status) {
+ return MeasureUnit::create(13, 1, status);
+}
+
+MeasureUnit MeasureUnit::getCentimeter() {
+ return MeasureUnit(13, 1);
+}
+
+MeasureUnit *MeasureUnit::createDecimeter(UErrorCode &status) {
+ return MeasureUnit::create(13, 2, status);
+}
+
+MeasureUnit MeasureUnit::getDecimeter() {
+ return MeasureUnit(13, 2);
+}
+
+MeasureUnit *MeasureUnit::createFathom(UErrorCode &status) {
+ return MeasureUnit::create(13, 3, status);
+}
+
+MeasureUnit MeasureUnit::getFathom() {
+ return MeasureUnit(13, 3);
+}
+
+MeasureUnit *MeasureUnit::createFoot(UErrorCode &status) {
+ return MeasureUnit::create(13, 4, status);
+}
+
+MeasureUnit MeasureUnit::getFoot() {
+ return MeasureUnit(13, 4);
+}
+
+MeasureUnit *MeasureUnit::createFurlong(UErrorCode &status) {
+ return MeasureUnit::create(13, 5, status);
+}
+
+MeasureUnit MeasureUnit::getFurlong() {
+ return MeasureUnit(13, 5);
+}
+
+MeasureUnit *MeasureUnit::createInch(UErrorCode &status) {
+ return MeasureUnit::create(13, 6, status);
+}
+
+MeasureUnit MeasureUnit::getInch() {
+ return MeasureUnit(13, 6);
+}
+
MeasureUnit *MeasureUnit::createKilometer(UErrorCode &status) {
- return MeasureUnit::create(12, 7, status);
+ return MeasureUnit::create(13, 7, status);
}
MeasureUnit MeasureUnit::getKilometer() {
- return MeasureUnit(12, 7);
+ return MeasureUnit(13, 7);
}
MeasureUnit *MeasureUnit::createLightYear(UErrorCode &status) {
- return MeasureUnit::create(12, 8, status);
+ return MeasureUnit::create(13, 8, status);
}
MeasureUnit MeasureUnit::getLightYear() {
- return MeasureUnit(12, 8);
+ return MeasureUnit(13, 8);
}
MeasureUnit *MeasureUnit::createMeter(UErrorCode &status) {
- return MeasureUnit::create(12, 9, status);
+ return MeasureUnit::create(13, 9, status);
}
MeasureUnit MeasureUnit::getMeter() {
- return MeasureUnit(12, 9);
+ return MeasureUnit(13, 9);
}
MeasureUnit *MeasureUnit::createMicrometer(UErrorCode &status) {
- return MeasureUnit::create(12, 10, status);
+ return MeasureUnit::create(13, 10, status);
}
MeasureUnit MeasureUnit::getMicrometer() {
- return MeasureUnit(12, 10);
+ return MeasureUnit(13, 10);
}
MeasureUnit *MeasureUnit::createMile(UErrorCode &status) {
- return MeasureUnit::create(12, 11, status);
+ return MeasureUnit::create(13, 11, status);
}
MeasureUnit MeasureUnit::getMile() {
- return MeasureUnit(12, 11);
+ return MeasureUnit(13, 11);
}
MeasureUnit *MeasureUnit::createMileScandinavian(UErrorCode &status) {
- return MeasureUnit::create(12, 12, status);
+ return MeasureUnit::create(13, 12, status);
}
MeasureUnit MeasureUnit::getMileScandinavian() {
- return MeasureUnit(12, 12);
+ return MeasureUnit(13, 12);
}
MeasureUnit *MeasureUnit::createMillimeter(UErrorCode &status) {
- return MeasureUnit::create(12, 13, status);
+ return MeasureUnit::create(13, 13, status);
}
MeasureUnit MeasureUnit::getMillimeter() {
- return MeasureUnit(12, 13);
+ return MeasureUnit(13, 13);
}
MeasureUnit *MeasureUnit::createNanometer(UErrorCode &status) {
- return MeasureUnit::create(12, 14, status);
+ return MeasureUnit::create(13, 14, status);
}
MeasureUnit MeasureUnit::getNanometer() {
- return MeasureUnit(12, 14);
+ return MeasureUnit(13, 14);
}
MeasureUnit *MeasureUnit::createNauticalMile(UErrorCode &status) {
- return MeasureUnit::create(12, 15, status);
+ return MeasureUnit::create(13, 15, status);
}
MeasureUnit MeasureUnit::getNauticalMile() {
- return MeasureUnit(12, 15);
+ return MeasureUnit(13, 15);
}
MeasureUnit *MeasureUnit::createParsec(UErrorCode &status) {
- return MeasureUnit::create(12, 16, status);
+ return MeasureUnit::create(13, 16, status);
}
MeasureUnit MeasureUnit::getParsec() {
- return MeasureUnit(12, 16);
+ return MeasureUnit(13, 16);
}
MeasureUnit *MeasureUnit::createPicometer(UErrorCode &status) {
- return MeasureUnit::create(12, 17, status);
+ return MeasureUnit::create(13, 17, status);
}
MeasureUnit MeasureUnit::getPicometer() {
- return MeasureUnit(12, 17);
+ return MeasureUnit(13, 17);
}
MeasureUnit *MeasureUnit::createPoint(UErrorCode &status) {
- return MeasureUnit::create(12, 18, status);
+ return MeasureUnit::create(13, 18, status);
}
MeasureUnit MeasureUnit::getPoint() {
- return MeasureUnit(12, 18);
+ return MeasureUnit(13, 18);
}
MeasureUnit *MeasureUnit::createSolarRadius(UErrorCode &status) {
- return MeasureUnit::create(12, 19, status);
+ return MeasureUnit::create(13, 19, status);
}
MeasureUnit MeasureUnit::getSolarRadius() {
- return MeasureUnit(12, 19);
+ return MeasureUnit(13, 19);
}
MeasureUnit *MeasureUnit::createYard(UErrorCode &status) {
- return MeasureUnit::create(12, 20, status);
+ return MeasureUnit::create(13, 20, status);
}
MeasureUnit MeasureUnit::getYard() {
- return MeasureUnit(12, 20);
+ return MeasureUnit(13, 20);
}
MeasureUnit *MeasureUnit::createLux(UErrorCode &status) {
- return MeasureUnit::create(13, 0, status);
+ return MeasureUnit::create(14, 0, status);
}
MeasureUnit MeasureUnit::getLux() {
- return MeasureUnit(13, 0);
+ return MeasureUnit(14, 0);
}
MeasureUnit *MeasureUnit::createSolarLuminosity(UErrorCode &status) {
- return MeasureUnit::create(13, 1, status);
+ return MeasureUnit::create(14, 1, status);
}
MeasureUnit MeasureUnit::getSolarLuminosity() {
- return MeasureUnit(13, 1);
+ return MeasureUnit(14, 1);
}
MeasureUnit *MeasureUnit::createCarat(UErrorCode &status) {
- return MeasureUnit::create(14, 0, status);
+ return MeasureUnit::create(15, 0, status);
}
MeasureUnit MeasureUnit::getCarat() {
- return MeasureUnit(14, 0);
+ return MeasureUnit(15, 0);
}
MeasureUnit *MeasureUnit::createDalton(UErrorCode &status) {
- return MeasureUnit::create(14, 1, status);
+ return MeasureUnit::create(15, 1, status);
}
MeasureUnit MeasureUnit::getDalton() {
- return MeasureUnit(14, 1);
+ return MeasureUnit(15, 1);
}
MeasureUnit *MeasureUnit::createEarthMass(UErrorCode &status) {
- return MeasureUnit::create(14, 2, status);
+ return MeasureUnit::create(15, 2, status);
}
MeasureUnit MeasureUnit::getEarthMass() {
- return MeasureUnit(14, 2);
+ return MeasureUnit(15, 2);
}
MeasureUnit *MeasureUnit::createGram(UErrorCode &status) {
- return MeasureUnit::create(14, 3, status);
+ return MeasureUnit::create(15, 3, status);
}
MeasureUnit MeasureUnit::getGram() {
- return MeasureUnit(14, 3);
+ return MeasureUnit(15, 3);
}
MeasureUnit *MeasureUnit::createKilogram(UErrorCode &status) {
- return MeasureUnit::create(14, 4, status);
+ return MeasureUnit::create(15, 4, status);
}
MeasureUnit MeasureUnit::getKilogram() {
- return MeasureUnit(14, 4);
+ return MeasureUnit(15, 4);
}
MeasureUnit *MeasureUnit::createMetricTon(UErrorCode &status) {
- return MeasureUnit::create(14, 5, status);
+ return MeasureUnit::create(15, 5, status);
}
MeasureUnit MeasureUnit::getMetricTon() {
- return MeasureUnit(14, 5);
+ return MeasureUnit(15, 5);
}
MeasureUnit *MeasureUnit::createMicrogram(UErrorCode &status) {
- return MeasureUnit::create(14, 6, status);
+ return MeasureUnit::create(15, 6, status);
}
MeasureUnit MeasureUnit::getMicrogram() {
- return MeasureUnit(14, 6);
+ return MeasureUnit(15, 6);
}
MeasureUnit *MeasureUnit::createMilligram(UErrorCode &status) {
- return MeasureUnit::create(14, 7, status);
+ return MeasureUnit::create(15, 7, status);
}
MeasureUnit MeasureUnit::getMilligram() {
- return MeasureUnit(14, 7);
+ return MeasureUnit(15, 7);
}
MeasureUnit *MeasureUnit::createOunce(UErrorCode &status) {
- return MeasureUnit::create(14, 8, status);
+ return MeasureUnit::create(15, 8, status);
}
MeasureUnit MeasureUnit::getOunce() {
- return MeasureUnit(14, 8);
+ return MeasureUnit(15, 8);
}
MeasureUnit *MeasureUnit::createOunceTroy(UErrorCode &status) {
- return MeasureUnit::create(14, 9, status);
+ return MeasureUnit::create(15, 9, status);
}
MeasureUnit MeasureUnit::getOunceTroy() {
- return MeasureUnit(14, 9);
+ return MeasureUnit(15, 9);
}
MeasureUnit *MeasureUnit::createPound(UErrorCode &status) {
- return MeasureUnit::create(14, 10, status);
+ return MeasureUnit::create(15, 10, status);
}
MeasureUnit MeasureUnit::getPound() {
- return MeasureUnit(14, 10);
+ return MeasureUnit(15, 10);
}
MeasureUnit *MeasureUnit::createSolarMass(UErrorCode &status) {
- return MeasureUnit::create(14, 11, status);
+ return MeasureUnit::create(15, 11, status);
}
MeasureUnit MeasureUnit::getSolarMass() {
- return MeasureUnit(14, 11);
+ return MeasureUnit(15, 11);
}
MeasureUnit *MeasureUnit::createStone(UErrorCode &status) {
- return MeasureUnit::create(14, 12, status);
+ return MeasureUnit::create(15, 12, status);
}
MeasureUnit MeasureUnit::getStone() {
- return MeasureUnit(14, 12);
+ return MeasureUnit(15, 12);
}
MeasureUnit *MeasureUnit::createTon(UErrorCode &status) {
- return MeasureUnit::create(14, 13, status);
+ return MeasureUnit::create(15, 13, status);
}
MeasureUnit MeasureUnit::getTon() {
- return MeasureUnit(14, 13);
+ return MeasureUnit(15, 13);
}
MeasureUnit *MeasureUnit::createGigawatt(UErrorCode &status) {
- return MeasureUnit::create(16, 0, status);
+ return MeasureUnit::create(17, 0, status);
}
MeasureUnit MeasureUnit::getGigawatt() {
- return MeasureUnit(16, 0);
+ return MeasureUnit(17, 0);
}
MeasureUnit *MeasureUnit::createHorsepower(UErrorCode &status) {
- return MeasureUnit::create(16, 1, status);
+ return MeasureUnit::create(17, 1, status);
}
MeasureUnit MeasureUnit::getHorsepower() {
- return MeasureUnit(16, 1);
+ return MeasureUnit(17, 1);
}
MeasureUnit *MeasureUnit::createKilowatt(UErrorCode &status) {
- return MeasureUnit::create(16, 2, status);
+ return MeasureUnit::create(17, 2, status);
}
MeasureUnit MeasureUnit::getKilowatt() {
- return MeasureUnit(16, 2);
+ return MeasureUnit(17, 2);
}
MeasureUnit *MeasureUnit::createMegawatt(UErrorCode &status) {
- return MeasureUnit::create(16, 3, status);
+ return MeasureUnit::create(17, 3, status);
}
MeasureUnit MeasureUnit::getMegawatt() {
- return MeasureUnit(16, 3);
+ return MeasureUnit(17, 3);
}
MeasureUnit *MeasureUnit::createMilliwatt(UErrorCode &status) {
- return MeasureUnit::create(16, 4, status);
+ return MeasureUnit::create(17, 4, status);
}
MeasureUnit MeasureUnit::getMilliwatt() {
- return MeasureUnit(16, 4);
+ return MeasureUnit(17, 4);
}
MeasureUnit *MeasureUnit::createWatt(UErrorCode &status) {
- return MeasureUnit::create(16, 5, status);
+ return MeasureUnit::create(17, 5, status);
}
MeasureUnit MeasureUnit::getWatt() {
- return MeasureUnit(16, 5);
+ return MeasureUnit(17, 5);
}
MeasureUnit *MeasureUnit::createAtmosphere(UErrorCode &status) {
- return MeasureUnit::create(17, 0, status);
+ return MeasureUnit::create(18, 0, status);
}
MeasureUnit MeasureUnit::getAtmosphere() {
- return MeasureUnit(17, 0);
+ return MeasureUnit(18, 0);
+}
+
+MeasureUnit *MeasureUnit::createBar(UErrorCode &status) {
+ return MeasureUnit::create(18, 1, status);
+}
+
+MeasureUnit MeasureUnit::getBar() {
+ return MeasureUnit(18, 1);
}
MeasureUnit *MeasureUnit::createHectopascal(UErrorCode &status) {
- return MeasureUnit::create(17, 1, status);
+ return MeasureUnit::create(18, 2, status);
}
MeasureUnit MeasureUnit::getHectopascal() {
- return MeasureUnit(17, 1);
+ return MeasureUnit(18, 2);
}
MeasureUnit *MeasureUnit::createInchHg(UErrorCode &status) {
- return MeasureUnit::create(17, 2, status);
+ return MeasureUnit::create(18, 3, status);
}
MeasureUnit MeasureUnit::getInchHg() {
- return MeasureUnit(17, 2);
+ return MeasureUnit(18, 3);
}
MeasureUnit *MeasureUnit::createKilopascal(UErrorCode &status) {
- return MeasureUnit::create(17, 3, status);
+ return MeasureUnit::create(18, 4, status);
}
MeasureUnit MeasureUnit::getKilopascal() {
- return MeasureUnit(17, 3);
+ return MeasureUnit(18, 4);
}
MeasureUnit *MeasureUnit::createMegapascal(UErrorCode &status) {
- return MeasureUnit::create(17, 4, status);
+ return MeasureUnit::create(18, 5, status);
}
MeasureUnit MeasureUnit::getMegapascal() {
- return MeasureUnit(17, 4);
+ return MeasureUnit(18, 5);
}
MeasureUnit *MeasureUnit::createMillibar(UErrorCode &status) {
- return MeasureUnit::create(17, 5, status);
+ return MeasureUnit::create(18, 6, status);
}
MeasureUnit MeasureUnit::getMillibar() {
- return MeasureUnit(17, 5);
+ return MeasureUnit(18, 6);
}
MeasureUnit *MeasureUnit::createMillimeterOfMercury(UErrorCode &status) {
- return MeasureUnit::create(17, 6, status);
+ return MeasureUnit::create(18, 7, status);
}
MeasureUnit MeasureUnit::getMillimeterOfMercury() {
- return MeasureUnit(17, 6);
+ return MeasureUnit(18, 7);
+}
+
+MeasureUnit *MeasureUnit::createPascal(UErrorCode &status) {
+ return MeasureUnit::create(18, 8, status);
+}
+
+MeasureUnit MeasureUnit::getPascal() {
+ return MeasureUnit(18, 8);
}
MeasureUnit *MeasureUnit::createPoundPerSquareInch(UErrorCode &status) {
- return MeasureUnit::create(17, 7, status);
+ return MeasureUnit::create(18, 9, status);
}
MeasureUnit MeasureUnit::getPoundPerSquareInch() {
- return MeasureUnit(17, 7);
+ return MeasureUnit(18, 9);
}
MeasureUnit *MeasureUnit::createKilometerPerHour(UErrorCode &status) {
- return MeasureUnit::create(18, 0, status);
+ return MeasureUnit::create(19, 0, status);
}
MeasureUnit MeasureUnit::getKilometerPerHour() {
- return MeasureUnit(18, 0);
+ return MeasureUnit(19, 0);
}
MeasureUnit *MeasureUnit::createKnot(UErrorCode &status) {
- return MeasureUnit::create(18, 1, status);
+ return MeasureUnit::create(19, 1, status);
}
MeasureUnit MeasureUnit::getKnot() {
- return MeasureUnit(18, 1);
+ return MeasureUnit(19, 1);
}
MeasureUnit *MeasureUnit::createMeterPerSecond(UErrorCode &status) {
- return MeasureUnit::create(18, 2, status);
+ return MeasureUnit::create(19, 2, status);
}
MeasureUnit MeasureUnit::getMeterPerSecond() {
- return MeasureUnit(18, 2);
+ return MeasureUnit(19, 2);
}
MeasureUnit *MeasureUnit::createMilePerHour(UErrorCode &status) {
- return MeasureUnit::create(18, 3, status);
+ return MeasureUnit::create(19, 3, status);
}
MeasureUnit MeasureUnit::getMilePerHour() {
- return MeasureUnit(18, 3);
+ return MeasureUnit(19, 3);
}
MeasureUnit *MeasureUnit::createCelsius(UErrorCode &status) {
- return MeasureUnit::create(19, 0, status);
+ return MeasureUnit::create(20, 0, status);
}
MeasureUnit MeasureUnit::getCelsius() {
- return MeasureUnit(19, 0);
+ return MeasureUnit(20, 0);
}
MeasureUnit *MeasureUnit::createFahrenheit(UErrorCode &status) {
- return MeasureUnit::create(19, 1, status);
+ return MeasureUnit::create(20, 1, status);
}
MeasureUnit MeasureUnit::getFahrenheit() {
- return MeasureUnit(19, 1);
+ return MeasureUnit(20, 1);
}
MeasureUnit *MeasureUnit::createGenericTemperature(UErrorCode &status) {
- return MeasureUnit::create(19, 2, status);
+ return MeasureUnit::create(20, 2, status);
}
MeasureUnit MeasureUnit::getGenericTemperature() {
- return MeasureUnit(19, 2);
+ return MeasureUnit(20, 2);
}
MeasureUnit *MeasureUnit::createKelvin(UErrorCode &status) {
- return MeasureUnit::create(19, 3, status);
+ return MeasureUnit::create(20, 3, status);
}
MeasureUnit MeasureUnit::getKelvin() {
- return MeasureUnit(19, 3);
+ return MeasureUnit(20, 3);
}
MeasureUnit *MeasureUnit::createNewtonMeter(UErrorCode &status) {
- return MeasureUnit::create(20, 0, status);
+ return MeasureUnit::create(21, 0, status);
}
MeasureUnit MeasureUnit::getNewtonMeter() {
- return MeasureUnit(20, 0);
+ return MeasureUnit(21, 0);
}
MeasureUnit *MeasureUnit::createPoundFoot(UErrorCode &status) {
- return MeasureUnit::create(20, 1, status);
+ return MeasureUnit::create(21, 1, status);
}
MeasureUnit MeasureUnit::getPoundFoot() {
- return MeasureUnit(20, 1);
+ return MeasureUnit(21, 1);
}
MeasureUnit *MeasureUnit::createAcreFoot(UErrorCode &status) {
- return MeasureUnit::create(21, 0, status);
+ return MeasureUnit::create(22, 0, status);
}
MeasureUnit MeasureUnit::getAcreFoot() {
- return MeasureUnit(21, 0);
+ return MeasureUnit(22, 0);
}
MeasureUnit *MeasureUnit::createBarrel(UErrorCode &status) {
- return MeasureUnit::create(21, 1, status);
+ return MeasureUnit::create(22, 1, status);
}
MeasureUnit MeasureUnit::getBarrel() {
- return MeasureUnit(21, 1);
+ return MeasureUnit(22, 1);
}
MeasureUnit *MeasureUnit::createBushel(UErrorCode &status) {
- return MeasureUnit::create(21, 2, status);
+ return MeasureUnit::create(22, 2, status);
}
MeasureUnit MeasureUnit::getBushel() {
- return MeasureUnit(21, 2);
+ return MeasureUnit(22, 2);
}
MeasureUnit *MeasureUnit::createCentiliter(UErrorCode &status) {
- return MeasureUnit::create(21, 3, status);
+ return MeasureUnit::create(22, 3, status);
}
MeasureUnit MeasureUnit::getCentiliter() {
- return MeasureUnit(21, 3);
+ return MeasureUnit(22, 3);
}
MeasureUnit *MeasureUnit::createCubicCentimeter(UErrorCode &status) {
- return MeasureUnit::create(21, 4, status);
+ return MeasureUnit::create(22, 4, status);
}
MeasureUnit MeasureUnit::getCubicCentimeter() {
- return MeasureUnit(21, 4);
+ return MeasureUnit(22, 4);
}
MeasureUnit *MeasureUnit::createCubicFoot(UErrorCode &status) {
- return MeasureUnit::create(21, 5, status);
+ return MeasureUnit::create(22, 5, status);
}
MeasureUnit MeasureUnit::getCubicFoot() {
- return MeasureUnit(21, 5);
+ return MeasureUnit(22, 5);
}
MeasureUnit *MeasureUnit::createCubicInch(UErrorCode &status) {
- return MeasureUnit::create(21, 6, status);
+ return MeasureUnit::create(22, 6, status);
}
MeasureUnit MeasureUnit::getCubicInch() {
- return MeasureUnit(21, 6);
+ return MeasureUnit(22, 6);
}
MeasureUnit *MeasureUnit::createCubicKilometer(UErrorCode &status) {
- return MeasureUnit::create(21, 7, status);
+ return MeasureUnit::create(22, 7, status);
}
MeasureUnit MeasureUnit::getCubicKilometer() {
- return MeasureUnit(21, 7);
+ return MeasureUnit(22, 7);
}
MeasureUnit *MeasureUnit::createCubicMeter(UErrorCode &status) {
- return MeasureUnit::create(21, 8, status);
+ return MeasureUnit::create(22, 8, status);
}
MeasureUnit MeasureUnit::getCubicMeter() {
- return MeasureUnit(21, 8);
+ return MeasureUnit(22, 8);
}
MeasureUnit *MeasureUnit::createCubicMile(UErrorCode &status) {
- return MeasureUnit::create(21, 9, status);
+ return MeasureUnit::create(22, 9, status);
}
MeasureUnit MeasureUnit::getCubicMile() {
- return MeasureUnit(21, 9);
+ return MeasureUnit(22, 9);
}
MeasureUnit *MeasureUnit::createCubicYard(UErrorCode &status) {
- return MeasureUnit::create(21, 10, status);
+ return MeasureUnit::create(22, 10, status);
}
MeasureUnit MeasureUnit::getCubicYard() {
- return MeasureUnit(21, 10);
+ return MeasureUnit(22, 10);
}
MeasureUnit *MeasureUnit::createCup(UErrorCode &status) {
- return MeasureUnit::create(21, 11, status);
+ return MeasureUnit::create(22, 11, status);
}
MeasureUnit MeasureUnit::getCup() {
- return MeasureUnit(21, 11);
+ return MeasureUnit(22, 11);
}
MeasureUnit *MeasureUnit::createCupMetric(UErrorCode &status) {
- return MeasureUnit::create(21, 12, status);
+ return MeasureUnit::create(22, 12, status);
}
MeasureUnit MeasureUnit::getCupMetric() {
- return MeasureUnit(21, 12);
+ return MeasureUnit(22, 12);
}
MeasureUnit *MeasureUnit::createDeciliter(UErrorCode &status) {
- return MeasureUnit::create(21, 13, status);
+ return MeasureUnit::create(22, 13, status);
}
MeasureUnit MeasureUnit::getDeciliter() {
- return MeasureUnit(21, 13);
+ return MeasureUnit(22, 13);
}
MeasureUnit *MeasureUnit::createFluidOunce(UErrorCode &status) {
- return MeasureUnit::create(21, 14, status);
+ return MeasureUnit::create(22, 14, status);
}
MeasureUnit MeasureUnit::getFluidOunce() {
- return MeasureUnit(21, 14);
+ return MeasureUnit(22, 14);
}
MeasureUnit *MeasureUnit::createFluidOunceImperial(UErrorCode &status) {
- return MeasureUnit::create(21, 15, status);
+ return MeasureUnit::create(22, 15, status);
}
MeasureUnit MeasureUnit::getFluidOunceImperial() {
- return MeasureUnit(21, 15);
+ return MeasureUnit(22, 15);
}
MeasureUnit *MeasureUnit::createGallon(UErrorCode &status) {
- return MeasureUnit::create(21, 16, status);
+ return MeasureUnit::create(22, 16, status);
}
MeasureUnit MeasureUnit::getGallon() {
- return MeasureUnit(21, 16);
+ return MeasureUnit(22, 16);
}
MeasureUnit *MeasureUnit::createGallonImperial(UErrorCode &status) {
- return MeasureUnit::create(21, 17, status);
+ return MeasureUnit::create(22, 17, status);
}
MeasureUnit MeasureUnit::getGallonImperial() {
- return MeasureUnit(21, 17);
+ return MeasureUnit(22, 17);
}
MeasureUnit *MeasureUnit::createHectoliter(UErrorCode &status) {
- return MeasureUnit::create(21, 18, status);
+ return MeasureUnit::create(22, 18, status);
}
MeasureUnit MeasureUnit::getHectoliter() {
- return MeasureUnit(21, 18);
+ return MeasureUnit(22, 18);
}
MeasureUnit *MeasureUnit::createLiter(UErrorCode &status) {
- return MeasureUnit::create(21, 19, status);
+ return MeasureUnit::create(22, 19, status);
}
MeasureUnit MeasureUnit::getLiter() {
- return MeasureUnit(21, 19);
+ return MeasureUnit(22, 19);
}
MeasureUnit *MeasureUnit::createMegaliter(UErrorCode &status) {
- return MeasureUnit::create(21, 20, status);
+ return MeasureUnit::create(22, 20, status);
}
MeasureUnit MeasureUnit::getMegaliter() {
- return MeasureUnit(21, 20);
+ return MeasureUnit(22, 20);
}
MeasureUnit *MeasureUnit::createMilliliter(UErrorCode &status) {
- return MeasureUnit::create(21, 21, status);
+ return MeasureUnit::create(22, 21, status);
}
MeasureUnit MeasureUnit::getMilliliter() {
- return MeasureUnit(21, 21);
+ return MeasureUnit(22, 21);
}
MeasureUnit *MeasureUnit::createPint(UErrorCode &status) {
- return MeasureUnit::create(21, 22, status);
+ return MeasureUnit::create(22, 22, status);
}
MeasureUnit MeasureUnit::getPint() {
- return MeasureUnit(21, 22);
+ return MeasureUnit(22, 22);
}
MeasureUnit *MeasureUnit::createPintMetric(UErrorCode &status) {
- return MeasureUnit::create(21, 23, status);
+ return MeasureUnit::create(22, 23, status);
}
MeasureUnit MeasureUnit::getPintMetric() {
- return MeasureUnit(21, 23);
+ return MeasureUnit(22, 23);
}
MeasureUnit *MeasureUnit::createQuart(UErrorCode &status) {
- return MeasureUnit::create(21, 24, status);
+ return MeasureUnit::create(22, 24, status);
}
MeasureUnit MeasureUnit::getQuart() {
- return MeasureUnit(21, 24);
+ return MeasureUnit(22, 24);
}
MeasureUnit *MeasureUnit::createTablespoon(UErrorCode &status) {
- return MeasureUnit::create(21, 25, status);
+ return MeasureUnit::create(22, 25, status);
}
MeasureUnit MeasureUnit::getTablespoon() {
- return MeasureUnit(21, 25);
+ return MeasureUnit(22, 25);
}
MeasureUnit *MeasureUnit::createTeaspoon(UErrorCode &status) {
- return MeasureUnit::create(21, 26, status);
+ return MeasureUnit::create(22, 26, status);
}
MeasureUnit MeasureUnit::getTeaspoon() {
- return MeasureUnit(21, 26);
+ return MeasureUnit(22, 26);
}
// End generated code
@@ -1923,7 +2027,7 @@ MeasureUnit &MeasureUnit::operator=(const MeasureUnit &other) {
return *this;
}
-UObject *MeasureUnit::clone() const {
+MeasureUnit *MeasureUnit::clone() const {
return new MeasureUnit(*this);
}
diff --git a/deps/icu-small/source/i18n/measure.cpp b/deps/icu-small/source/i18n/measure.cpp
index d9084f87db2baa..bffa44215e3cde 100644
--- a/deps/icu-small/source/i18n/measure.cpp
+++ b/deps/icu-small/source/i18n/measure.cpp
@@ -43,12 +43,12 @@ Measure& Measure::operator=(const Measure& other) {
if (this != &other) {
delete unit;
number = other.number;
- unit = (MeasureUnit*) other.unit->clone();
+ unit = other.unit->clone();
}
return *this;
}
-UObject *Measure::clone() const {
+Measure *Measure::clone() const {
return new Measure(*this);
}
diff --git a/deps/icu-small/source/i18n/msgfmt.cpp b/deps/icu-small/source/i18n/msgfmt.cpp
index e39b26b969889f..3ca368ef954846 100644
--- a/deps/icu-small/source/i18n/msgfmt.cpp
+++ b/deps/icu-small/source/i18n/msgfmt.cpp
@@ -436,7 +436,7 @@ MessageFormat::operator==(const Format& rhs) const
// -------------------------------------
// Creates a copy of this MessageFormat, the caller owns the copy.
-Format*
+MessageFormat*
MessageFormat::clone() const
{
return new MessageFormat(*this);
@@ -813,7 +813,7 @@ MessageFormat::getFormats(int32_t& cnt) const
// Get total required capacity first (it's refreshed on each call).
int32_t totalCapacity = 0;
- for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0; ++totalCapacity) {};
+ for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0; ++totalCapacity) {}
MessageFormat* t = const_cast (this);
cnt = 0;
@@ -1873,7 +1873,7 @@ UBool MessageFormat::DummyFormat::operator==(const Format&) const {
return TRUE;
}
-Format* MessageFormat::DummyFormat::clone() const {
+MessageFormat::DummyFormat* MessageFormat::DummyFormat::clone() const {
return new DummyFormat();
}
diff --git a/deps/icu-small/source/i18n/name2uni.cpp b/deps/icu-small/source/i18n/name2uni.cpp
index d901eb126a8a46..90bca9d71bef87 100644
--- a/deps/icu-small/source/i18n/name2uni.cpp
+++ b/deps/icu-small/source/i18n/name2uni.cpp
@@ -100,7 +100,7 @@ NameUnicodeTransliterator::NameUnicodeTransliterator(const NameUnicodeTransliter
/**
* Transliterator API.
*/
-Transliterator* NameUnicodeTransliterator::clone(void) const {
+NameUnicodeTransliterator* NameUnicodeTransliterator::clone() const {
return new NameUnicodeTransliterator(*this);
}
diff --git a/deps/icu-small/source/i18n/name2uni.h b/deps/icu-small/source/i18n/name2uni.h
index 4c743def32ede2..44ad85fb822cb3 100644
--- a/deps/icu-small/source/i18n/name2uni.h
+++ b/deps/icu-small/source/i18n/name2uni.h
@@ -49,7 +49,7 @@ class NameUnicodeTransliterator : public Transliterator {
* Transliterator API.
* @return A copy of the object.
*/
- virtual Transliterator* clone(void) const;
+ virtual NameUnicodeTransliterator* clone() const;
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
diff --git a/deps/icu-small/source/i18n/nortrans.cpp b/deps/icu-small/source/i18n/nortrans.cpp
index 589c82482ec9b9..6a8d2c74194fb0 100644
--- a/deps/icu-small/source/i18n/nortrans.cpp
+++ b/deps/icu-small/source/i18n/nortrans.cpp
@@ -92,7 +92,7 @@ NormalizationTransliterator::NormalizationTransliterator(const NormalizationTran
/**
* Transliterator API.
*/
-Transliterator* NormalizationTransliterator::clone(void) const {
+NormalizationTransliterator* NormalizationTransliterator::clone() const {
return new NormalizationTransliterator(*this);
}
diff --git a/deps/icu-small/source/i18n/nortrans.h b/deps/icu-small/source/i18n/nortrans.h
index d309452f9a4d6a..198ed29c95e70f 100644
--- a/deps/icu-small/source/i18n/nortrans.h
+++ b/deps/icu-small/source/i18n/nortrans.h
@@ -44,7 +44,7 @@ class NormalizationTransliterator : public Transliterator {
* Transliterator API.
* @return A copy of the object.
*/
- virtual Transliterator* clone(void) const;
+ virtual NormalizationTransliterator* clone() const;
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
diff --git a/deps/icu-small/source/i18n/nounit.cpp b/deps/icu-small/source/i18n/nounit.cpp
index db07387c590af8..076f76f199c737 100644
--- a/deps/icu-small/source/i18n/nounit.cpp
+++ b/deps/icu-small/source/i18n/nounit.cpp
@@ -29,7 +29,7 @@ NoUnit::NoUnit(const char* subtype) {
NoUnit::NoUnit(const NoUnit& other) : MeasureUnit(other) {
}
-UObject* NoUnit::clone() const {
+NoUnit* NoUnit::clone() const {
return new NoUnit(*this);
}
diff --git a/deps/icu-small/source/i18n/nultrans.cpp b/deps/icu-small/source/i18n/nultrans.cpp
index 62d1290ac75e93..439cc55d381a2a 100644
--- a/deps/icu-small/source/i18n/nultrans.cpp
+++ b/deps/icu-small/source/i18n/nultrans.cpp
@@ -24,7 +24,7 @@ NullTransliterator::NullTransliterator() : Transliterator(UNICODE_STRING_SIMPLE(
NullTransliterator::~NullTransliterator() {}
-Transliterator* NullTransliterator::clone(void) const {
+NullTransliterator* NullTransliterator::clone() const {
return new NullTransliterator();
}
diff --git a/deps/icu-small/source/i18n/nultrans.h b/deps/icu-small/source/i18n/nultrans.h
index a01b04e9ba1ec9..36c92fa7b189d3 100644
--- a/deps/icu-small/source/i18n/nultrans.h
+++ b/deps/icu-small/source/i18n/nultrans.h
@@ -45,7 +45,7 @@ class NullTransliterator : public Transliterator {
* Transliterator API.
* @internal Use transliterator factory methods instead since this class will be removed in that release.
*/
- virtual Transliterator* clone(void) const;
+ virtual NullTransliterator* clone() const;
/**
* Implements {@link Transliterator#handleTransliterate}.
diff --git a/deps/icu-small/source/i18n/number_affixutils.cpp b/deps/icu-small/source/i18n/number_affixutils.cpp
index 3eb9c59bf49090..1039a84c656124 100644
--- a/deps/icu-small/source/i18n/number_affixutils.cpp
+++ b/deps/icu-small/source/i18n/number_affixutils.cpp
@@ -156,7 +156,7 @@ Field AffixUtils::getFieldForType(AffixPatternType type) {
}
int32_t
-AffixUtils::unescape(const UnicodeString &affixPattern, NumberStringBuilder &output, int32_t position,
+AffixUtils::unescape(const UnicodeString &affixPattern, FormattedStringBuilder &output, int32_t position,
const SymbolProvider &provider, Field field, UErrorCode &status) {
int32_t length = 0;
AffixTag tag;
@@ -230,7 +230,7 @@ UnicodeString AffixUtils::replaceType(const UnicodeString &affixPattern, AffixPa
UnicodeString output(affixPattern); // copy
if (affixPattern.length() == 0) {
return output;
- };
+ }
AffixTag tag;
while (hasNext(tag, affixPattern)) {
tag = nextToken(tag, affixPattern, status);
@@ -246,7 +246,7 @@ bool AffixUtils::containsOnlySymbolsAndIgnorables(const UnicodeString& affixPatt
const UnicodeSet& ignorables, UErrorCode& status) {
if (affixPattern.length() == 0) {
return true;
- };
+ }
AffixTag tag;
while (hasNext(tag, affixPattern)) {
tag = nextToken(tag, affixPattern, status);
@@ -262,7 +262,7 @@ void AffixUtils::iterateWithConsumer(const UnicodeString& affixPattern, TokenCon
UErrorCode& status) {
if (affixPattern.length() == 0) {
return;
- };
+ }
AffixTag tag;
while (hasNext(tag, affixPattern)) {
tag = nextToken(tag, affixPattern, status);
diff --git a/deps/icu-small/source/i18n/number_affixutils.h b/deps/icu-small/source/i18n/number_affixutils.h
index f011a54b316166..5cfde61ffd0ca2 100644
--- a/deps/icu-small/source/i18n/number_affixutils.h
+++ b/deps/icu-small/source/i18n/number_affixutils.h
@@ -11,7 +11,7 @@
#include "number_types.h"
#include "unicode/stringpiece.h"
#include "unicode/unistr.h"
-#include "number_stringbuilder.h"
+#include "formatted_string_builder.h"
#include "unicode/uniset.h"
U_NAMESPACE_BEGIN namespace number {
@@ -134,16 +134,16 @@ class U_I18N_API AffixUtils {
/**
* Executes the unescape state machine. Replaces the unquoted characters "-", "+", "%", "‰", and
* "¤" with the corresponding symbols provided by the {@link SymbolProvider}, and inserts the
- * result into the NumberStringBuilder at the requested location.
+ * result into the FormattedStringBuilder at the requested location.
*
* Example input: "'-'¤x"; example output: "-$x"
*
* @param affixPattern The original string to be unescaped.
- * @param output The NumberStringBuilder to mutate with the result.
- * @param position The index into the NumberStringBuilder to insert the string.
+ * @param output The FormattedStringBuilder to mutate with the result.
+ * @param position The index into the FormattedStringBuilder to insert the string.
* @param provider An object to generate locale symbols.
*/
- static int32_t unescape(const UnicodeString& affixPattern, NumberStringBuilder& output,
+ static int32_t unescape(const UnicodeString& affixPattern, FormattedStringBuilder& output,
int32_t position, const SymbolProvider& provider, Field field,
UErrorCode& status);
diff --git a/deps/icu-small/source/i18n/number_asformat.cpp b/deps/icu-small/source/i18n/number_asformat.cpp
index 9d3ea69f578e1e..e876174fdce0ee 100644
--- a/deps/icu-small/source/i18n/number_asformat.cpp
+++ b/deps/icu-small/source/i18n/number_asformat.cpp
@@ -43,7 +43,7 @@ UBool LocalizedNumberFormatterAsFormat::operator==(const Format& other) const {
return fFormatter.toSkeleton(localStatus) == _other->fFormatter.toSkeleton(localStatus);
}
-Format* LocalizedNumberFormatterAsFormat::clone() const {
+LocalizedNumberFormatterAsFormat* LocalizedNumberFormatterAsFormat::clone() const {
return new LocalizedNumberFormatterAsFormat(*this);
}
@@ -62,12 +62,12 @@ UnicodeString& LocalizedNumberFormatterAsFormat::format(const Formattable& obj,
// always return first occurrence:
pos.setBeginIndex(0);
pos.setEndIndex(0);
- bool found = data.getStringRef().nextFieldPosition(pos, status);
+ bool found = data.nextFieldPosition(pos, status);
if (found && appendTo.length() != 0) {
pos.setBeginIndex(pos.getBeginIndex() + appendTo.length());
pos.setEndIndex(pos.getEndIndex() + appendTo.length());
}
- appendTo.append(data.getStringRef().toTempUnicodeString());
+ appendTo.append(data.toTempString(status));
return appendTo;
}
@@ -84,10 +84,10 @@ UnicodeString& LocalizedNumberFormatterAsFormat::format(const Formattable& obj,
if (U_FAILURE(status)) {
return appendTo;
}
- appendTo.append(data.getStringRef().toTempUnicodeString());
+ appendTo.append(data.toTempString(status));
if (posIter != nullptr) {
FieldPositionIteratorHandler fpih(posIter, status);
- data.getStringRef().getAllFieldPositions(fpih, status);
+ data.getAllFieldPositions(fpih, status);
}
return appendTo;
}
diff --git a/deps/icu-small/source/i18n/number_asformat.h b/deps/icu-small/source/i18n/number_asformat.h
index bf82d72ae302a4..7b0a1dee6f438b 100644
--- a/deps/icu-small/source/i18n/number_asformat.h
+++ b/deps/icu-small/source/i18n/number_asformat.h
@@ -45,7 +45,7 @@ class U_I18N_API LocalizedNumberFormatterAsFormat : public Format {
/**
* Creates a copy of this object.
*/
- Format* clone() const U_OVERRIDE;
+ LocalizedNumberFormatterAsFormat* clone() const U_OVERRIDE;
/**
* Formats a Number using the wrapped LocalizedNumberFormatter. The provided formattable must be a
diff --git a/deps/icu-small/source/i18n/number_compact.cpp b/deps/icu-small/source/i18n/number_compact.cpp
index f330251be38c88..3d259999d6ce52 100644
--- a/deps/icu-small/source/i18n/number_compact.cpp
+++ b/deps/icu-small/source/i18n/number_compact.cpp
@@ -272,15 +272,15 @@ void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micr
parent->processQuantity(quantity, micros, status);
if (U_FAILURE(status)) { return; }
- // Treat zero as if it had magnitude 0
+ // Treat zero, NaN, and infinity as if they had magnitude 0
int32_t magnitude;
- if (quantity.isZero()) {
+ if (quantity.isZeroish()) {
magnitude = 0;
micros.rounder.apply(quantity, status);
} else {
// TODO: Revisit chooseMultiplierAndApply
int32_t multiplier = micros.rounder.chooseMultiplierAndApply(quantity, data, status);
- magnitude = quantity.isZero() ? 0 : quantity.getMagnitude();
+ magnitude = quantity.isZeroish() ? 0 : quantity.getMagnitude();
magnitude -= multiplier;
}
diff --git a/deps/icu-small/source/i18n/number_currencysymbols.cpp b/deps/icu-small/source/i18n/number_currencysymbols.cpp
index 0b79d6596f18c0..4d6fb2cb1d8dec 100644
--- a/deps/icu-small/source/i18n/number_currencysymbols.cpp
+++ b/deps/icu-small/source/i18n/number_currencysymbols.cpp
@@ -53,13 +53,12 @@ UnicodeString CurrencySymbols::getCurrencySymbol(UErrorCode& status) const {
UnicodeString CurrencySymbols::loadSymbol(UCurrNameStyle selector, UErrorCode& status) const {
const char16_t* isoCode = fCurrency.getISOCurrency();
- UBool ignoredIsChoiceFormatFillIn = FALSE;
int32_t symbolLen = 0;
const char16_t* symbol = ucurr_getName(
isoCode,
fLocaleName.data(),
selector,
- &ignoredIsChoiceFormatFillIn,
+ nullptr /* isChoiceFormat */,
&symbolLen,
&status);
// If given an unknown currency, ucurr_getName returns the input string, which we can't alias safely!
@@ -82,12 +81,11 @@ UnicodeString CurrencySymbols::getIntlCurrencySymbol(UErrorCode&) const {
UnicodeString CurrencySymbols::getPluralName(StandardPlural::Form plural, UErrorCode& status) const {
const char16_t* isoCode = fCurrency.getISOCurrency();
- UBool isChoiceFormat = FALSE;
int32_t symbolLen = 0;
const char16_t* symbol = ucurr_getPluralName(
isoCode,
fLocaleName.data(),
- &isChoiceFormat,
+ nullptr /* isChoiceFormat */,
StandardPlural::getKeyword(plural),
&symbolLen,
&status);
diff --git a/deps/icu-small/source/i18n/number_decimalquantity.cpp b/deps/icu-small/source/i18n/number_decimalquantity.cpp
index d899c27671181e..2c4c2ce7e9931b 100644
--- a/deps/icu-small/source/i18n/number_decimalquantity.cpp
+++ b/deps/icu-small/source/i18n/number_decimalquantity.cpp
@@ -205,7 +205,7 @@ void DecimalQuantity::roundToIncrement(double roundingIncrement, RoundingMode ro
}
void DecimalQuantity::multiplyBy(const DecNum& multiplicand, UErrorCode& status) {
- if (isInfinite() || isZero() || isNaN()) {
+ if (isZeroish()) {
return;
}
// Convert to DecNum, multiply, and convert back.
@@ -218,7 +218,7 @@ void DecimalQuantity::multiplyBy(const DecNum& multiplicand, UErrorCode& status)
}
void DecimalQuantity::divideBy(const DecNum& divisor, UErrorCode& status) {
- if (isInfinite() || isZero() || isNaN()) {
+ if (isZeroish()) {
return;
}
// Convert to DecNum, multiply, and convert back.
@@ -318,8 +318,14 @@ bool DecimalQuantity::isNegative() const {
return (flags & NEGATIVE_FLAG) != 0;
}
-int8_t DecimalQuantity::signum() const {
- return isNegative() ? -1 : isZero() ? 0 : 1;
+Signum DecimalQuantity::signum() const {
+ if (isNegative()) {
+ return SIGNUM_NEG;
+ } else if (isZeroish() && !isInfinite()) {
+ return SIGNUM_ZERO;
+ } else {
+ return SIGNUM_POS;
+ }
}
bool DecimalQuantity::isInfinite() const {
@@ -330,7 +336,7 @@ bool DecimalQuantity::isNaN() const {
return (flags & NAN_FLAG) != 0;
}
-bool DecimalQuantity::isZero() const {
+bool DecimalQuantity::isZeroish() const {
return precision == 0;
}
@@ -548,7 +554,10 @@ uint64_t DecimalQuantity::toFractionLong(bool includeTrailingZeros) const {
}
bool DecimalQuantity::fitsInLong(bool ignoreFraction) const {
- if (isZero()) {
+ if (isInfinite() || isNaN()) {
+ return false;
+ }
+ if (isZeroish()) {
return true;
}
if (scale < 0 && !ignoreFraction) {
diff --git a/deps/icu-small/source/i18n/number_decimalquantity.h b/deps/icu-small/source/i18n/number_decimalquantity.h
index 06cc836c7796f2..4ec6c5a5b2bcf7 100644
--- a/deps/icu-small/source/i18n/number_decimalquantity.h
+++ b/deps/icu-small/source/i18n/number_decimalquantity.h
@@ -146,14 +146,17 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory {
*/
int32_t getMagnitude() const;
- /** @return Whether the value represented by this {@link DecimalQuantity} is zero. */
- bool isZero() const;
+ /**
+ * @return Whether the value represented by this {@link DecimalQuantity} is
+ * zero, infinity, or NaN.
+ */
+ bool isZeroish() const;
/** @return Whether the value represented by this {@link DecimalQuantity} is less than zero. */
bool isNegative() const;
- /** @return -1 if the value is negative; 1 if positive; or 0 if zero. */
- int8_t signum() const;
+ /** @return The appropriate value from the Signum enum. */
+ Signum signum() const;
/** @return Whether the value represented by this {@link DecimalQuantity} is infinite. */
bool isInfinite() const U_OVERRIDE;
diff --git a/deps/icu-small/source/i18n/number_decnum.h b/deps/icu-small/source/i18n/number_decnum.h
index a7793470b55695..0c7399dbddd43b 100644
--- a/deps/icu-small/source/i18n/number_decnum.h
+++ b/deps/icu-small/source/i18n/number_decnum.h
@@ -55,6 +55,8 @@ class U_I18N_API DecNum : public UMemory {
bool isZero() const;
+ void toString(ByteSink& output, UErrorCode& status) const;
+
inline const decNumber* getRawDecNumber() const {
return fData.getAlias();
}
diff --git a/deps/icu-small/source/i18n/number_fluent.cpp b/deps/icu-small/source/i18n/number_fluent.cpp
index 09e0905609eb30..2dbd2fa6cd5acf 100644
--- a/deps/icu-small/source/i18n/number_fluent.cpp
+++ b/deps/icu-small/source/i18n/number_fluent.cpp
@@ -696,8 +696,8 @@ void LocalizedNumberFormatter::formatImpl(impl::UFormattedNumberData* results, U
void LocalizedNumberFormatter::getAffixImpl(bool isPrefix, bool isNegative, UnicodeString& result,
UErrorCode& status) const {
- NumberStringBuilder string;
- auto signum = static_cast(isNegative ? -1 : 1);
+ FormattedStringBuilder string;
+ auto signum = static_cast(isNegative ? SIGNUM_NEG : SIGNUM_POS);
// Always return affixes for plural form OTHER.
static const StandardPlural::Form plural = StandardPlural::OTHER;
int32_t prefixLength;
diff --git a/deps/icu-small/source/i18n/number_formatimpl.cpp b/deps/icu-small/source/i18n/number_formatimpl.cpp
index 08b833beb7ad2e..2e2c4a9620c77c 100644
--- a/deps/icu-small/source/i18n/number_formatimpl.cpp
+++ b/deps/icu-small/source/i18n/number_formatimpl.cpp
@@ -72,7 +72,7 @@ NumberFormatterImpl::NumberFormatterImpl(const MacroProps& macros, UErrorCode& s
}
int32_t NumberFormatterImpl::formatStatic(const MacroProps& macros, DecimalQuantity& inValue,
- NumberStringBuilder& outString, UErrorCode& status) {
+ FormattedStringBuilder& outString, UErrorCode& status) {
NumberFormatterImpl impl(macros, false, status);
MicroProps& micros = impl.preProcessUnsafe(inValue, status);
if (U_FAILURE(status)) { return 0; }
@@ -81,9 +81,9 @@ int32_t NumberFormatterImpl::formatStatic(const MacroProps& macros, DecimalQuant
return length;
}
-int32_t NumberFormatterImpl::getPrefixSuffixStatic(const MacroProps& macros, int8_t signum,
+int32_t NumberFormatterImpl::getPrefixSuffixStatic(const MacroProps& macros, Signum signum,
StandardPlural::Form plural,
- NumberStringBuilder& outString, UErrorCode& status) {
+ FormattedStringBuilder& outString, UErrorCode& status) {
NumberFormatterImpl impl(macros, false, status);
return impl.getPrefixSuffixUnsafe(signum, plural, outString, status);
}
@@ -93,7 +93,7 @@ int32_t NumberFormatterImpl::getPrefixSuffixStatic(const MacroProps& macros, int
// The "unsafe" method simply re-uses fMicros, eliminating the extra copy operation.
// See MicroProps::processQuantity() for details.
-int32_t NumberFormatterImpl::format(DecimalQuantity& inValue, NumberStringBuilder& outString,
+int32_t NumberFormatterImpl::format(DecimalQuantity& inValue, FormattedStringBuilder& outString,
UErrorCode& status) const {
MicroProps micros;
preProcess(inValue, micros, status);
@@ -129,8 +129,8 @@ MicroProps& NumberFormatterImpl::preProcessUnsafe(DecimalQuantity& inValue, UErr
return fMicros;
}
-int32_t NumberFormatterImpl::getPrefixSuffix(int8_t signum, StandardPlural::Form plural,
- NumberStringBuilder& outString, UErrorCode& status) const {
+int32_t NumberFormatterImpl::getPrefixSuffix(Signum signum, StandardPlural::Form plural,
+ FormattedStringBuilder& outString, UErrorCode& status) const {
if (U_FAILURE(status)) { return 0; }
// #13453: DecimalFormat wants the affixes from the pattern only (modMiddle, aka pattern modifier).
// Safe path: use fImmutablePatternModifier.
@@ -140,8 +140,8 @@ int32_t NumberFormatterImpl::getPrefixSuffix(int8_t signum, StandardPlural::Form
return modifier->getPrefixLength();
}
-int32_t NumberFormatterImpl::getPrefixSuffixUnsafe(int8_t signum, StandardPlural::Form plural,
- NumberStringBuilder& outString, UErrorCode& status) {
+int32_t NumberFormatterImpl::getPrefixSuffixUnsafe(Signum signum, StandardPlural::Form plural,
+ FormattedStringBuilder& outString, UErrorCode& status) {
if (U_FAILURE(status)) { return 0; }
// #13453: DecimalFormat wants the affixes from the pattern only (modMiddle, aka pattern modifier).
// Unsafe path: use fPatternModifier.
@@ -215,7 +215,12 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
if (macros.symbols.isDecimalFormatSymbols()) {
fMicros.symbols = macros.symbols.getDecimalFormatSymbols();
} else {
- fMicros.symbols = new DecimalFormatSymbols(macros.locale, *ns, status);
+ auto newSymbols = new DecimalFormatSymbols(macros.locale, *ns, status);
+ if (newSymbols == nullptr) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return nullptr;
+ }
+ fMicros.symbols = newSymbols;
// Give ownership to the NumberFormatterImpl.
fSymbols.adoptInstead(fMicros.symbols);
}
@@ -229,7 +234,11 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
if (info.exists) {
pattern = info.pattern;
// It's clunky to clone an object here, but this code is not frequently executed.
- auto* symbols = new DecimalFormatSymbols(*fMicros.symbols);
+ auto symbols = new DecimalFormatSymbols(*fMicros.symbols);
+ if (symbols == nullptr) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return nullptr;
+ }
fMicros.symbols = symbols;
fSymbols.adoptInstead(symbols);
symbols->setSymbol(
@@ -260,6 +269,10 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
pattern = utils::getPatternForStyle(macros.locale, nsName, patternStyle, status);
}
auto patternInfo = new ParsedPatternInfo();
+ if (patternInfo == nullptr) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return nullptr;
+ }
fPatternInfo.adoptInstead(patternInfo);
PatternParser::parseToPatternInfo(UnicodeString(pattern), *patternInfo, status);
@@ -337,7 +350,12 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
// Inner modifier (scientific notation)
if (macros.notation.fType == Notation::NTN_SCIENTIFIC) {
- fScientificHandler.adoptInstead(new ScientificHandler(¯os.notation, fMicros.symbols, chain));
+ auto newScientificHandler = new ScientificHandler(¯os.notation, fMicros.symbols, chain);
+ if (newScientificHandler == nullptr) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return nullptr;
+ }
+ fScientificHandler.adoptInstead(newScientificHandler);
chain = fScientificHandler.getAlias();
} else {
// No inner modifier required
@@ -346,6 +364,10 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
// Middle modifier (patterns, positive/negative, currency symbols, percent)
auto patternModifier = new MutablePatternModifier(false);
+ if (patternModifier == nullptr) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return nullptr;
+ }
fPatternModifier.adoptInstead(patternModifier);
patternModifier->setPatternInfo(
macros.affixProvider != nullptr ? macros.affixProvider
@@ -401,16 +423,20 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
if (macros.notation.fType == Notation::NTN_COMPACT) {
CompactType compactType = (isCurrency && unitWidth != UNUM_UNIT_WIDTH_FULL_NAME)
? CompactType::TYPE_CURRENCY : CompactType::TYPE_DECIMAL;
- fCompactHandler.adoptInstead(
- new CompactHandler(
- macros.notation.fUnion.compactStyle,
- macros.locale,
- nsName,
- compactType,
- resolvePluralRules(macros.rules, macros.locale, status),
- safe ? patternModifier : nullptr,
- chain,
- status));
+ auto newCompactHandler = new CompactHandler(
+ macros.notation.fUnion.compactStyle,
+ macros.locale,
+ nsName,
+ compactType,
+ resolvePluralRules(macros.rules, macros.locale, status),
+ safe ? patternModifier : nullptr,
+ chain,
+ status);
+ if (newCompactHandler == nullptr) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return nullptr;
+ }
+ fCompactHandler.adoptInstead(newCompactHandler);
chain = fCompactHandler.getAlias();
}
@@ -430,7 +456,7 @@ NumberFormatterImpl::resolvePluralRules(const PluralRules* rulesPtr, const Local
return fRules.getAlias();
}
-int32_t NumberFormatterImpl::writeAffixes(const MicroProps& micros, NumberStringBuilder& string,
+int32_t NumberFormatterImpl::writeAffixes(const MicroProps& micros, FormattedStringBuilder& string,
int32_t start, int32_t end, UErrorCode& status) {
// Always apply the inner modifier (which is "strong").
int32_t length = micros.modInner->apply(string, start, end, status);
@@ -445,7 +471,7 @@ int32_t NumberFormatterImpl::writeAffixes(const MicroProps& micros, NumberString
}
int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuantity& quantity,
- NumberStringBuilder& string, int32_t index,
+ FormattedStringBuilder& string, int32_t index,
UErrorCode& status) {
int32_t length = 0;
if (quantity.isInfinite()) {
@@ -487,7 +513,7 @@ int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuanti
}
int32_t NumberFormatterImpl::writeIntegerDigits(const MicroProps& micros, DecimalQuantity& quantity,
- NumberStringBuilder& string, int32_t index,
+ FormattedStringBuilder& string, int32_t index,
UErrorCode& status) {
int length = 0;
int integerCount = quantity.getUpperDisplayMagnitude() + 1;
@@ -513,7 +539,7 @@ int32_t NumberFormatterImpl::writeIntegerDigits(const MicroProps& micros, Decima
}
int32_t NumberFormatterImpl::writeFractionDigits(const MicroProps& micros, DecimalQuantity& quantity,
- NumberStringBuilder& string, int32_t index,
+ FormattedStringBuilder& string, int32_t index,
UErrorCode& status) {
int length = 0;
int fractionCount = -quantity.getLowerDisplayMagnitude();
diff --git a/deps/icu-small/source/i18n/number_formatimpl.h b/deps/icu-small/source/i18n/number_formatimpl.h
index fd8708c532e131..206c5f58c576a1 100644
--- a/deps/icu-small/source/i18n/number_formatimpl.h
+++ b/deps/icu-small/source/i18n/number_formatimpl.h
@@ -8,7 +8,7 @@
#define __NUMBER_FORMATIMPL_H__
#include "number_types.h"
-#include "number_stringbuilder.h"
+#include "formatted_string_builder.h"
#include "number_patternstring.h"
#include "number_utils.h"
#include "number_patternmodifier.h"
@@ -35,7 +35,7 @@ class NumberFormatterImpl : public UMemory {
* Builds and evaluates an "unsafe" MicroPropsGenerator, which is cheaper but can be used only once.
*/
static int32_t
- formatStatic(const MacroProps ¯os, DecimalQuantity &inValue, NumberStringBuilder &outString,
+ formatStatic(const MacroProps ¯os, DecimalQuantity &inValue, FormattedStringBuilder &outString,
UErrorCode &status);
/**
@@ -44,14 +44,14 @@ class NumberFormatterImpl : public UMemory {
* @return The index into the output at which the prefix ends and the suffix starts; in other words,
* the prefix length.
*/
- static int32_t getPrefixSuffixStatic(const MacroProps& macros, int8_t signum,
- StandardPlural::Form plural, NumberStringBuilder& outString,
+ static int32_t getPrefixSuffixStatic(const MacroProps& macros, Signum signum,
+ StandardPlural::Form plural, FormattedStringBuilder& outString,
UErrorCode& status);
/**
* Evaluates the "safe" MicroPropsGenerator created by "fromMacros".
*/
- int32_t format(DecimalQuantity& inValue, NumberStringBuilder& outString, UErrorCode& status) const;
+ int32_t format(DecimalQuantity& inValue, FormattedStringBuilder& outString, UErrorCode& status) const;
/**
* Like format(), but saves the result into an output MicroProps without additional processing.
@@ -61,7 +61,7 @@ class NumberFormatterImpl : public UMemory {
/**
* Like getPrefixSuffixStatic() but uses the safe compiled object.
*/
- int32_t getPrefixSuffix(int8_t signum, StandardPlural::Form plural, NumberStringBuilder& outString,
+ int32_t getPrefixSuffix(Signum signum, StandardPlural::Form plural, FormattedStringBuilder& outString,
UErrorCode& status) const;
const MicroProps& getRawMicroProps() const {
@@ -73,12 +73,12 @@ class NumberFormatterImpl : public UMemory {
* This method formats only the main number, not affixes.
*/
static int32_t writeNumber(const MicroProps& micros, DecimalQuantity& quantity,
- NumberStringBuilder& string, int32_t index, UErrorCode& status);
+ FormattedStringBuilder& string, int32_t index, UErrorCode& status);
/**
* Adds the affixes. Intended to be called immediately after formatNumber.
*/
- static int32_t writeAffixes(const MicroProps& micros, NumberStringBuilder& string, int32_t start,
+ static int32_t writeAffixes(const MicroProps& micros, FormattedStringBuilder& string, int32_t start,
int32_t end, UErrorCode& status);
private:
@@ -109,8 +109,8 @@ class NumberFormatterImpl : public UMemory {
MicroProps& preProcessUnsafe(DecimalQuantity &inValue, UErrorCode &status);
- int32_t getPrefixSuffixUnsafe(int8_t signum, StandardPlural::Form plural,
- NumberStringBuilder& outString, UErrorCode& status);
+ int32_t getPrefixSuffixUnsafe(Signum signum, StandardPlural::Form plural,
+ FormattedStringBuilder& outString, UErrorCode& status);
/**
* If rulesPtr is non-null, return it. Otherwise, return a PluralRules owned by this object for the
@@ -136,11 +136,11 @@ class NumberFormatterImpl : public UMemory {
macrosToMicroGenerator(const MacroProps ¯os, bool safe, UErrorCode &status);
static int32_t
- writeIntegerDigits(const MicroProps µs, DecimalQuantity &quantity, NumberStringBuilder &string,
+ writeIntegerDigits(const MicroProps µs, DecimalQuantity &quantity, FormattedStringBuilder &string,
int32_t index, UErrorCode &status);
static int32_t
- writeFractionDigits(const MicroProps µs, DecimalQuantity &quantity, NumberStringBuilder &string,
+ writeFractionDigits(const MicroProps µs, DecimalQuantity &quantity, FormattedStringBuilder &string,
int32_t index, UErrorCode &status);
};
diff --git a/deps/icu-small/source/i18n/number_longnames.cpp b/deps/icu-small/source/i18n/number_longnames.cpp
index 0cd160042a46d3..817aa0e0d9c39d 100644
--- a/deps/icu-small/source/i18n/number_longnames.cpp
+++ b/deps/icu-small/source/i18n/number_longnames.cpp
@@ -148,12 +148,11 @@ void getCurrencyLongNameData(const Locale &locale, const CurrencyUnit ¤cy,
if (pattern.isBogus()) {
continue;
}
- UBool isChoiceFormat = FALSE;
int32_t longNameLen = 0;
const char16_t *longName = ucurr_getPluralName(
currency.getISOCurrency(),
locale.getName(),
- &isChoiceFormat,
+ nullptr /* isChoiceFormat */,
StandardPlural::getKeyword(static_cast(i)),
&longNameLen,
&status);
@@ -265,6 +264,26 @@ UnicodeString LongNameHandler::getUnitDisplayName(
return simpleFormats[DNAM_INDEX];
}
+UnicodeString LongNameHandler::getUnitPattern(
+ const Locale& loc,
+ const MeasureUnit& unit,
+ UNumberUnitWidth width,
+ StandardPlural::Form pluralForm,
+ UErrorCode& status) {
+ if (U_FAILURE(status)) {
+ return ICU_Utility::makeBogusString();
+ }
+ UnicodeString simpleFormats[ARRAY_LENGTH];
+ getMeasureData(loc, unit, width, simpleFormats, status);
+ // The above already handles fallback from other widths to short
+ if (U_FAILURE(status)) {
+ return ICU_Utility::makeBogusString();
+ }
+ // Now handle fallback from other plural forms to OTHER
+ return (!(simpleFormats[pluralForm]).isBogus())? simpleFormats[pluralForm]:
+ simpleFormats[StandardPlural::Form::OTHER];
+}
+
LongNameHandler* LongNameHandler::forCurrencyLongNames(const Locale &loc, const CurrencyUnit ¤cy,
const PluralRules *rules,
const MicroPropsGenerator *parent,
@@ -289,7 +308,7 @@ void LongNameHandler::simpleFormatsToModifiers(const UnicodeString *simpleFormat
if (U_FAILURE(status)) { return; }
SimpleFormatter compiledFormatter(simpleFormat, 0, 1, status);
if (U_FAILURE(status)) { return; }
- fModifiers[i] = SimpleModifier(compiledFormatter, field, false, {this, 0, plural});
+ fModifiers[i] = SimpleModifier(compiledFormatter, field, false, {this, SIGNUM_ZERO, plural});
}
}
@@ -306,7 +325,7 @@ void LongNameHandler::multiSimpleFormatsToModifiers(const UnicodeString *leadFor
if (U_FAILURE(status)) { return; }
SimpleFormatter compoundCompiled(compoundFormat, 0, 1, status);
if (U_FAILURE(status)) { return; }
- fModifiers[i] = SimpleModifier(compoundCompiled, field, false, {this, 0, plural});
+ fModifiers[i] = SimpleModifier(compoundCompiled, field, false, {this, SIGNUM_ZERO, plural});
}
}
@@ -317,7 +336,7 @@ void LongNameHandler::processQuantity(DecimalQuantity &quantity, MicroProps &mic
micros.modOuter = &fModifiers[pluralForm];
}
-const Modifier* LongNameHandler::getModifier(int8_t /*signum*/, StandardPlural::Form plural) const {
+const Modifier* LongNameHandler::getModifier(Signum /*signum*/, StandardPlural::Form plural) const {
return &fModifiers[plural];
}
diff --git a/deps/icu-small/source/i18n/number_longnames.h b/deps/icu-small/source/i18n/number_longnames.h
index 76fb82d744b6d4..a19425aa268af6 100644
--- a/deps/icu-small/source/i18n/number_longnames.h
+++ b/deps/icu-small/source/i18n/number_longnames.h
@@ -22,6 +22,13 @@ class LongNameHandler : public MicroPropsGenerator, public ModifierStore, public
UNumberUnitWidth width,
UErrorCode& status);
+ static UnicodeString getUnitPattern(
+ const Locale& loc,
+ const MeasureUnit& unit,
+ UNumberUnitWidth width,
+ StandardPlural::Form pluralForm,
+ UErrorCode& status);
+
static LongNameHandler*
forCurrencyLongNames(const Locale &loc, const CurrencyUnit ¤cy, const PluralRules *rules,
const MicroPropsGenerator *parent, UErrorCode &status);
@@ -34,7 +41,7 @@ class LongNameHandler : public MicroPropsGenerator, public ModifierStore, public
void
processQuantity(DecimalQuantity &quantity, MicroProps µs, UErrorCode &status) const U_OVERRIDE;
- const Modifier* getModifier(int8_t signum, StandardPlural::Form plural) const U_OVERRIDE;
+ const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const U_OVERRIDE;
private:
SimpleModifier fModifiers[StandardPlural::Form::COUNT];
diff --git a/deps/icu-small/source/i18n/number_mapper.h b/deps/icu-small/source/i18n/number_mapper.h
index d28e9cec393a05..de7d9c3865c8df 100644
--- a/deps/icu-small/source/i18n/number_mapper.h
+++ b/deps/icu-small/source/i18n/number_mapper.h
@@ -126,8 +126,14 @@ struct DecimalFormatWarehouse {
* TODO: Make some of these fields by value instead of by LocalPointer?
*/
struct DecimalFormatFields : public UMemory {
+
+ DecimalFormatFields() {}
+
+ DecimalFormatFields(const DecimalFormatProperties& propsToCopy)
+ : properties(propsToCopy) {}
+
/** The property bag corresponding to user-specified settings and settings from the pattern string. */
- LocalPointer properties;
+ DecimalFormatProperties properties;
/** The symbols for the current locale. */
LocalPointer symbols;
@@ -136,7 +142,7 @@ struct DecimalFormatFields : public UMemory {
* The pre-computed formatter object. Setters cause this to be re-computed atomically. The {@link
* #format} method uses the formatter directly without needing to synchronize.
*/
- LocalPointer formatter;
+ LocalizedNumberFormatter formatter;
/** The lazy-computed parser for .parse() */
std::atomic<::icu::numparse::impl::NumberParserImpl*> atomicParser = {};
@@ -148,7 +154,7 @@ struct DecimalFormatFields : public UMemory {
DecimalFormatWarehouse warehouse;
/** The effective properties as exported from the formatter object. Used by some getters. */
- LocalPointer exportedProperties;
+ DecimalFormatProperties exportedProperties;
// Data for fastpath
bool canUseFastFormat = false;
diff --git a/deps/icu-small/source/i18n/number_modifiers.cpp b/deps/icu-small/source/i18n/number_modifiers.cpp
index 1fcbe7b9b79301..3a44f8f6f15328 100644
--- a/deps/icu-small/source/i18n/number_modifiers.cpp
+++ b/deps/icu-small/source/i18n/number_modifiers.cpp
@@ -57,7 +57,7 @@ Modifier::Parameters::Parameters()
: obj(nullptr) {}
Modifier::Parameters::Parameters(
- const ModifierStore* _obj, int8_t _signum, StandardPlural::Form _plural)
+ const ModifierStore* _obj, Signum _signum, StandardPlural::Form _plural)
: obj(_obj), signum(_signum), plural(_plural) {}
ModifierStore::~ModifierStore() = default;
@@ -69,7 +69,7 @@ AdoptingModifierStore::~AdoptingModifierStore() {
}
-int32_t ConstantAffixModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex,
+int32_t ConstantAffixModifier::apply(FormattedStringBuilder &output, int leftIndex, int rightIndex,
UErrorCode &status) const {
// Insert the suffix first since inserting the prefix will change the rightIndex
int length = output.insert(rightIndex, fSuffix, fField, status);
@@ -154,7 +154,7 @@ SimpleModifier::SimpleModifier()
: fField(UNUM_FIELD_COUNT), fStrong(false), fPrefixLength(0), fSuffixLength(0) {
}
-int32_t SimpleModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex,
+int32_t SimpleModifier::apply(FormattedStringBuilder &output, int leftIndex, int rightIndex,
UErrorCode &status) const {
return formatAsPrefixSuffix(output, leftIndex, rightIndex, status);
}
@@ -203,7 +203,7 @@ bool SimpleModifier::semanticallyEquivalent(const Modifier& other) const {
int32_t
-SimpleModifier::formatAsPrefixSuffix(NumberStringBuilder &result, int32_t startIndex, int32_t endIndex,
+SimpleModifier::formatAsPrefixSuffix(FormattedStringBuilder &result, int32_t startIndex, int32_t endIndex,
UErrorCode &status) const {
if (fSuffixOffset == -1 && fPrefixLength + fSuffixLength > 0) {
// There is no argument for the inner number; overwrite the entire segment with our string.
@@ -227,7 +227,7 @@ SimpleModifier::formatAsPrefixSuffix(NumberStringBuilder &result, int32_t startI
int32_t
-SimpleModifier::formatTwoArgPattern(const SimpleFormatter& compiled, NumberStringBuilder& result,
+SimpleModifier::formatTwoArgPattern(const SimpleFormatter& compiled, FormattedStringBuilder& result,
int32_t index, int32_t* outPrefixLength, int32_t* outSuffixLength,
Field field, UErrorCode& status) {
const UnicodeString& compiledPattern = compiled.compiledPattern;
@@ -284,7 +284,7 @@ SimpleModifier::formatTwoArgPattern(const SimpleFormatter& compiled, NumberStrin
}
-int32_t ConstantMultiFieldModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex,
+int32_t ConstantMultiFieldModifier::apply(FormattedStringBuilder &output, int leftIndex, int rightIndex,
UErrorCode &status) const {
int32_t length = output.insert(leftIndex, fPrefix, status);
if (fOverwrite) {
@@ -333,8 +333,8 @@ bool ConstantMultiFieldModifier::semanticallyEquivalent(const Modifier& other) c
}
-CurrencySpacingEnabledModifier::CurrencySpacingEnabledModifier(const NumberStringBuilder &prefix,
- const NumberStringBuilder &suffix,
+CurrencySpacingEnabledModifier::CurrencySpacingEnabledModifier(const FormattedStringBuilder &prefix,
+ const FormattedStringBuilder &suffix,
bool overwrite,
bool strong,
const DecimalFormatSymbols &symbols,
@@ -374,7 +374,7 @@ CurrencySpacingEnabledModifier::CurrencySpacingEnabledModifier(const NumberStrin
}
}
-int32_t CurrencySpacingEnabledModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex,
+int32_t CurrencySpacingEnabledModifier::apply(FormattedStringBuilder &output, int leftIndex, int rightIndex,
UErrorCode &status) const {
// Currency spacing logic
int length = 0;
@@ -395,7 +395,7 @@ int32_t CurrencySpacingEnabledModifier::apply(NumberStringBuilder &output, int l
}
int32_t
-CurrencySpacingEnabledModifier::applyCurrencySpacing(NumberStringBuilder &output, int32_t prefixStart,
+CurrencySpacingEnabledModifier::applyCurrencySpacing(FormattedStringBuilder &output, int32_t prefixStart,
int32_t prefixLen, int32_t suffixStart,
int32_t suffixLen,
const DecimalFormatSymbols &symbols,
@@ -414,7 +414,7 @@ CurrencySpacingEnabledModifier::applyCurrencySpacing(NumberStringBuilder &output
}
int32_t
-CurrencySpacingEnabledModifier::applyCurrencySpacingAffix(NumberStringBuilder &output, int32_t index,
+CurrencySpacingEnabledModifier::applyCurrencySpacingAffix(FormattedStringBuilder &output, int32_t index,
EAffix affix,
const DecimalFormatSymbols &symbols,
UErrorCode &status) {
diff --git a/deps/icu-small/source/i18n/number_modifiers.h b/deps/icu-small/source/i18n/number_modifiers.h
index 495128bb149dcf..c84c6aa273ed76 100644
--- a/deps/icu-small/source/i18n/number_modifiers.h
+++ b/deps/icu-small/source/i18n/number_modifiers.h
@@ -12,7 +12,7 @@
#include "unicode/uniset.h"
#include "unicode/simpleformatter.h"
#include "standardplural.h"
-#include "number_stringbuilder.h"
+#include "formatted_string_builder.h"
#include "number_types.h"
U_NAMESPACE_BEGIN namespace number {
@@ -28,7 +28,7 @@ class U_I18N_API ConstantAffixModifier : public Modifier, public UObject {
bool strong)
: fPrefix(prefix), fSuffix(suffix), fField(field), fStrong(strong) {}
- int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
+ int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
UErrorCode &status) const U_OVERRIDE;
int32_t getPrefixLength() const U_OVERRIDE;
@@ -64,7 +64,7 @@ class U_I18N_API SimpleModifier : public Modifier, public UMemory {
// Default constructor for LongNameHandler.h
SimpleModifier();
- int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
+ int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
UErrorCode &status) const U_OVERRIDE;
int32_t getPrefixLength() const U_OVERRIDE;
@@ -81,7 +81,7 @@ class U_I18N_API SimpleModifier : public Modifier, public UMemory {
/**
* TODO: This belongs in SimpleFormatterImpl. The only reason I haven't moved it there yet is because
- * NumberStringBuilder is an internal class and SimpleFormatterImpl feels like it should not depend on it.
+ * FormattedStringBuilder is an internal class and SimpleFormatterImpl feels like it should not depend on it.
*
*
* Formats a value that is already stored inside the StringBuilder result
between the indices
@@ -100,22 +100,22 @@ class U_I18N_API SimpleModifier : public Modifier, public UMemory {
* @return The number of characters (UTF-16 code points) that were added to the StringBuilder.
*/
int32_t
- formatAsPrefixSuffix(NumberStringBuilder& result, int32_t startIndex, int32_t endIndex,
+ formatAsPrefixSuffix(FormattedStringBuilder& result, int32_t startIndex, int32_t endIndex,
UErrorCode& status) const;
/**
* TODO: Like above, this belongs with the rest of the SimpleFormatterImpl code.
- * I put it here so that the SimpleFormatter uses in NumberStringBuilder are near each other.
+ * I put it here so that the SimpleFormatter uses in FormattedStringBuilder are near each other.
*
*
- * Applies the compiled two-argument pattern to the NumberStringBuilder.
+ * Applies the compiled two-argument pattern to the FormattedStringBuilder.
*
*
* This method is optimized for the case where the prefix and suffix are often empty, such as
* in the range pattern like "{0}-{1}".
*/
static int32_t
- formatTwoArgPattern(const SimpleFormatter& compiled, NumberStringBuilder& result,
+ formatTwoArgPattern(const SimpleFormatter& compiled, FormattedStringBuilder& result,
int32_t index, int32_t* outPrefixLength, int32_t* outSuffixLength,
Field field, UErrorCode& status);
@@ -131,13 +131,13 @@ class U_I18N_API SimpleModifier : public Modifier, public UMemory {
/**
* An implementation of {@link Modifier} that allows for multiple types of fields in the same modifier. Constructed
- * based on the contents of two {@link NumberStringBuilder} instances (one for the prefix, one for the suffix).
+ * based on the contents of two {@link FormattedStringBuilder} instances (one for the prefix, one for the suffix).
*/
class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory {
public:
ConstantMultiFieldModifier(
- const NumberStringBuilder &prefix,
- const NumberStringBuilder &suffix,
+ const FormattedStringBuilder &prefix,
+ const FormattedStringBuilder &suffix,
bool overwrite,
bool strong,
const Modifier::Parameters parameters)
@@ -148,8 +148,8 @@ class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory {
fParameters(parameters) {}
ConstantMultiFieldModifier(
- const NumberStringBuilder &prefix,
- const NumberStringBuilder &suffix,
+ const FormattedStringBuilder &prefix,
+ const FormattedStringBuilder &suffix,
bool overwrite,
bool strong)
: fPrefix(prefix),
@@ -157,7 +157,7 @@ class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory {
fOverwrite(overwrite),
fStrong(strong) {}
- int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
+ int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
UErrorCode &status) const U_OVERRIDE;
int32_t getPrefixLength() const U_OVERRIDE;
@@ -173,10 +173,10 @@ class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory {
bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE;
protected:
- // NOTE: In Java, these are stored as array pointers. In C++, the NumberStringBuilder is stored by
+ // NOTE: In Java, these are stored as array pointers. In C++, the FormattedStringBuilder is stored by
// value and is treated internally as immutable.
- NumberStringBuilder fPrefix;
- NumberStringBuilder fSuffix;
+ FormattedStringBuilder fPrefix;
+ FormattedStringBuilder fSuffix;
bool fOverwrite;
bool fStrong;
Modifier::Parameters fParameters;
@@ -187,19 +187,19 @@ class U_I18N_API CurrencySpacingEnabledModifier : public ConstantMultiFieldModif
public:
/** Safe code path */
CurrencySpacingEnabledModifier(
- const NumberStringBuilder &prefix,
- const NumberStringBuilder &suffix,
+ const FormattedStringBuilder &prefix,
+ const FormattedStringBuilder &suffix,
bool overwrite,
bool strong,
const DecimalFormatSymbols &symbols,
UErrorCode &status);
- int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
+ int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
UErrorCode &status) const U_OVERRIDE;
/** Unsafe code path */
static int32_t
- applyCurrencySpacing(NumberStringBuilder &output, int32_t prefixStart, int32_t prefixLen,
+ applyCurrencySpacing(FormattedStringBuilder &output, int32_t prefixStart, int32_t prefixLen,
int32_t suffixStart, int32_t suffixLen, const DecimalFormatSymbols &symbols,
UErrorCode &status);
@@ -218,7 +218,7 @@ class U_I18N_API CurrencySpacingEnabledModifier : public ConstantMultiFieldModif
};
/** Unsafe code path */
- static int32_t applyCurrencySpacingAffix(NumberStringBuilder &output, int32_t index, EAffix affix,
+ static int32_t applyCurrencySpacingAffix(FormattedStringBuilder &output, int32_t index, EAffix affix,
const DecimalFormatSymbols &symbols, UErrorCode &status);
static UnicodeSet
@@ -234,7 +234,7 @@ class U_I18N_API EmptyModifier : public Modifier, public UMemory {
public:
explicit EmptyModifier(bool isStrong) : fStrong(isStrong) {}
- int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
+ int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
UErrorCode &status) const U_OVERRIDE {
(void)output;
(void)leftIndex;
@@ -289,7 +289,7 @@ class U_I18N_API AdoptingModifierStore : public ModifierStore, public UMemory {
/**
* Sets the Modifier with the specified signum and plural form.
*/
- void adoptModifier(int8_t signum, StandardPlural::Form plural, const Modifier *mod) {
+ void adoptModifier(Signum signum, StandardPlural::Form plural, const Modifier *mod) {
U_ASSERT(mods[getModIndex(signum, plural)] == nullptr);
mods[getModIndex(signum, plural)] = mod;
}
@@ -298,13 +298,13 @@ class U_I18N_API AdoptingModifierStore : public ModifierStore, public UMemory {
* Sets the Modifier with the specified signum.
* The modifier will apply to all plural forms.
*/
- void adoptModifierWithoutPlural(int8_t signum, const Modifier *mod) {
+ void adoptModifierWithoutPlural(Signum signum, const Modifier *mod) {
U_ASSERT(mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)] == nullptr);
mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)] = mod;
}
/** Returns a reference to the modifier; no ownership change. */
- const Modifier *getModifier(int8_t signum, StandardPlural::Form plural) const U_OVERRIDE {
+ const Modifier *getModifier(Signum signum, StandardPlural::Form plural) const U_OVERRIDE {
const Modifier* modifier = mods[getModIndex(signum, plural)];
if (modifier == nullptr && plural != DEFAULT_STANDARD_PLURAL) {
modifier = mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)];
@@ -313,7 +313,7 @@ class U_I18N_API AdoptingModifierStore : public ModifierStore, public UMemory {
}
/** Returns a reference to the modifier; no ownership change. */
- const Modifier *getModifierWithoutPlural(int8_t signum) const {
+ const Modifier *getModifierWithoutPlural(Signum signum) const {
return mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)];
}
@@ -321,7 +321,7 @@ class U_I18N_API AdoptingModifierStore : public ModifierStore, public UMemory {
// NOTE: mods is zero-initialized (to nullptr)
const Modifier *mods[3 * StandardPlural::COUNT] = {};
- inline static int32_t getModIndex(int8_t signum, StandardPlural::Form plural) {
+ inline static int32_t getModIndex(Signum signum, StandardPlural::Form plural) {
U_ASSERT(signum >= -1 && signum <= 1);
U_ASSERT(plural >= 0 && plural < StandardPlural::COUNT);
return static_cast(plural) * 3 + (signum + 1);
diff --git a/deps/icu-small/source/i18n/number_output.cpp b/deps/icu-small/source/i18n/number_output.cpp
index 6f4e2482044f14..e2f069139a4b47 100644
--- a/deps/icu-small/source/i18n/number_output.cpp
+++ b/deps/icu-small/source/i18n/number_output.cpp
@@ -9,6 +9,7 @@
#include "number_utypes.h"
#include "util.h"
#include "number_decimalquantity.h"
+#include "number_decnum.h"
U_NAMESPACE_BEGIN
namespace number {
@@ -20,8 +21,7 @@ UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(FormattedNumber)
UBool FormattedNumber::nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const {
UPRV_FORMATTED_VALUE_METHOD_GUARD(FALSE)
- // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
- return fData->getStringRef().nextFieldPosition(fieldPosition, status) ? TRUE : FALSE;
+ return fData->nextFieldPosition(fieldPosition, status);
}
void FormattedNumber::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const {
@@ -29,10 +29,17 @@ void FormattedNumber::getAllFieldPositions(FieldPositionIterator& iterator, UErr
getAllFieldPositionsImpl(fpih, status);
}
+void FormattedNumber::toDecimalNumber(ByteSink& sink, UErrorCode& status) const {
+ UPRV_FORMATTED_VALUE_METHOD_GUARD(UPRV_NOARG)
+ impl::DecNum decnum;
+ fData->quantity.toDecNum(decnum, status);
+ decnum.toString(sink, status);
+}
+
void FormattedNumber::getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih,
UErrorCode& status) const {
UPRV_FORMATTED_VALUE_METHOD_GUARD(UPRV_NOARG)
- fData->getStringRef().getAllFieldPositions(fpih, status);
+ fData->getAllFieldPositions(fpih, status);
}
void FormattedNumber::getDecimalQuantity(impl::DecimalQuantity& output, UErrorCode& status) const {
diff --git a/deps/icu-small/source/i18n/number_padding.cpp b/deps/icu-small/source/i18n/number_padding.cpp
index 31684d7208b606..c68a9875b2055f 100644
--- a/deps/icu-small/source/i18n/number_padding.cpp
+++ b/deps/icu-small/source/i18n/number_padding.cpp
@@ -7,7 +7,7 @@
#include "unicode/numberformatter.h"
#include "number_types.h"
-#include "number_stringbuilder.h"
+#include "formatted_string_builder.h"
#include "number_decimfmtprops.h"
using namespace icu;
@@ -17,7 +17,7 @@ using namespace icu::number::impl;
namespace {
int32_t
-addPaddingHelper(UChar32 paddingCp, int32_t requiredPadding, NumberStringBuilder &string, int32_t index,
+addPaddingHelper(UChar32 paddingCp, int32_t requiredPadding, FormattedStringBuilder &string, int32_t index,
UErrorCode &status) {
for (int32_t i = 0; i < requiredPadding; i++) {
// TODO: If appending to the end, this will cause actual insertion operations. Improve.
@@ -60,7 +60,7 @@ Padder Padder::forProperties(const DecimalFormatProperties& properties) {
}
int32_t Padder::padAndApply(const Modifier &mod1, const Modifier &mod2,
- NumberStringBuilder &string, int32_t leftIndex, int32_t rightIndex,
+ FormattedStringBuilder &string, int32_t leftIndex, int32_t rightIndex,
UErrorCode &status) const {
int32_t modLength = mod1.getCodePointCount() + mod2.getCodePointCount();
int32_t requiredPadding = fWidth - modLength - string.codePointCount();
diff --git a/deps/icu-small/source/i18n/number_patternmodifier.cpp b/deps/icu-small/source/i18n/number_patternmodifier.cpp
index 75de439f3ed2e1..724f5b9741cc52 100644
--- a/deps/icu-small/source/i18n/number_patternmodifier.cpp
+++ b/deps/icu-small/source/i18n/number_patternmodifier.cpp
@@ -43,7 +43,7 @@ void MutablePatternModifier::setSymbols(const DecimalFormatSymbols* symbols,
fRules = rules;
}
-void MutablePatternModifier::setNumberProperties(int8_t signum, StandardPlural::Form plural) {
+void MutablePatternModifier::setNumberProperties(Signum signum, StandardPlural::Form plural) {
fSignum = signum;
fPlural = plural;
}
@@ -79,12 +79,12 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* paren
if (needsPlurals()) {
// Slower path when we require the plural keyword.
for (StandardPlural::Form plural : STANDARD_PLURAL_VALUES) {
- setNumberProperties(1, plural);
- pm->adoptModifier(1, plural, createConstantModifier(status));
- setNumberProperties(0, plural);
- pm->adoptModifier(0, plural, createConstantModifier(status));
- setNumberProperties(-1, plural);
- pm->adoptModifier(-1, plural, createConstantModifier(status));
+ setNumberProperties(SIGNUM_POS, plural);
+ pm->adoptModifier(SIGNUM_POS, plural, createConstantModifier(status));
+ setNumberProperties(SIGNUM_ZERO, plural);
+ pm->adoptModifier(SIGNUM_ZERO, plural, createConstantModifier(status));
+ setNumberProperties(SIGNUM_NEG, plural);
+ pm->adoptModifier(SIGNUM_NEG, plural, createConstantModifier(status));
}
if (U_FAILURE(status)) {
delete pm;
@@ -93,12 +93,12 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* paren
return new ImmutablePatternModifier(pm, fRules, parent); // adopts pm
} else {
// Faster path when plural keyword is not needed.
- setNumberProperties(1, StandardPlural::Form::COUNT);
- pm->adoptModifierWithoutPlural(1, createConstantModifier(status));
- setNumberProperties(0, StandardPlural::Form::COUNT);
- pm->adoptModifierWithoutPlural(0, createConstantModifier(status));
- setNumberProperties(-1, StandardPlural::Form::COUNT);
- pm->adoptModifierWithoutPlural(-1, createConstantModifier(status));
+ setNumberProperties(SIGNUM_POS, StandardPlural::Form::COUNT);
+ pm->adoptModifierWithoutPlural(SIGNUM_POS, createConstantModifier(status));
+ setNumberProperties(SIGNUM_ZERO, StandardPlural::Form::COUNT);
+ pm->adoptModifierWithoutPlural(SIGNUM_ZERO, createConstantModifier(status));
+ setNumberProperties(SIGNUM_NEG, StandardPlural::Form::COUNT);
+ pm->adoptModifierWithoutPlural(SIGNUM_NEG, createConstantModifier(status));
if (U_FAILURE(status)) {
delete pm;
return nullptr;
@@ -108,8 +108,8 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* paren
}
ConstantMultiFieldModifier* MutablePatternModifier::createConstantModifier(UErrorCode& status) {
- NumberStringBuilder a;
- NumberStringBuilder b;
+ FormattedStringBuilder a;
+ FormattedStringBuilder b;
insertPrefix(a, 0, status);
insertSuffix(b, 0, status);
if (fPatternInfo->hasCurrencySign()) {
@@ -140,7 +140,7 @@ void ImmutablePatternModifier::applyToMicros(
}
}
-const Modifier* ImmutablePatternModifier::getModifier(int8_t signum, StandardPlural::Form plural) const {
+const Modifier* ImmutablePatternModifier::getModifier(Signum signum, StandardPlural::Form plural) const {
if (rules == nullptr) {
return pm->getModifierWithoutPlural(signum);
} else {
@@ -170,7 +170,7 @@ void MutablePatternModifier::processQuantity(DecimalQuantity& fq, MicroProps& mi
micros.modMiddle = this;
}
-int32_t MutablePatternModifier::apply(NumberStringBuilder& output, int32_t leftIndex, int32_t rightIndex,
+int32_t MutablePatternModifier::apply(FormattedStringBuilder& output, int32_t leftIndex, int32_t rightIndex,
UErrorCode& status) const {
// The unsafe code path performs self-mutation, so we need a const_cast.
// This method needs to be const because it overrides a const method in the parent class.
@@ -248,13 +248,13 @@ bool MutablePatternModifier::semanticallyEquivalent(const Modifier& other) const
UPRV_UNREACHABLE;
}
-int32_t MutablePatternModifier::insertPrefix(NumberStringBuilder& sb, int position, UErrorCode& status) {
+int32_t MutablePatternModifier::insertPrefix(FormattedStringBuilder& sb, int position, UErrorCode& status) {
prepareAffix(true);
int32_t length = AffixUtils::unescape(currentAffix, sb, position, *this, fField, status);
return length;
}
-int32_t MutablePatternModifier::insertSuffix(NumberStringBuilder& sb, int position, UErrorCode& status) {
+int32_t MutablePatternModifier::insertSuffix(FormattedStringBuilder& sb, int position, UErrorCode& status) {
prepareAffix(false);
int32_t length = AffixUtils::unescape(currentAffix, sb, position, *this, fField, status);
return length;
diff --git a/deps/icu-small/source/i18n/number_patternmodifier.h b/deps/icu-small/source/i18n/number_patternmodifier.h
index 27e293b64ce50f..b2c90e0af76354 100644
--- a/deps/icu-small/source/i18n/number_patternmodifier.h
+++ b/deps/icu-small/source/i18n/number_patternmodifier.h
@@ -48,7 +48,7 @@ class U_I18N_API ImmutablePatternModifier : public MicroPropsGenerator, public U
void applyToMicros(MicroProps& micros, const DecimalQuantity& quantity, UErrorCode& status) const;
- const Modifier* getModifier(int8_t signum, StandardPlural::Form plural) const;
+ const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const;
private:
ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules,
@@ -142,7 +142,7 @@ class U_I18N_API MutablePatternModifier
* The plural form of the number, required only if the pattern contains the triple
* currency sign, "¤¤¤" (and as indicated by {@link #needsPlurals()}).
*/
- void setNumberProperties(int8_t signum, StandardPlural::Form plural);
+ void setNumberProperties(Signum signum, StandardPlural::Form plural);
/**
* Returns true if the pattern represented by this MurkyModifier requires a plural keyword in order to localize.
@@ -184,7 +184,7 @@ class U_I18N_API MutablePatternModifier
void processQuantity(DecimalQuantity &, MicroProps µs, UErrorCode &status) const U_OVERRIDE;
- int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
+ int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
UErrorCode &status) const U_OVERRIDE;
int32_t getPrefixLength() const U_OVERRIDE;
@@ -223,7 +223,7 @@ class U_I18N_API MutablePatternModifier
const PluralRules *fRules;
// Number details (initialized in setNumberProperties)
- int8_t fSignum;
+ Signum fSignum;
StandardPlural::Form fPlural;
// QuantityChain details (initialized in addToChain)
@@ -240,17 +240,17 @@ class U_I18N_API MutablePatternModifier
* CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP.
*
* @param a
- * A working NumberStringBuilder object; passed from the outside to prevent the need to create many new
+ * A working FormattedStringBuilder object; passed from the outside to prevent the need to create many new
* instances if this method is called in a loop.
* @param b
- * Another working NumberStringBuilder object.
+ * Another working FormattedStringBuilder object.
* @return The constant modifier object.
*/
ConstantMultiFieldModifier *createConstantModifier(UErrorCode &status);
- int32_t insertPrefix(NumberStringBuilder &sb, int position, UErrorCode &status);
+ int32_t insertPrefix(FormattedStringBuilder &sb, int position, UErrorCode &status);
- int32_t insertSuffix(NumberStringBuilder &sb, int position, UErrorCode &status);
+ int32_t insertSuffix(FormattedStringBuilder &sb, int position, UErrorCode &status);
void prepareAffix(bool isPrefix);
};
diff --git a/deps/icu-small/source/i18n/number_patternstring.cpp b/deps/icu-small/source/i18n/number_patternstring.cpp
index 90754246633064..c7212c1e5c23fe 100644
--- a/deps/icu-small/source/i18n/number_patternstring.cpp
+++ b/deps/icu-small/source/i18n/number_patternstring.cpp
@@ -352,7 +352,7 @@ void ParsedPatternInfo::consumeIntegerFormat(UErrorCode& status) {
result.groupingSizes += 1;
result.integerNumerals += 1;
result.integerTotal += 1;
- if (!result.rounding.isZero() || state.peek() != u'0') {
+ if (!result.rounding.isZeroish() || state.peek() != u'0') {
result.rounding.appendDigit(static_cast(state.peek() - u'0'), 0, true);
}
break;
@@ -532,7 +532,7 @@ PatternParser::patternInfoToProperties(DecimalFormatProperties& properties, Pars
properties.roundingIncrement = 0.0;
properties.minimumSignificantDigits = positive.integerAtSigns;
properties.maximumSignificantDigits = positive.integerAtSigns + positive.integerTrailingHashSigns;
- } else if (!positive.rounding.isZero()) {
+ } else if (!positive.rounding.isZeroish()) {
if (!ignoreRounding) {
properties.minimumFractionDigits = minFrac;
properties.maximumFractionDigits = positive.fractionTotal;
@@ -1000,7 +1000,7 @@ PatternStringUtils::convertLocalized(const UnicodeString& input, const DecimalFo
}
void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix,
- int8_t signum, UNumberSignDisplay signDisplay,
+ Signum signum, UNumberSignDisplay signDisplay,
StandardPlural::Form plural,
bool perMilleReplacesPercent, UnicodeString& output) {
@@ -1014,6 +1014,7 @@ void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider&
// Should we use the affix from the negative subpattern? (If not, we will use the positive
// subpattern.)
+ // TODO: Deal with signum
bool useNegativeAffixPattern = patternInfo.hasNegativeSubpattern() && (
signum == -1 || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign));
diff --git a/deps/icu-small/source/i18n/number_patternstring.h b/deps/icu-small/source/i18n/number_patternstring.h
index 42e7c3916133d1..819c74d4bd886d 100644
--- a/deps/icu-small/source/i18n/number_patternstring.h
+++ b/deps/icu-small/source/i18n/number_patternstring.h
@@ -295,7 +295,7 @@ class U_I18N_API PatternStringUtils {
* substitution, and plural forms for CurrencyPluralInfo.
*/
static void patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix,
- int8_t signum, UNumberSignDisplay signDisplay,
+ Signum signum, UNumberSignDisplay signDisplay,
StandardPlural::Form plural, bool perMilleReplacesPercent,
UnicodeString& output);
diff --git a/deps/icu-small/source/i18n/number_rounding.cpp b/deps/icu-small/source/i18n/number_rounding.cpp
index 9e369f7925fe2f..813d4b680d497b 100644
--- a/deps/icu-small/source/i18n/number_rounding.cpp
+++ b/deps/icu-small/source/i18n/number_rounding.cpp
@@ -33,7 +33,7 @@ int32_t getRoundingMagnitudeSignificant(const DecimalQuantity &value, int maxSig
if (maxSig == -1) {
return INT32_MIN;
}
- int magnitude = value.isZero() ? 0 : value.getMagnitude();
+ int magnitude = value.isZeroish() ? 0 : value.getMagnitude();
return magnitude - maxSig + 1;
}
@@ -45,7 +45,7 @@ int32_t getDisplayMagnitudeFraction(int minFrac) {
}
int32_t getDisplayMagnitudeSignificant(const DecimalQuantity &value, int minSig) {
- int magnitude = value.isZero() ? 0 : value.getMagnitude();
+ int magnitude = value.isZeroish() ? 0 : value.getMagnitude();
return magnitude - minSig + 1;
}
@@ -306,8 +306,8 @@ bool RoundingImpl::isSignificantDigits() const {
int32_t
RoundingImpl::chooseMultiplierAndApply(impl::DecimalQuantity &input, const impl::MultiplierProducer &producer,
UErrorCode &status) {
- // Do not call this method with zero.
- U_ASSERT(!input.isZero());
+ // Do not call this method with zero, NaN, or infinity.
+ U_ASSERT(!input.isZeroish());
// Perform the first attempt at rounding.
int magnitude = input.getMagnitude();
@@ -316,7 +316,7 @@ RoundingImpl::chooseMultiplierAndApply(impl::DecimalQuantity &input, const impl:
apply(input, status);
// If the number rounded to zero, exit.
- if (input.isZero() || U_FAILURE(status)) {
+ if (input.isZeroish() || U_FAILURE(status)) {
return multiplier;
}
@@ -374,7 +374,7 @@ void RoundingImpl::apply(impl::DecimalQuantity &value, UErrorCode& status) const
value.setMinFraction(
uprv_max(0, -getDisplayMagnitudeSignificant(value, fPrecision.fUnion.fracSig.fMinSig)));
// Make sure that digits are displayed on zero.
- if (value.isZero() && fPrecision.fUnion.fracSig.fMinSig > 0) {
+ if (value.isZeroish() && fPrecision.fUnion.fracSig.fMinSig > 0) {
value.setMinInteger(1);
}
break;
@@ -436,7 +436,7 @@ void RoundingImpl::apply(impl::DecimalQuantity &value, UErrorCode& status) const
void RoundingImpl::apply(impl::DecimalQuantity &value, int32_t minInt, UErrorCode /*status*/) {
// This method is intended for the one specific purpose of helping print "00.000E0".
U_ASSERT(isSignificantDigits());
- U_ASSERT(value.isZero());
+ U_ASSERT(value.isZeroish());
value.setMinFraction(fPrecision.fUnion.fracSig.fMinSig - minInt);
}
diff --git a/deps/icu-small/source/i18n/number_scientific.cpp b/deps/icu-small/source/i18n/number_scientific.cpp
index 6df07b9cc9e988..20aa45bff01959 100644
--- a/deps/icu-small/source/i18n/number_scientific.cpp
+++ b/deps/icu-small/source/i18n/number_scientific.cpp
@@ -8,7 +8,7 @@
#include
#include "number_scientific.h"
#include "number_utils.h"
-#include "number_stringbuilder.h"
+#include "formatted_string_builder.h"
#include "unicode/unum.h"
#include "number_microprops.h"
@@ -36,7 +36,7 @@ void ScientificModifier::set(int32_t exponent, const ScientificHandler *handler)
fHandler = handler;
}
-int32_t ScientificModifier::apply(NumberStringBuilder &output, int32_t /*leftIndex*/, int32_t rightIndex,
+int32_t ScientificModifier::apply(FormattedStringBuilder &output, int32_t /*leftIndex*/, int32_t rightIndex,
UErrorCode &status) const {
// FIXME: Localized exponent separator location.
int i = rightIndex;
@@ -123,9 +123,15 @@ void ScientificHandler::processQuantity(DecimalQuantity &quantity, MicroProps &m
fParent->processQuantity(quantity, micros, status);
if (U_FAILURE(status)) { return; }
+ // Do not apply scientific notation to special doubles
+ if (quantity.isInfinite() || quantity.isNaN()) {
+ micros.modInner = µs.helpers.emptyStrongModifier;
+ return;
+ }
+
// Treat zero as if it had magnitude 0
int32_t exponent;
- if (quantity.isZero()) {
+ if (quantity.isZeroish()) {
if (fSettings.fRequireMinInt && micros.rounder.isSignificantDigits()) {
// Show "00.000E0" on pattern "00.000E0"
micros.rounder.apply(quantity, fSettings.fEngineeringInterval, status);
diff --git a/deps/icu-small/source/i18n/number_scientific.h b/deps/icu-small/source/i18n/number_scientific.h
index e377bd941efaeb..1c9ce1efa80a3f 100644
--- a/deps/icu-small/source/i18n/number_scientific.h
+++ b/deps/icu-small/source/i18n/number_scientific.h
@@ -21,7 +21,7 @@ class U_I18N_API ScientificModifier : public UMemory, public Modifier {
void set(int32_t exponent, const ScientificHandler *handler);
- int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
+ int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
UErrorCode &status) const U_OVERRIDE;
int32_t getPrefixLength() const U_OVERRIDE;
diff --git a/deps/icu-small/source/i18n/number_skeletons.cpp b/deps/icu-small/source/i18n/number_skeletons.cpp
index 4c280ad11dd8da..4025539239b786 100644
--- a/deps/icu-small/source/i18n/number_skeletons.cpp
+++ b/deps/icu-small/source/i18n/number_skeletons.cpp
@@ -20,6 +20,7 @@
#include "unicode/numberformatter.h"
#include "uinvchar.h"
#include "charstr.h"
+#include "string_segment.h"
using namespace icu;
using namespace icu::number;
@@ -119,17 +120,17 @@ inline void appendMultiple(UnicodeString& sb, UChar32 cp, int32_t count) {
#define CHECK_NULL(seen, field, status) (void)(seen); /* for auto-format line wrapping */ \
-{ \
+UPRV_BLOCK_MACRO_BEGIN { \
if ((seen).field) { \
(status) = U_NUMBER_SKELETON_SYNTAX_ERROR; \
return STATE_NULL; \
} \
(seen).field = true; \
-}
+} UPRV_BLOCK_MACRO_END
#define SKELETON_UCHAR_TO_CHAR(dest, src, start, end, status) (void)(dest); \
-{ \
+UPRV_BLOCK_MACRO_BEGIN { \
UErrorCode conversionStatus = U_ZERO_ERROR; \
(dest).appendInvariantChars({FALSE, (src).getBuffer() + (start), (end) - (start)}, conversionStatus); \
if (conversionStatus == U_INVARIANT_CONVERSION_ERROR) { \
@@ -140,7 +141,7 @@ inline void appendMultiple(UnicodeString& sb, UChar32 cp, int32_t count) {
(status) = conversionStatus; \
return; \
} \
-}
+} UPRV_BLOCK_MACRO_END
} // anonymous namespace
@@ -1217,7 +1218,7 @@ void blueprint_helpers::parseIntegerWidthOption(const StringSegment& segment, Ma
maxInt = 0;
}
for (; offset < segment.length(); offset++) {
- if (segment.charAt(offset) == u'#') {
+ if (maxInt != -1 && segment.charAt(offset) == u'#') {
maxInt++;
} else {
break;
diff --git a/deps/icu-small/source/i18n/number_skeletons.h b/deps/icu-small/source/i18n/number_skeletons.h
index bc228bd0d7408e..59af771928fbd0 100644
--- a/deps/icu-small/source/i18n/number_skeletons.h
+++ b/deps/icu-small/source/i18n/number_skeletons.h
@@ -10,10 +10,10 @@
#include "number_types.h"
#include "numparse_types.h"
#include "unicode/ucharstrie.h"
+#include "string_segment.h"
-using icu::numparse::impl::StringSegment;
-
-U_NAMESPACE_BEGIN namespace number {
+U_NAMESPACE_BEGIN
+namespace number {
namespace impl {
// Forward-declaration
diff --git a/deps/icu-small/source/i18n/number_stringbuilder.h b/deps/icu-small/source/i18n/number_stringbuilder.h
deleted file mode 100644
index d48f6e106cf87e..00000000000000
--- a/deps/icu-small/source/i18n/number_stringbuilder.h
+++ /dev/null
@@ -1,164 +0,0 @@
-// © 2017 and later: Unicode, Inc. and others.
-// License & terms of use: http://www.unicode.org/copyright.html
-
-#include "unicode/utypes.h"
-
-#if !UCONFIG_NO_FORMATTING
-#ifndef __NUMBER_STRINGBUILDER_H__
-#define __NUMBER_STRINGBUILDER_H__
-
-
-#include
-#include "unicode/numfmt.h"
-#include "unicode/ustring.h"
-#include "cstring.h"
-#include "uassert.h"
-#include "number_types.h"
-#include "fphdlimp.h"
-
-U_NAMESPACE_BEGIN namespace number {
-namespace impl {
-
-class U_I18N_API NumberStringBuilder : public UMemory {
- private:
- static const int32_t DEFAULT_CAPACITY = 40;
-
- template
- union ValueOrHeapArray {
- T value[DEFAULT_CAPACITY];
- struct {
- T *ptr;
- int32_t capacity;
- } heap;
- };
-
- public:
- NumberStringBuilder();
-
- ~NumberStringBuilder();
-
- NumberStringBuilder(const NumberStringBuilder &other);
-
- NumberStringBuilder &operator=(const NumberStringBuilder &other);
-
- int32_t length() const;
-
- int32_t codePointCount() const;
-
- inline char16_t charAt(int32_t index) const {
- U_ASSERT(index >= 0);
- U_ASSERT(index < fLength);
- return getCharPtr()[fZero + index];
- }
-
- inline Field fieldAt(int32_t index) const {
- U_ASSERT(index >= 0);
- U_ASSERT(index < fLength);
- return getFieldPtr()[fZero + index];
- }
-
- UChar32 getFirstCodePoint() const;
-
- UChar32 getLastCodePoint() const;
-
- UChar32 codePointAt(int32_t index) const;
-
- UChar32 codePointBefore(int32_t index) const;
-
- NumberStringBuilder &clear();
-
- int32_t appendCodePoint(UChar32 codePoint, Field field, UErrorCode &status);
-
- int32_t insertCodePoint(int32_t index, UChar32 codePoint, Field field, UErrorCode &status);
-
- int32_t append(const UnicodeString &unistr, Field field, UErrorCode &status);
-
- int32_t insert(int32_t index, const UnicodeString &unistr, Field field, UErrorCode &status);
-
- int32_t insert(int32_t index, const UnicodeString &unistr, int32_t start, int32_t end, Field field,
- UErrorCode &status);
-
- int32_t splice(int32_t startThis, int32_t endThis, const UnicodeString &unistr,
- int32_t startOther, int32_t endOther, Field field, UErrorCode& status);
-
- int32_t append(const NumberStringBuilder &other, UErrorCode &status);
-
- int32_t insert(int32_t index, const NumberStringBuilder &other, UErrorCode &status);
-
- void writeTerminator(UErrorCode& status);
-
- /**
- * Gets a "safe" UnicodeString that can be used even after the NumberStringBuilder is destructed.
- * */
- UnicodeString toUnicodeString() const;
-
- /**
- * Gets an "unsafe" UnicodeString that is valid only as long as the NumberStringBuilder is alive and
- * unchanged. Slightly faster than toUnicodeString().
- */
- const UnicodeString toTempUnicodeString() const;
-
- UnicodeString toDebugString() const;
-
- const char16_t *chars() const;
-
- bool contentEquals(const NumberStringBuilder &other) const;
-
- bool nextFieldPosition(FieldPosition& fp, UErrorCode& status) const;
-
- void getAllFieldPositions(FieldPositionIteratorHandler& fpih, UErrorCode& status) const;
-
- bool nextPosition(ConstrainedFieldPosition& cfpos, Field numericField, UErrorCode& status) const;
-
- bool containsField(Field field) const;
-
- private:
- bool fUsingHeap = false;
- ValueOrHeapArray fChars;
- ValueOrHeapArray fFields;
- int32_t fZero = DEFAULT_CAPACITY / 2;
- int32_t fLength = 0;
-
- inline char16_t *getCharPtr() {
- return fUsingHeap ? fChars.heap.ptr : fChars.value;
- }
-
- inline const char16_t *getCharPtr() const {
- return fUsingHeap ? fChars.heap.ptr : fChars.value;
- }
-
- inline Field *getFieldPtr() {
- return fUsingHeap ? fFields.heap.ptr : fFields.value;
- }
-
- inline const Field *getFieldPtr() const {
- return fUsingHeap ? fFields.heap.ptr : fFields.value;
- }
-
- inline int32_t getCapacity() const {
- return fUsingHeap ? fChars.heap.capacity : DEFAULT_CAPACITY;
- }
-
- int32_t prepareForInsert(int32_t index, int32_t count, UErrorCode &status);
-
- int32_t prepareForInsertHelper(int32_t index, int32_t count, UErrorCode &status);
-
- int32_t remove(int32_t index, int32_t count);
-
- static bool isIntOrGroup(Field field);
-
- static bool isNumericField(Field field);
-
- int32_t trimBack(int32_t limit) const;
-
- int32_t trimFront(int32_t start) const;
-};
-
-} // namespace impl
-} // namespace number
-U_NAMESPACE_END
-
-
-#endif //__NUMBER_STRINGBUILDER_H__
-
-#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/deps/icu-small/source/i18n/number_types.h b/deps/icu-small/source/i18n/number_types.h
index 225d1e57750490..d62aa6a66b30d3 100644
--- a/deps/icu-small/source/i18n/number_types.h
+++ b/deps/icu-small/source/i18n/number_types.h
@@ -17,17 +17,16 @@
#include "unicode/platform.h"
#include "unicode/uniset.h"
#include "standardplural.h"
+#include "formatted_string_builder.h"
-U_NAMESPACE_BEGIN namespace number {
+U_NAMESPACE_BEGIN
+namespace number {
namespace impl {
-// Typedef several enums for brevity and for easier comparison to Java.
+// For convenience and historical reasons, import the Field typedef to the namespace.
+typedef FormattedStringBuilder::Field Field;
-// Convention: bottom 4 bits for field, top 4 bits for field category.
-// Field category 0 implies the number category so that the number field
-// literals can be directly passed as a Field type.
-// See the helper functions in "NumFieldUtils" in number_utils.h
-typedef uint8_t Field;
+// Typedef several enums for brevity and for easier comparison to Java.
typedef UNumberFormatRoundingMode RoundingMode;
@@ -49,7 +48,6 @@ static constexpr char16_t kFallbackPaddingString[] = u" ";
class Modifier;
class MutablePatternModifier;
class DecimalQuantity;
-class NumberStringBuilder;
class ModifierStore;
struct MicroProps;
@@ -93,6 +91,12 @@ enum CompactType {
TYPE_DECIMAL, TYPE_CURRENCY
};
+enum Signum {
+ SIGNUM_NEG = -1,
+ SIGNUM_ZERO = 0,
+ SIGNUM_POS = 1
+};
+
class U_I18N_API AffixPatternProvider {
public:
@@ -160,7 +164,7 @@ class U_I18N_API Modifier {
* formatted.
* @return The number of characters (UTF-16 code units) that were added to the string builder.
*/
- virtual int32_t apply(NumberStringBuilder& output, int leftIndex, int rightIndex,
+ virtual int32_t apply(FormattedStringBuilder& output, int leftIndex, int rightIndex,
UErrorCode& status) const = 0;
/**
@@ -196,11 +200,11 @@ class U_I18N_API Modifier {
*/
struct U_I18N_API Parameters {
const ModifierStore* obj = nullptr;
- int8_t signum;
+ Signum signum;
StandardPlural::Form plural;
Parameters();
- Parameters(const ModifierStore* _obj, int8_t _signum, StandardPlural::Form _plural);
+ Parameters(const ModifierStore* _obj, Signum _signum, StandardPlural::Form _plural);
};
/**
@@ -231,7 +235,7 @@ class U_I18N_API ModifierStore {
/**
* Returns a Modifier with the given parameters (best-effort).
*/
- virtual const Modifier* getModifier(int8_t signum, StandardPlural::Form plural) const = 0;
+ virtual const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const = 0;
};
diff --git a/deps/icu-small/source/i18n/number_utils.cpp b/deps/icu-small/source/i18n/number_utils.cpp
index 0983b7b0726ec2..91d7f335cd82d3 100644
--- a/deps/icu-small/source/i18n/number_utils.cpp
+++ b/deps/icu-small/source/i18n/number_utils.cpp
@@ -252,4 +252,15 @@ bool DecNum::isZero() const {
return decNumberIsZero(fData.getAlias());
}
+void DecNum::toString(ByteSink& output, UErrorCode& status) const {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ // "string must be at least dn->digits+14 characters long"
+ int32_t minCapacity = fData.getAlias()->digits + 14;
+ MaybeStackArray buffer(minCapacity);
+ uprv_decNumberToString(fData, buffer.getAlias());
+ output.Append(buffer.getAlias(), static_cast(uprv_strlen(buffer.getAlias())));
+}
+
#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/deps/icu-small/source/i18n/number_utils.h b/deps/icu-small/source/i18n/number_utils.h
index 203dec6d83b92b..93195f080b2787 100644
--- a/deps/icu-small/source/i18n/number_utils.h
+++ b/deps/icu-small/source/i18n/number_utils.h
@@ -17,6 +17,7 @@
#include "number_roundingutils.h"
#include "decNumber.h"
#include "charstr.h"
+#include "formatted_string_builder.h"
U_NAMESPACE_BEGIN
@@ -32,52 +33,10 @@ enum CldrPatternStyle {
CLDR_PATTERN_STYLE_COUNT,
};
-
-/**
- * Helper functions for dealing with the Field typedef, which stores fields
- * in a compressed format.
- */
-class NumFieldUtils {
-public:
- struct CategoryFieldPair {
- int32_t category;
- int32_t field;
- };
-
- /** Compile-time function to construct a Field from a category and a field */
- template
- static constexpr Field compress() {
- static_assert(category != 0, "cannot use Undefined category in NumFieldUtils");
- static_assert(category <= 0xf, "only 4 bits for category");
- static_assert(field <= 0xf, "only 4 bits for field");
- return static_cast((category << 4) | field);
- }
-
- /** Runtime inline function to unpack the category and field from the Field */
- static inline CategoryFieldPair expand(Field field) {
- if (field == UNUM_FIELD_COUNT) {
- return {UFIELD_CATEGORY_UNDEFINED, 0};
- }
- CategoryFieldPair ret = {
- (field >> 4),
- (field & 0xf)
- };
- if (ret.category == 0) {
- ret.category = UFIELD_CATEGORY_NUMBER;
- }
- return ret;
- }
-
- static inline bool isNumericField(Field field) {
- int8_t category = field >> 4;
- return category == 0 || category == UFIELD_CATEGORY_NUMBER;
- }
-};
-
// Namespace for naked functions
namespace utils {
-inline int32_t insertDigitFromSymbols(NumberStringBuilder& output, int32_t index, int8_t digit,
+inline int32_t insertDigitFromSymbols(FormattedStringBuilder& output, int32_t index, int8_t digit,
const DecimalFormatSymbols& symbols, Field field,
UErrorCode& status) {
if (symbols.getCodePointZero() != -1) {
diff --git a/deps/icu-small/source/i18n/number_utypes.h b/deps/icu-small/source/i18n/number_utypes.h
index 88b493cbc254c9..6dbe5bee68fb71 100644
--- a/deps/icu-small/source/i18n/number_utypes.h
+++ b/deps/icu-small/source/i18n/number_utypes.h
@@ -10,7 +10,7 @@
#include "unicode/numberformatter.h"
#include "number_types.h"
#include "number_decimalquantity.h"
-#include "number_stringbuilder.h"
+#include "formatted_string_builder.h"
#include "formattedval_impl.h"
U_NAMESPACE_BEGIN namespace number {
@@ -31,9 +31,9 @@ const DecimalQuantity* validateUFormattedNumberToDecimalQuantity(
* The DecimalQuantity is not currently being used by FormattedNumber, but at some point it could be used
* to add a toDecNumber() or similar method.
*/
-class UFormattedNumberData : public FormattedValueNumberStringBuilderImpl {
+class UFormattedNumberData : public FormattedValueStringBuilderImpl {
public:
- UFormattedNumberData() : FormattedValueNumberStringBuilderImpl(0) {}
+ UFormattedNumberData() : FormattedValueStringBuilderImpl(0) {}
virtual ~UFormattedNumberData();
DecimalQuantity quantity;
diff --git a/deps/icu-small/source/i18n/numfmt.cpp b/deps/icu-small/source/i18n/numfmt.cpp
index 21efd184558778..bf78179bcddefe 100644
--- a/deps/icu-small/source/i18n/numfmt.cpp
+++ b/deps/icu-small/source/i18n/numfmt.cpp
@@ -569,7 +569,7 @@ NumberFormat::format(const Formattable& obj,
if(arg.wasCurrency() && u_strcmp(iso, getCurrency())) {
// trying to format a different currency.
// Right now, we clone.
- LocalPointer