diff options
136 files changed, 2401 insertions, 1579 deletions
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index 3bb9c916fd..9e63da3fc4 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -198,7 +198,7 @@ License: HarfBuzz Files: ./thirdparty/icu4c/ Comment: International Components for Unicode -Copyright: 1991-2020, Unicode +Copyright: 1991-2021, Unicode License: Unicode Files: ./thirdparty/jpeg-compressor/ diff --git a/core/math/random_pcg.cpp b/core/math/random_pcg.cpp index 9609620469..1152c4e834 100644 --- a/core/math/random_pcg.cpp +++ b/core/math/random_pcg.cpp @@ -39,7 +39,7 @@ RandomPCG::RandomPCG(uint64_t p_seed, uint64_t p_inc) : } void RandomPCG::randomize() { - seed(OS::get_singleton()->get_ticks_usec() * pcg.state + PCG_DEFAULT_INC_64); + seed((OS::get_singleton()->get_unix_time() + OS::get_singleton()->get_ticks_usec()) * pcg.state + PCG_DEFAULT_INC_64); } double RandomPCG::random(double p_from, double p_to) { diff --git a/core/string/node_path.h b/core/string/node_path.h index 26e15636d9..a277ab26fa 100644 --- a/core/string/node_path.h +++ b/core/string/node_path.h @@ -66,8 +66,6 @@ public: void prepend_period(); - NodePath get_parent() const; - _FORCE_INLINE_ uint32_t hash() const { if (!data) { return 0; diff --git a/core/templates/safe_refcount.h b/core/templates/safe_refcount.h index 91a34ecd54..e9e5695f80 100644 --- a/core/templates/safe_refcount.h +++ b/core/templates/safe_refcount.h @@ -36,6 +36,7 @@ #if !defined(NO_THREADS) #include <atomic> +#include <type_traits> // Design goals for these classes: // - No automatic conversions or arithmetic operators, diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 25f8f22d44..95108f1613 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -804,10 +804,7 @@ <method name="randomize"> <description> Randomizes the seed (or the internal state) of the random number generator. Current implementation reseeds using a number based on time. - [codeblock] - func _ready(): - randomize() - [/codeblock] + [b]Note:[/b] This method is called automatically when the project is run. If you need to fix the seed to have reproducible results, use [method seed] to initialize the random number generator. </description> </method> <method name="range_lerp"> diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml index c33d007735..d645588af2 100644 --- a/doc/classes/Color.xml +++ b/doc/classes/Color.xml @@ -269,7 +269,7 @@ <argument index="1" name="weight" type="float"> </argument> <description> - Returns the linear interpolation with another color. The interpolation factor [code]t[/code] is between 0 and 1. + Returns the linear interpolation with another color. The interpolation factor [code]weight[/code] is between 0 and 1. [codeblocks] [gdscript] var c1 = Color(1.0, 0.0, 0.0) diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index 701a430538..229facd08b 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -659,11 +659,9 @@ </return> <argument index="0" name="body" type="RID"> </argument> - <argument index="1" name="receiver" type="Object"> - </argument> - <argument index="2" name="method" type="StringName"> + <argument index="1" name="callable" type="Callable"> </argument> - <argument index="3" name="userdata" type="Variant" default="null"> + <argument index="2" name="userdata" type="Variant" default="null"> </argument> <description> Sets the function used to calculate physics for an object, if that object allows it (see [method body_set_omit_force_integration]). diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml index c61347ba0b..46de9e5282 100644 --- a/doc/classes/PhysicsServer3D.xml +++ b/doc/classes/PhysicsServer3D.xml @@ -653,11 +653,9 @@ </return> <argument index="0" name="body" type="RID"> </argument> - <argument index="1" name="receiver" type="Object"> - </argument> - <argument index="2" name="method" type="StringName"> + <argument index="1" name="callable" type="Callable"> </argument> - <argument index="3" name="userdata" type="Variant" default="null"> + <argument index="2" name="userdata" type="Variant" default="null"> </argument> <description> Sets the function used to calculate physics for an object, if that object allows it (see [method body_set_omit_force_integration]). diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index c8fd0d667b..2bfe7ad48f 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -6,6 +6,7 @@ <description> Contains global variables accessible from everywhere. Use [method get_setting], [method set_setting] or [method has_setting] to access them. Variables stored in [code]project.godot[/code] are also loaded into ProjectSettings, making this object very useful for reading custom game configuration options. When naming a Project Settings property, use the full path to the setting including the category. For example, [code]"application/config/name"[/code] for the project name. Category and property names can be viewed in the Project Settings dialog. + [b]Feature tags:[/b] Project settings can be overriden for specific platforms and configurations (debug, release, ...) using [url=https://docs.godotengine.org/en/latest/tutorials/export/feature_tags.html]feature tags[/url]. [b]Overriding:[/b] Any project setting can be overridden by creating a file named [code]override.cfg[/code] in the project's root directory. This can also be used in exported projects by placing this file in the same directory as the project binary. Overriding will still take the base project settings' [url=https://docs.godotengine.org/en/latest/tutorials/export/feature_tags.html]feature tags[/url] in account. Therefore, make sure to [i]also[/i] override the setting with the desired feature tags if you want them to override base project settings on all platforms and configurations. </description> <tutorials> @@ -746,6 +747,11 @@ <member name="input_devices/pointing/ios/touch_delay" type="float" setter="" getter="" default="0.15"> Default delay for touch events. This only affects iOS devices. </member> + <member name="internationalization/locale/include_text_server_data" type="bool" setter="" getter="" default="false"> + If [code]true[/code], text server break iteration rule sets, dictionaries and other optional data are included in the exported project. + [b]Note:[/b] "ICU / HarfBuzz / Graphite" text server data includes dictionaries for Burmese, Chinese, Japanese, Khmer, Lao and Thai as well as Unicode Standard Annex #29 and Unicode Standard Annex #14 word and line breaking rules. Data is about 4 MB large. + [b]Note:[/b] "Fallback" text server does not use additional data. + </member> <member name="internationalization/locale/fallback" type="String" setter="" getter="" default=""en""> The locale to fall back to if a translation isn't available in a given language. If left empty, [code]en[/code] (English) will be used. </member> diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index b979425b85..94d4b1a903 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -229,7 +229,7 @@ <argument index="1" name="weight" type="float"> </argument> <description> - Returns the result of the linear interpolation between this vector and [code]b[/code] by amount [code]t[/code]. [code]t[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. + Returns the result of the linear interpolation between this vector and [code]to[/code] by amount [code]weight[/code]. [code]weight[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. </description> </method> <method name="move_toward" qualifiers="const"> @@ -464,7 +464,7 @@ <argument index="1" name="weight" type="float"> </argument> <description> - Returns the result of spherical linear interpolation between this vector and [code]b[/code], by amount [code]t[/code]. [code]t[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. + Returns the result of spherical linear interpolation between this vector and [code]to[/code], by amount [code]weight[/code]. [code]weight[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. [b]Note:[/b] Both vectors must be normalized. </description> </method> diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml index bd568e01ec..0a86369506 100644 --- a/doc/classes/Vector3.xml +++ b/doc/classes/Vector3.xml @@ -204,7 +204,7 @@ <argument index="1" name="weight" type="float"> </argument> <description> - Returns the result of the linear interpolation between this vector and [code]b[/code] by amount [code]weight[/code]. [code]weight[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. + Returns the result of the linear interpolation between this vector and [code]to[/code] by amount [code]weight[/code]. [code]weight[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. </description> </method> <method name="max_axis" qualifiers="const"> @@ -484,7 +484,7 @@ <argument index="1" name="weight" type="float"> </argument> <description> - Returns the result of spherical linear interpolation between this vector and [code]b[/code], by amount [code]t[/code]. [code]t[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. + Returns the result of spherical linear interpolation between this vector and [code]to[/code], by amount [code]weight[/code]. [code]weight[/code] is on the range of 0.0 to 1.0, representing the amount of interpolation. [b]Note:[/b] Both vectors must be normalized. </description> </method> diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp index 3ef9548727..ded0ee3aa7 100644 --- a/editor/debugger/editor_debugger_node.cpp +++ b/editor/debugger/editor_debugger_node.cpp @@ -209,7 +209,7 @@ void EditorDebuggerNode::stop() { // Also close all debugging sessions. _for_all(tabs, [&](ScriptEditorDebugger *dbg) { if (dbg->is_session_active()) { - dbg->stop(); + dbg->_stop_and_notify(); } }); _break_state_changed(); diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index a5ebfbfb8a..a368a9618e 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -1051,14 +1051,28 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & } } - // Store text server data if exists. + // Store text server data if it is supported. if (TS->has_feature(TextServer::FEATURE_USE_SUPPORT_DATA)) { - String ts_data = "res://" + TS->get_support_data_filename(); - if (FileAccess::exists(ts_data)) { - Vector<uint8_t> array = FileAccess::get_file_as_array(ts_data); - err = p_func(p_udata, ts_data, array, idx, total, enc_in_filters, enc_ex_filters, key); - if (err != OK) { - return err; + bool use_data = ProjectSettings::get_singleton()->get("internationalization/locale/include_text_server_data"); + if (use_data) { + // Try using user provided data file. + String ts_data = "res://" + TS->get_support_data_filename(); + if (FileAccess::exists(ts_data)) { + Vector<uint8_t> array = FileAccess::get_file_as_array(ts_data); + err = p_func(p_udata, ts_data, array, idx, total, enc_in_filters, enc_ex_filters, key); + if (err != OK) { + return err; + } + } else { + // Use default text server data. + String icu_data_file = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_icu_data"); + TS->save_support_data(icu_data_file); + Vector<uint8_t> array = FileAccess::get_file_as_array(icu_data_file); + err = p_func(p_udata, ts_data, array, idx, total, enc_in_filters, enc_ex_filters, key); + DirAccess::remove_file_or_error(icu_data_file); + if (err != OK) { + return err; + } } } } diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index 781d21c370..0f5c01be0e 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -116,13 +116,14 @@ void ExportTemplateManager::_update_template_list() { } for (Set<String>::Element *E = templates.back(); E; E = E->prev()) { - HBoxContainer *hbc = memnew(HBoxContainer); - Label *version = memnew(Label); - version->set_modulate(current->get_theme_color("disabled_font_color", "Editor")); String text = E->get(); if (text == current_version) { - text += " " + TTR("(Current)"); + continue; } + + HBoxContainer *hbc = memnew(HBoxContainer); + Label *version = memnew(Label); + version->set_modulate(current->get_theme_color("disabled_font_color", "Editor")); version->set_text(text); version->set_h_size_flags(Control::SIZE_EXPAND_FILL); hbc->add_child(version); @@ -653,7 +654,7 @@ ExportTemplateManager::ExportTemplateManager() { main_vb->add_margin_child(TTR("Current Version:"), current_hb, false); installed_scroll = memnew(ScrollContainer); - main_vb->add_margin_child(TTR("Installed Versions:"), installed_scroll, true); + main_vb->add_margin_child(TTR("Other Installed Versions:"), installed_scroll, true); installed_vb = memnew(VBoxContainer); installed_scroll->add_child(installed_vb); diff --git a/editor/icons/FontSize.svg b/editor/icons/FontSize.svg new file mode 100644 index 0000000000..e608d89b6a --- /dev/null +++ b/editor/icons/FontSize.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><g id="SmallerT"><rect x="1.047" y="7.127" width="6.025" height="1.2" style="fill:#e0e0e0;fill-rule:nonzero;"/><rect x="3.452" y="7.127" width="1.214" height="6.508" style="fill:#e0e0e0;fill-rule:nonzero;"/><rect x="2.238" y="13.171" width="3.643" height="0.465" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M1.477,7.127l0,2.4l-0.43,0l-0,-2.4l0.43,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M7.071,7.127l0,2.4l-0.43,0l0,-2.4l0.43,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M1.477,8.327l0,1.2c0,-0.658 0.389,-1.2 0.861,-1.2l-0.861,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M5.78,8.327c0.473,0 0.861,0.542 0.861,1.2l0,-1.2l-0.861,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M2.238,13.171c0.666,-0 1.214,-0.42 1.214,-0.93l0,0.93l-1.214,-0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M5.88,13.171c-0.666,-0 -1.214,-0.42 -1.214,-0.93l0,0.93l1.214,-0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g><g id="BiggerT"><rect x="4.563" y="2.873" width="10.773" height="1.539" style="fill:#e0e0e0;fill-rule:nonzero;"/><rect x="9.18" y="2.873" width="1.539" height="10.773" style="fill:#e0e0e0;fill-rule:nonzero;"/><rect x="7.641" y="12.877" width="4.617" height="0.769" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M5.332,2.873l0,3.078l-0.769,0l-0,-3.078l0.769,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M15.336,2.873l-0,3.078l-0.77,0l0,-3.078l0.77,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M5.332,4.412l0,1.539c0,-0.844 0.695,-1.539 1.539,-1.539l-1.539,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M13.027,4.412c0.844,0 1.539,0.695 1.539,1.539l0,-1.539l-1.539,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M7.641,12.877c0.844,-0 1.539,-0.695 1.539,-1.539l-0,1.539l-1.539,-0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M12.258,12.877c-0.845,-0 -1.539,-0.695 -1.539,-1.539l-0,1.539l1.539,-0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g></svg> diff --git a/editor/icons/ThemeRemoveAllItems.svg b/editor/icons/ThemeRemoveAllItems.svg new file mode 100644 index 0000000000..47ed624d04 --- /dev/null +++ b/editor/icons/ThemeRemoveAllItems.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><path d="M8,1.745c-0.595,0 -1.084,0.489 -1.084,1.084l0,3.699l-3.851,-1.927c-0.163,-0.08 -0.343,-0.119 -0.525,-0.112c-0.395,0.015 -0.752,0.244 -0.929,0.597c-0.076,0.151 -0.115,0.317 -0.115,0.485c0,0.41 0.233,0.786 0.599,0.97l3.481,1.74l-3.481,1.74c-0.366,0.184 -0.599,0.56 -0.599,0.97c0,0.168 0.039,0.334 0.115,0.485c0.183,0.367 0.559,0.599 0.969,0.599c0.168,0 0.334,-0.039 0.485,-0.114l3.851,-1.927l0,3.111c0,0.594 0.489,1.084 1.084,1.084c0.595,-0 1.084,-0.49 1.084,-1.084l-0,-3.111l3.851,1.927c0.151,0.075 0.317,0.114 0.485,0.114c0.41,0 0.786,-0.232 0.969,-0.599c0.076,-0.151 0.115,-0.317 0.115,-0.485c-0,-0.41 -0.233,-0.786 -0.599,-0.97l-3.481,-1.74l3.481,-1.74c0.366,-0.184 0.599,-0.56 0.599,-0.97c-0,-0.168 -0.039,-0.334 -0.115,-0.485c-0.182,-0.364 -0.554,-0.596 -0.961,-0.599c-0.171,-0.001 -0.34,0.038 -0.493,0.114l-3.851,1.927l-0,-3.699c-0,-0.595 -0.489,-1.084 -1.084,-1.084Z" style="fill:#a5efac;"/><path d="M8,1.745c-0,0 -0,1.783 -0,1.783l-1.084,0l0,-0.699c0,-0.595 0.489,-1.084 1.084,-1.084Z" style="fill:#ff7070;fill-rule:nonzero;"/><path d="M1.528,5.312l2.957,-0l-1.42,-0.711c-0.163,-0.08 -0.343,-0.119 -0.525,-0.112c-0.395,0.015 -0.752,0.244 -0.929,0.597c-0.036,0.072 -0.064,0.148 -0.083,0.226Zm5.388,-1.784l1.084,0l-0,1.784l-1.084,-0l0,-1.784Z" style="fill:#ffeb70;fill-rule:nonzero;"/><path d="M6.916,5.312l1.084,-0l-0,1.783l-4.796,0l-1.109,-0.554c-0.366,-0.184 -0.599,-0.56 -0.599,-0.97c0,-0.088 0.011,-0.175 0.032,-0.259l2.957,-0l2.431,1.216l0,-1.216Z" style="fill:#9dff70;fill-rule:nonzero;"/><path d="M3.204,7.095l4.796,0l-0,1.783l-3.619,0l1.195,-0.597l-2.372,-1.186Z" style="fill:#70ffb9;fill-rule:nonzero;"/><path d="M4.381,8.878l3.619,0l-0,1.784l-1.084,-0l0,-0.628l-1.255,0.628l-4.114,-0c0.088,-0.274 0.283,-0.508 0.548,-0.641l2.286,-1.143Z" style="fill:#70deff;fill-rule:nonzero;"/><path d="M6.916,12.445l1.084,0l-0,1.784l-0,-0c-0.595,-0.001 -1.084,-0.49 -1.084,-1.084l0,-0.7Z" style="fill:#ff70ac;fill-rule:nonzero;"/><path d="M6.916,10.662l1.084,-0l-0,1.783l-1.084,0l0,-1.783Zm-1.255,-0l-4.114,-0c-0.033,0.105 -0.051,0.216 -0.051,0.329c0,0.168 0.039,0.334 0.115,0.485c0.183,0.367 0.559,0.599 0.969,0.599c0.168,0 0.334,-0.039 0.485,-0.114l2.596,-1.299Z" style="fill:#9f70ff;fill-rule:nonzero;"/></svg> diff --git a/editor/icons/ThemeRemoveCustomItems.svg b/editor/icons/ThemeRemoveCustomItems.svg new file mode 100644 index 0000000000..bb8a8bd026 --- /dev/null +++ b/editor/icons/ThemeRemoveCustomItems.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><path d="M11.299,3c0.772,0.513 1.42,1.199 1.888,2l-2.553,0c-0.706,-0.621 -1.629,-1 -2.634,-1c-1.005,0 -1.928,0.379 -2.634,1l-2.553,0c0.468,-0.801 1.116,-1.487 1.888,-2l6.598,-0Z" style="fill:#ffeb70;fill-rule:nonzero;"/><path d="M5.366,5c-0.593,0.522 -1.033,1.216 -1.238,2l-2.043,0c0.122,-0.717 0.373,-1.392 0.728,-2l2.553,-0Zm7.821,-0c0.355,0.608 0.606,1.283 0.728,2l-2.043,0c-0.205,-0.784 -0.645,-1.478 -1.238,-2l2.553,-0Z" style="fill:#9dff70;fill-rule:nonzero;"/><path d="M13.915,7c0.056,0.326 0.085,0.66 0.085,1c-0,0.34 -0.029,0.674 -0.085,1l-2.043,0c0.083,-0.32 0.128,-0.655 0.128,-1c0,-0.345 -0.045,-0.68 -0.128,-1l2.043,-0Zm-9.787,0c-0.083,0.32 -0.128,0.655 -0.128,1c0,0.345 0.045,0.68 0.128,1l-2.043,-0c-0.056,-0.326 -0.085,-0.66 -0.085,-1c0,-0.34 0.029,-0.674 0.085,-1l2.043,0Z" style="fill:#70ffb9;fill-rule:nonzero;"/><path d="M4.128,9c0.205,0.784 0.645,1.478 1.238,2l-2.553,0c-0.355,-0.608 -0.606,-1.283 -0.728,-2l2.043,0Zm9.787,0c-0.122,0.717 -0.373,1.392 -0.728,2l-2.553,0c0.593,-0.522 1.033,-1.216 1.238,-2l2.043,0Z" style="fill:#70deff;fill-rule:nonzero;"/><path d="M11.299,13l-6.598,0c0.949,0.631 2.084,1 3.299,1c1.215,0 2.35,-0.369 3.299,-1Z" style="fill:#ff70ac;fill-rule:nonzero;"/><path d="M13.187,11c-0.468,0.801 -1.116,1.487 -1.888,2l-6.598,0c-0.772,-0.513 -1.42,-1.199 -1.888,-2l2.553,0c0.706,0.621 1.629,1 2.634,1c1.005,0 1.928,-0.379 2.634,-1l2.553,0Z" style="fill:#9f70ff;fill-rule:nonzero;"/><path d="M4.701,3l6.598,0c-0.949,-0.631 -2.084,-1 -3.299,-1c-1.215,0 -2.35,0.369 -3.299,1Z" style="fill:#ff7070;fill-rule:nonzero;"/></svg> diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp index 0e68af06f0..161f1dde0d 100644 --- a/editor/localization_editor.cpp +++ b/editor/localization_editor.cpp @@ -37,24 +37,6 @@ #include "scene/gui/control.h" void LocalizationEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_TEXT_SERVER_CHANGED) { - ts_name->set_text(TTR("Text server: ") + TS->get_name()); - - FileAccessRef file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES); - if (TS->has_feature(TextServer::FEATURE_USE_SUPPORT_DATA)) { - if (file_check->file_exists("res://" + TS->get_support_data_filename())) { - ts_data_status->set_text(TTR("Support data: ") + TTR("Installed")); - ts_install->set_disabled(true); - } else { - ts_data_status->set_text(TTR("Support data: ") + TTR("Not installed")); - ts_install->set_disabled(false); - } - } else { - ts_data_status->set_text(TTR("Support data: ") + TTR("Not supported")); - ts_install->set_disabled(false); - } - ts_data_info->set_text(TTR("Info: ") + TS->get_support_data_info()); - } if (p_what == NOTIFICATION_ENTER_TREE) { translation_list->connect("button_pressed", callable_mp(this, &LocalizationEditor::_translation_delete)); translation_pot_list->connect("button_pressed", callable_mp(this, &LocalizationEditor::_pot_delete)); @@ -649,26 +631,6 @@ void LocalizationEditor::update_translations() { updating_translations = false; } -void LocalizationEditor::_install_ts_data() { - if (TS->has_feature(TextServer::FEATURE_USE_SUPPORT_DATA)) { - TS->save_support_data("res://" + TS->get_support_data_filename()); - } - - FileAccessRef file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES); - if (TS->has_feature(TextServer::FEATURE_USE_SUPPORT_DATA)) { - if (file_check->file_exists("res://" + TS->get_support_data_filename())) { - ts_data_status->set_text(TTR("Support data: ") + TTR("Installed")); - ts_install->set_disabled(true); - } else { - ts_data_status->set_text(TTR("Support data: ") + TTR("Not installed")); - ts_install->set_disabled(false); - } - } else { - ts_data_status->set_text(TTR("Support data: ") + TTR("Not supported")); - ts_install->set_disabled(false); - } -} - void LocalizationEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("update_translations"), &LocalizationEditor::update_translations); @@ -838,37 +800,4 @@ LocalizationEditor::LocalizationEditor() { pot_file_open_dialog->connect("files_selected", callable_mp(this, &LocalizationEditor::_pot_add)); add_child(pot_file_open_dialog); } - - { - VBoxContainer *tvb = memnew(VBoxContainer); - tvb->set_name(TTR("Text Server Data")); - translations->add_child(tvb); - - ts_name = memnew(Label(TTR("Text server: ") + TS->get_name())); - tvb->add_child(ts_name); - - ts_data_status = memnew(Label(TTR("Support data: "))); - tvb->add_child(ts_data_status); - - ts_data_info = memnew(Label(TTR("Info: ") + TS->get_support_data_info())); - tvb->add_child(ts_data_info); - - ts_install = memnew(Button(TTR("Install support data..."))); - ts_install->connect("pressed", callable_mp(this, &LocalizationEditor::_install_ts_data)); - tvb->add_child(ts_install); - - FileAccessRef file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES); - if (TS->has_feature(TextServer::FEATURE_USE_SUPPORT_DATA)) { - if (file_check->file_exists("res://" + TS->get_support_data_filename())) { - ts_data_status->set_text(TTR("Support data: ") + TTR("Installed")); - ts_install->set_disabled(true); - } else { - ts_data_status->set_text(TTR("Support data: ") + TTR("Not installed")); - ts_install->set_disabled(false); - } - } else { - ts_data_status->set_text(TTR("Support data: ") + TTR("Not supported")); - ts_install->set_disabled(false); - } - } } diff --git a/editor/localization_editor.h b/editor/localization_editor.h index 6e0d7ce61f..23cea06fbe 100644 --- a/editor/localization_editor.h +++ b/editor/localization_editor.h @@ -58,11 +58,6 @@ class LocalizationEditor : public VBoxContainer { Vector<TreeItem *> translation_filter_treeitems; Vector<int> translation_locales_idxs_remap; - Label *ts_name; - Label *ts_data_status; - Label *ts_data_info; - Button *ts_install; - Tree *translation_pot_list; EditorFileDialog *pot_file_open_dialog; EditorFileDialog *pot_generate_dialog; @@ -94,8 +89,6 @@ class LocalizationEditor : public VBoxContainer { void _pot_generate(const String &p_file); void _update_pot_file_extensions(); - void _install_ts_data(); - protected: void _notification(int p_what); static void _bind_methods(); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index dfa8c04145..c765aa0319 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -31,12 +31,696 @@ #include "theme_editor_plugin.h" #include "core/os/file_access.h" +#include "core/os/keyboard.h" #include "core/version.h" #include "editor/editor_scale.h" #include "scene/gui/progress_bar.h" +void ThemeItemEditorDialog::_dialog_about_to_show() { + ERR_FAIL_COND(edited_theme.is_null()); + + _update_edit_types(); +} + +void ThemeItemEditorDialog::_update_edit_types() { + Ref<Theme> base_theme = Theme::get_default(); + + List<StringName> theme_types; + edited_theme->get_type_list(&theme_types); + theme_types.sort_custom<StringName::AlphCompare>(); + + bool item_reselected = false; + edit_type_list->clear(); + int e_idx = 0; + for (List<StringName>::Element *E = theme_types.front(); E; E = E->next()) { + Ref<Texture2D> item_icon; + if (E->get() == "") { + item_icon = get_theme_icon("NodeDisabled", "EditorIcons"); + } else { + item_icon = EditorNode::get_singleton()->get_class_icon(E->get(), "NodeDisabled"); + } + edit_type_list->add_item(E->get(), item_icon); + + if (E->get() == edited_item_type) { + edit_type_list->select(e_idx); + item_reselected = true; + } + e_idx++; + } + if (!item_reselected) { + edited_item_type = ""; + + if (edit_type_list->get_item_count() > 0) { + edit_type_list->select(0); + } + } + + List<StringName> default_types; + base_theme->get_type_list(&default_types); + default_types.sort_custom<StringName::AlphCompare>(); + + edit_add_class_options->clear(); + for (List<StringName>::Element *E = default_types.front(); E; E = E->next()) { + edit_add_class_options->add_item(E->get()); + } + + String selected_type = ""; + Vector<int> selected_ids = edit_type_list->get_selected_items(); + if (selected_ids.size() > 0) { + selected_type = edit_type_list->get_item_text(selected_ids[0]); + + edit_items_add_color->set_disabled(false); + edit_items_add_constant->set_disabled(false); + edit_items_add_font->set_disabled(false); + edit_items_add_font_size->set_disabled(false); + edit_items_add_icon->set_disabled(false); + edit_items_add_stylebox->set_disabled(false); + + edit_items_remove_class->set_disabled(false); + edit_items_remove_custom->set_disabled(false); + edit_items_remove_all->set_disabled(false); + } else { + edit_items_add_color->set_disabled(true); + edit_items_add_constant->set_disabled(true); + edit_items_add_font->set_disabled(true); + edit_items_add_font_size->set_disabled(true); + edit_items_add_icon->set_disabled(true); + edit_items_add_stylebox->set_disabled(true); + + edit_items_remove_class->set_disabled(true); + edit_items_remove_custom->set_disabled(true); + edit_items_remove_all->set_disabled(true); + } + _update_edit_item_tree(selected_type); +} + +void ThemeItemEditorDialog::_edited_type_selected(int p_item_idx) { + String selected_type = edit_type_list->get_item_text(p_item_idx); + _update_edit_item_tree(selected_type); +} + +void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) { + edited_item_type = p_item_type; + + edit_items_tree->clear(); + TreeItem *root = edit_items_tree->create_item(); + + List<StringName> names; + + { + names.clear(); + edited_theme->get_color_list(p_item_type, &names); + + if (names.size() > 0) { + TreeItem *color_root = edit_items_tree->create_item(root); + color_root->set_metadata(0, Theme::DATA_TYPE_COLOR); + color_root->set_icon(0, get_theme_icon("Color", "EditorIcons")); + color_root->set_text(0, TTR("Colors")); + color_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Color Items")); + + names.sort_custom<StringName::AlphCompare>(); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + TreeItem *item = edit_items_tree->create_item(color_root); + item->set_text(0, E->get()); + item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item")); + item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item")); + } + } + } + + { + names.clear(); + edited_theme->get_constant_list(p_item_type, &names); + + if (names.size() > 0) { + TreeItem *constant_root = edit_items_tree->create_item(root); + constant_root->set_metadata(0, Theme::DATA_TYPE_CONSTANT); + constant_root->set_icon(0, get_theme_icon("MemberConstant", "EditorIcons")); + constant_root->set_text(0, TTR("Constants")); + constant_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Constant Items")); + + names.sort_custom<StringName::AlphCompare>(); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + TreeItem *item = edit_items_tree->create_item(constant_root); + item->set_text(0, E->get()); + item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item")); + item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item")); + } + } + } + + { + names.clear(); + edited_theme->get_font_list(p_item_type, &names); + + if (names.size() > 0) { + TreeItem *font_root = edit_items_tree->create_item(root); + font_root->set_metadata(0, Theme::DATA_TYPE_FONT); + font_root->set_icon(0, get_theme_icon("Font", "EditorIcons")); + font_root->set_text(0, TTR("Fonts")); + font_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Font Items")); + + names.sort_custom<StringName::AlphCompare>(); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + TreeItem *item = edit_items_tree->create_item(font_root); + item->set_text(0, E->get()); + item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item")); + item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item")); + } + } + } + + { + names.clear(); + edited_theme->get_font_size_list(p_item_type, &names); + + if (names.size() > 0) { + TreeItem *font_size_root = edit_items_tree->create_item(root); + font_size_root->set_metadata(0, Theme::DATA_TYPE_FONT_SIZE); + font_size_root->set_icon(0, get_theme_icon("FontSize", "EditorIcons")); + font_size_root->set_text(0, TTR("Font Sizes")); + font_size_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Font Size Items")); + + names.sort_custom<StringName::AlphCompare>(); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + TreeItem *item = edit_items_tree->create_item(font_size_root); + item->set_text(0, E->get()); + item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item")); + item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item")); + } + } + } + + { + names.clear(); + edited_theme->get_icon_list(p_item_type, &names); + + if (names.size() > 0) { + TreeItem *icon_root = edit_items_tree->create_item(root); + icon_root->set_metadata(0, Theme::DATA_TYPE_ICON); + icon_root->set_icon(0, get_theme_icon("ImageTexture", "EditorIcons")); + icon_root->set_text(0, TTR("Icons")); + icon_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Icon Items")); + + names.sort_custom<StringName::AlphCompare>(); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + TreeItem *item = edit_items_tree->create_item(icon_root); + item->set_text(0, E->get()); + item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item")); + item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item")); + } + } + } + + { + names.clear(); + edited_theme->get_stylebox_list(p_item_type, &names); + + if (names.size() > 0) { + TreeItem *stylebox_root = edit_items_tree->create_item(root); + stylebox_root->set_metadata(0, Theme::DATA_TYPE_STYLEBOX); + stylebox_root->set_icon(0, get_theme_icon("StyleBoxFlat", "EditorIcons")); + stylebox_root->set_text(0, TTR("Styleboxes")); + stylebox_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All StyleBox Items")); + + names.sort_custom<StringName::AlphCompare>(); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + TreeItem *item = edit_items_tree->create_item(stylebox_root); + item->set_text(0, E->get()); + item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item")); + item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item")); + } + } + } +} + +void ThemeItemEditorDialog::_item_tree_button_pressed(Object *p_item, int p_column, int p_id) { + TreeItem *item = Object::cast_to<TreeItem>(p_item); + if (!item) { + return; + } + + switch (p_id) { + case ITEMS_TREE_RENAME_ITEM: { + String item_name = item->get_text(0); + int data_type = item->get_parent()->get_metadata(0); + _open_rename_theme_item_dialog((Theme::DataType)data_type, item_name); + } break; + case ITEMS_TREE_REMOVE_ITEM: { + String item_name = item->get_text(0); + int data_type = item->get_parent()->get_metadata(0); + edited_theme->clear_theme_item((Theme::DataType)data_type, item_name, edited_item_type); + } break; + case ITEMS_TREE_REMOVE_DATA_TYPE: { + int data_type = item->get_metadata(0); + _remove_data_type_items((Theme::DataType)data_type, edited_item_type); + } break; + } + + _update_edit_item_tree(edited_item_type); +} + +void ThemeItemEditorDialog::_add_class_type_items() { + int selected_idx = edit_add_class_options->get_selected(); + String type_name = edit_add_class_options->get_item_text(selected_idx); + List<StringName> names; + + { + names.clear(); + Theme::get_default()->get_icon_list(type_name, &names); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + edited_theme->set_icon(E->get(), type_name, Ref<Texture2D>()); + } + } + { + names.clear(); + Theme::get_default()->get_stylebox_list(type_name, &names); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + edited_theme->set_stylebox(E->get(), type_name, Ref<StyleBox>()); + } + } + { + names.clear(); + Theme::get_default()->get_font_list(type_name, &names); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + edited_theme->set_font(E->get(), type_name, Ref<Font>()); + } + } + { + names.clear(); + Theme::get_default()->get_font_size_list(type_name, &names); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + edited_theme->set_font_size(E->get(), type_name, Theme::get_default()->get_font_size(E->get(), type_name)); + } + } + { + names.clear(); + Theme::get_default()->get_color_list(type_name, &names); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + edited_theme->set_color(E->get(), type_name, Theme::get_default()->get_color(E->get(), type_name)); + } + } + { + names.clear(); + Theme::get_default()->get_constant_list(type_name, &names); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + edited_theme->set_constant(E->get(), type_name, Theme::get_default()->get_constant(E->get(), type_name)); + } + } + + _update_edit_types(); +} + +void ThemeItemEditorDialog::_add_custom_type() { + edited_theme->add_icon_type(edit_add_custom_value->get_text()); + edited_theme->add_stylebox_type(edit_add_custom_value->get_text()); + edited_theme->add_font_type(edit_add_custom_value->get_text()); + edited_theme->add_font_size_type(edit_add_custom_value->get_text()); + edited_theme->add_color_type(edit_add_custom_value->get_text()); + edited_theme->add_constant_type(edit_add_custom_value->get_text()); + _update_edit_types(); +} + +void ThemeItemEditorDialog::_add_theme_item(Theme::DataType p_data_type, String p_item_name, String p_item_type) { + switch (p_data_type) { + case Theme::DATA_TYPE_ICON: + edited_theme->set_icon(p_item_name, p_item_type, Ref<Texture2D>()); + break; + case Theme::DATA_TYPE_STYLEBOX: + edited_theme->set_stylebox(p_item_name, p_item_type, Ref<StyleBox>()); + break; + case Theme::DATA_TYPE_FONT: + edited_theme->set_font(p_item_name, p_item_type, Ref<Font>()); + break; + case Theme::DATA_TYPE_FONT_SIZE: + edited_theme->set_font_size(p_item_name, p_item_type, -1); + break; + case Theme::DATA_TYPE_COLOR: + edited_theme->set_color(p_item_name, p_item_type, Color()); + break; + case Theme::DATA_TYPE_CONSTANT: + edited_theme->set_constant(p_item_name, p_item_type, 0); + break; + case Theme::DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } +} + +void ThemeItemEditorDialog::_remove_data_type_items(Theme::DataType p_data_type, String p_item_type) { + List<StringName> names; + + edited_theme->get_theme_item_list(p_data_type, p_item_type, &names); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + edited_theme->clear_theme_item(p_data_type, E->get(), p_item_type); + } +} + +void ThemeItemEditorDialog::_remove_class_items() { + List<StringName> names; + + for (int dt = 0; dt < Theme::DATA_TYPE_MAX; dt++) { + Theme::DataType data_type = (Theme::DataType)dt; + + names.clear(); + Theme::get_default()->get_theme_item_list(data_type, edited_item_type, &names); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + if (edited_theme->has_theme_item_nocheck(data_type, E->get(), edited_item_type)) { + edited_theme->clear_theme_item(data_type, E->get(), edited_item_type); + } + } + } + + _update_edit_item_tree(edited_item_type); +} + +void ThemeItemEditorDialog::_remove_custom_items() { + List<StringName> names; + + for (int dt = 0; dt < Theme::DATA_TYPE_MAX; dt++) { + Theme::DataType data_type = (Theme::DataType)dt; + + names.clear(); + edited_theme->get_theme_item_list(data_type, edited_item_type, &names); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + if (!Theme::get_default()->has_theme_item_nocheck(data_type, E->get(), edited_item_type)) { + edited_theme->clear_theme_item(data_type, E->get(), edited_item_type); + } + } + } + + _update_edit_item_tree(edited_item_type); +} + +void ThemeItemEditorDialog::_remove_all_items() { + List<StringName> names; + + for (int dt = 0; dt < Theme::DATA_TYPE_MAX; dt++) { + Theme::DataType data_type = (Theme::DataType)dt; + + names.clear(); + edited_theme->get_theme_item_list(data_type, edited_item_type, &names); + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + edited_theme->clear_theme_item(data_type, E->get(), edited_item_type); + } + } + + _update_edit_item_tree(edited_item_type); +} + +void ThemeItemEditorDialog::_open_add_theme_item_dialog(int p_data_type) { + ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds."); + + item_popup_mode = CREATE_THEME_ITEM; + edit_item_data_type = (Theme::DataType)p_data_type; + + switch (edit_item_data_type) { + case Theme::DATA_TYPE_COLOR: + edit_theme_item_dialog->set_title(TTR("Add Color Item")); + break; + case Theme::DATA_TYPE_CONSTANT: + edit_theme_item_dialog->set_title(TTR("Add Constant Item")); + break; + case Theme::DATA_TYPE_FONT: + edit_theme_item_dialog->set_title(TTR("Add Font Item")); + break; + case Theme::DATA_TYPE_FONT_SIZE: + edit_theme_item_dialog->set_title(TTR("Add Font Size Item")); + break; + case Theme::DATA_TYPE_ICON: + edit_theme_item_dialog->set_title(TTR("Add Icon Item")); + break; + case Theme::DATA_TYPE_STYLEBOX: + edit_theme_item_dialog->set_title(TTR("Add Stylebox Item")); + break; + case Theme::DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } + + edit_theme_item_old_vb->hide(); + theme_item_name->clear(); + edit_theme_item_dialog->popup_centered(Size2(380, 110) * EDSCALE); + theme_item_name->grab_focus(); +} + +void ThemeItemEditorDialog::_open_rename_theme_item_dialog(Theme::DataType p_data_type, String p_item_name) { + ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds."); + + item_popup_mode = RENAME_THEME_ITEM; + edit_item_data_type = p_data_type; + edit_item_old_name = p_item_name; + + switch (edit_item_data_type) { + case Theme::DATA_TYPE_COLOR: + edit_theme_item_dialog->set_title(TTR("Rename Color Item")); + break; + case Theme::DATA_TYPE_CONSTANT: + edit_theme_item_dialog->set_title(TTR("Rename Constant Item")); + break; + case Theme::DATA_TYPE_FONT: + edit_theme_item_dialog->set_title(TTR("Rename Font Item")); + break; + case Theme::DATA_TYPE_FONT_SIZE: + edit_theme_item_dialog->set_title(TTR("Rename Font Size Item")); + break; + case Theme::DATA_TYPE_ICON: + edit_theme_item_dialog->set_title(TTR("Rename Icon Item")); + break; + case Theme::DATA_TYPE_STYLEBOX: + edit_theme_item_dialog->set_title(TTR("Rename Stylebox Item")); + break; + case Theme::DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } + + edit_theme_item_old_vb->show(); + theme_item_old_name->set_text(p_item_name); + theme_item_name->set_text(p_item_name); + edit_theme_item_dialog->popup_centered(Size2(380, 140) * EDSCALE); + theme_item_name->grab_focus(); +} + +void ThemeItemEditorDialog::_confirm_edit_theme_item() { + if (item_popup_mode == CREATE_THEME_ITEM) { + _add_theme_item(edit_item_data_type, theme_item_name->get_text(), edited_item_type); + } else if (item_popup_mode == RENAME_THEME_ITEM) { + edited_theme->rename_theme_item(edit_item_data_type, edit_item_old_name, theme_item_name->get_text(), edited_item_type); + } + + item_popup_mode = ITEM_POPUP_MODE_MAX; + edit_item_data_type = Theme::DATA_TYPE_MAX; + edit_item_old_name = ""; + + _update_edit_item_tree(edited_item_type); +} + +void ThemeItemEditorDialog::_edit_theme_item_gui_input(const Ref<InputEvent> &p_event) { + Ref<InputEventKey> k = p_event; + + if (k.is_valid()) { + if (!k->is_pressed()) { + return; + } + + switch (k->get_keycode()) { + case KEY_KP_ENTER: + case KEY_ENTER: { + _confirm_edit_theme_item(); + edit_theme_item_dialog->hide(); + edit_theme_item_dialog->set_input_as_handled(); + } break; + case KEY_ESCAPE: { + edit_theme_item_dialog->hide(); + edit_theme_item_dialog->set_input_as_handled(); + } break; + } + } +} + +void ThemeItemEditorDialog::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + connect("about_to_popup", callable_mp(this, &ThemeItemEditorDialog::_dialog_about_to_show)); + [[fallthrough]]; + } + case NOTIFICATION_THEME_CHANGED: { + edit_items_add_color->set_icon(get_theme_icon("Color", "EditorIcons")); + edit_items_add_constant->set_icon(get_theme_icon("MemberConstant", "EditorIcons")); + edit_items_add_font->set_icon(get_theme_icon("Font", "EditorIcons")); + edit_items_add_font_size->set_icon(get_theme_icon("FontSize", "EditorIcons")); + edit_items_add_icon->set_icon(get_theme_icon("ImageTexture", "EditorIcons")); + edit_items_add_stylebox->set_icon(get_theme_icon("StyleBoxFlat", "EditorIcons")); + + edit_items_remove_class->set_icon(get_theme_icon("Control", "EditorIcons")); + edit_items_remove_custom->set_icon(get_theme_icon("ThemeRemoveCustomItems", "EditorIcons")); + edit_items_remove_all->set_icon(get_theme_icon("ThemeRemoveAllItems", "EditorIcons")); + } break; + } +} + +void ThemeItemEditorDialog::set_edited_theme(const Ref<Theme> &p_theme) { + edited_theme = p_theme; +} + +ThemeItemEditorDialog::ThemeItemEditorDialog() { + set_title(TTR("Edit Theme Items")); + + HSplitContainer *edit_dialog_hs = memnew(HSplitContainer); + add_child(edit_dialog_hs); + + VBoxContainer *edit_dialog_side_vb = memnew(VBoxContainer); + edit_dialog_side_vb->set_custom_minimum_size(Size2(200.0, 0.0) * EDSCALE); + edit_dialog_hs->add_child(edit_dialog_side_vb); + + Label *edit_type_label = memnew(Label); + edit_type_label->set_text(TTR("Types:")); + edit_dialog_side_vb->add_child(edit_type_label); + + edit_type_list = memnew(ItemList); + edit_type_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + edit_dialog_side_vb->add_child(edit_type_list); + edit_type_list->connect("item_selected", callable_mp(this, &ThemeItemEditorDialog::_edited_type_selected)); + + Label *edit_add_class_label = memnew(Label); + edit_add_class_label->set_text(TTR("Add Type from Class:")); + edit_dialog_side_vb->add_child(edit_add_class_label); + + HBoxContainer *edit_add_class = memnew(HBoxContainer); + edit_dialog_side_vb->add_child(edit_add_class); + edit_add_class_options = memnew(OptionButton); + edit_add_class_options->set_h_size_flags(Control::SIZE_EXPAND_FILL); + edit_add_class->add_child(edit_add_class_options); + Button *edit_add_class_button = memnew(Button); + edit_add_class_button->set_text(TTR("Add")); + edit_add_class->add_child(edit_add_class_button); + edit_add_class_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_class_type_items)); + + Label *edit_add_custom_label = memnew(Label); + edit_add_custom_label->set_text(TTR("Add Custom Type:")); + edit_dialog_side_vb->add_child(edit_add_custom_label); + + HBoxContainer *edit_add_custom = memnew(HBoxContainer); + edit_dialog_side_vb->add_child(edit_add_custom); + edit_add_custom_value = memnew(LineEdit); + edit_add_custom_value->set_h_size_flags(Control::SIZE_EXPAND_FILL); + edit_add_custom->add_child(edit_add_custom_value); + Button *edit_add_custom_button = memnew(Button); + edit_add_custom_button->set_text(TTR("Add")); + edit_add_custom->add_child(edit_add_custom_button); + edit_add_custom_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_custom_type)); + + VBoxContainer *edit_items_vb = memnew(VBoxContainer); + edit_items_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); + edit_dialog_hs->add_child(edit_items_vb); + + HBoxContainer *edit_items_toolbar = memnew(HBoxContainer); + edit_items_vb->add_child(edit_items_toolbar); + + Label *edit_items_toolbar_add_label = memnew(Label); + edit_items_toolbar_add_label->set_text(TTR("Add:")); + edit_items_toolbar->add_child(edit_items_toolbar_add_label); + + edit_items_add_color = memnew(Button); + edit_items_add_color->set_tooltip(TTR("Add Color Item")); + edit_items_add_color->set_flat(true); + edit_items_add_color->set_disabled(true); + edit_items_toolbar->add_child(edit_items_add_color); + edit_items_add_color->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_COLOR)); + + edit_items_add_constant = memnew(Button); + edit_items_add_constant->set_tooltip(TTR("Add Constant Item")); + edit_items_add_constant->set_flat(true); + edit_items_add_constant->set_disabled(true); + edit_items_toolbar->add_child(edit_items_add_constant); + edit_items_add_constant->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_CONSTANT)); + + edit_items_add_font = memnew(Button); + edit_items_add_font->set_tooltip(TTR("Add Font Item")); + edit_items_add_font->set_flat(true); + edit_items_add_font->set_disabled(true); + edit_items_toolbar->add_child(edit_items_add_font); + edit_items_add_font->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_FONT)); + + edit_items_add_font_size = memnew(Button); + edit_items_add_font_size->set_tooltip(TTR("Add Font Size Item")); + edit_items_add_font_size->set_flat(true); + edit_items_add_font_size->set_disabled(true); + edit_items_toolbar->add_child(edit_items_add_font_size); + edit_items_add_font_size->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_FONT_SIZE)); + + edit_items_add_icon = memnew(Button); + edit_items_add_icon->set_tooltip(TTR("Add Icon Item")); + edit_items_add_icon->set_flat(true); + edit_items_add_icon->set_disabled(true); + edit_items_toolbar->add_child(edit_items_add_icon); + edit_items_add_icon->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_ICON)); + + edit_items_add_stylebox = memnew(Button); + edit_items_add_stylebox->set_tooltip(TTR("Add StyleBox Item")); + edit_items_add_stylebox->set_flat(true); + edit_items_add_stylebox->set_disabled(true); + edit_items_toolbar->add_child(edit_items_add_stylebox); + edit_items_add_stylebox->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_STYLEBOX)); + + edit_items_toolbar->add_child(memnew(VSeparator)); + + Label *edit_items_toolbar_remove_label = memnew(Label); + edit_items_toolbar_remove_label->set_text(TTR("Remove:")); + edit_items_toolbar->add_child(edit_items_toolbar_remove_label); + + edit_items_remove_class = memnew(Button); + edit_items_remove_class->set_tooltip(TTR("Remove Class Items")); + edit_items_remove_class->set_flat(true); + edit_items_remove_class->set_disabled(true); + edit_items_toolbar->add_child(edit_items_remove_class); + edit_items_remove_class->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_remove_class_items)); + + edit_items_remove_custom = memnew(Button); + edit_items_remove_custom->set_tooltip(TTR("Remove Custom Items")); + edit_items_remove_custom->set_flat(true); + edit_items_remove_custom->set_disabled(true); + edit_items_toolbar->add_child(edit_items_remove_custom); + edit_items_remove_custom->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_remove_custom_items)); + + edit_items_remove_all = memnew(Button); + edit_items_remove_all->set_tooltip(TTR("Remove All Items")); + edit_items_remove_all->set_flat(true); + edit_items_remove_all->set_disabled(true); + edit_items_toolbar->add_child(edit_items_remove_all); + edit_items_remove_all->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_remove_all_items)); + + edit_items_tree = memnew(Tree); + edit_items_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); + edit_items_tree->set_hide_root(true); + edit_items_tree->set_columns(1); + edit_items_vb->add_child(edit_items_tree); + edit_items_tree->connect("button_pressed", callable_mp(this, &ThemeItemEditorDialog::_item_tree_button_pressed)); + + edit_theme_item_dialog = memnew(ConfirmationDialog); + edit_theme_item_dialog->set_title(TTR("Add Theme Item")); + add_child(edit_theme_item_dialog); + VBoxContainer *edit_theme_item_vb = memnew(VBoxContainer); + edit_theme_item_dialog->add_child(edit_theme_item_vb); + + edit_theme_item_old_vb = memnew(VBoxContainer); + edit_theme_item_vb->add_child(edit_theme_item_old_vb); + Label *edit_theme_item_old = memnew(Label); + edit_theme_item_old->set_text(TTR("Old Name:")); + edit_theme_item_old_vb->add_child(edit_theme_item_old); + theme_item_old_name = memnew(Label); + edit_theme_item_old_vb->add_child(theme_item_old_name); + + Label *edit_theme_item_label = memnew(Label); + edit_theme_item_label->set_text(TTR("Name:")); + edit_theme_item_vb->add_child(edit_theme_item_label); + theme_item_name = memnew(LineEdit); + edit_theme_item_vb->add_child(theme_item_name); + theme_item_name->connect("gui_input", callable_mp(this, &ThemeItemEditorDialog::_edit_theme_item_gui_input)); + edit_theme_item_dialog->connect("confirmed", callable_mp(this, &ThemeItemEditorDialog::_confirm_edit_theme_item)); +} + void ThemeEditor::edit(const Ref<Theme> &p_theme) { theme = p_theme; + theme_edit_dialog->set_edited_theme(p_theme); main_panel->set_theme(p_theme); main_container->set_theme(p_theme); } @@ -58,55 +742,6 @@ void ThemeEditor::_refresh_interval() { _propagate_redraw(main_container); } -void ThemeEditor::_type_menu_cbk(int p_option) { - type_edit->set_text(type_menu->get_popup()->get_item_text(p_option)); -} - -void ThemeEditor::_name_menu_about_to_show() { - String fromtype = type_edit->get_text(); - List<StringName> names; - - if (popup_mode == POPUP_ADD) { - switch (type_select->get_selected()) { - case 0: - Theme::get_default()->get_icon_list(fromtype, &names); - break; - case 1: - Theme::get_default()->get_stylebox_list(fromtype, &names); - break; - case 2: - Theme::get_default()->get_font_list(fromtype, &names); - break; - case 3: - Theme::get_default()->get_font_size_list(fromtype, &names); - break; - case 4: - Theme::get_default()->get_color_list(fromtype, &names); - break; - case 5: - Theme::get_default()->get_constant_list(fromtype, &names); - break; - } - } else if (popup_mode == POPUP_REMOVE) { - theme->get_icon_list(fromtype, &names); - theme->get_stylebox_list(fromtype, &names); - theme->get_font_list(fromtype, &names); - theme->get_font_size_list(fromtype, &names); - theme->get_color_list(fromtype, &names); - theme->get_constant_list(fromtype, &names); - } - - name_menu->get_popup()->clear(); - name_menu->get_popup()->set_size(Size2()); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - name_menu->get_popup()->add_item(E->get()); - } -} - -void ThemeEditor::_name_menu_cbk(int p_option) { - name_edit->set_text(name_menu->get_popup()->get_item_text(p_option)); -} - struct _TECategory { template <class T> struct RefItem { @@ -335,296 +970,71 @@ void ThemeEditor::_save_template_cbk(String fname) { memdelete(file); } -void ThemeEditor::_dialog_cbk() { - switch (popup_mode) { - case POPUP_ADD: { - switch (type_select->get_selected()) { - case 0: - theme->set_icon(name_edit->get_text(), type_edit->get_text(), Ref<Texture2D>()); - break; - case 1: - theme->set_stylebox(name_edit->get_text(), type_edit->get_text(), Ref<StyleBox>()); - break; - case 2: - theme->set_font(name_edit->get_text(), type_edit->get_text(), Ref<Font>()); - break; - case 3: - theme->set_font_size(name_edit->get_text(), type_edit->get_text(), -1); - break; - case 4: - theme->set_color(name_edit->get_text(), type_edit->get_text(), Color()); - break; - case 5: - theme->set_constant(name_edit->get_text(), type_edit->get_text(), 0); - break; - } - - } break; - case POPUP_CLASS_ADD: { - StringName fromtype = type_edit->get_text(); - List<StringName> names; - - { - names.clear(); - Theme::get_default()->get_icon_list(fromtype, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - theme->set_icon(E->get(), fromtype, Ref<Texture2D>()); - } - } - { - names.clear(); - Theme::get_default()->get_stylebox_list(fromtype, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - theme->set_stylebox(E->get(), fromtype, Ref<StyleBox>()); - } - } - { - names.clear(); - Theme::get_default()->get_font_list(fromtype, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - theme->set_font(E->get(), fromtype, Ref<Font>()); - } - } - { - names.clear(); - Theme::get_default()->get_font_size_list(fromtype, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - theme->set_font_size(E->get(), fromtype, Theme::get_default()->get_font_size(E->get(), fromtype)); - } - } - { - names.clear(); - Theme::get_default()->get_color_list(fromtype, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - theme->set_color(E->get(), fromtype, Theme::get_default()->get_color(E->get(), fromtype)); - } - } - { - names.clear(); - Theme::get_default()->get_constant_list(fromtype, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - theme->set_constant(E->get(), fromtype, Theme::get_default()->get_constant(E->get(), fromtype)); - } - } - } break; - case POPUP_REMOVE: { - switch (type_select->get_selected()) { - case 0: - theme->clear_icon(name_edit->get_text(), type_edit->get_text()); - break; - case 1: - theme->clear_stylebox(name_edit->get_text(), type_edit->get_text()); - break; - case 2: - theme->clear_font(name_edit->get_text(), type_edit->get_text()); - break; - case 3: - theme->clear_font_size(name_edit->get_text(), type_edit->get_text()); - break; - case 4: - theme->clear_color(name_edit->get_text(), type_edit->get_text()); - break; - case 5: - theme->clear_constant(name_edit->get_text(), type_edit->get_text()); - break; - } - - } break; - case POPUP_CLASS_REMOVE: { - StringName fromtype = type_edit->get_text(); - List<StringName> names; - - { - names.clear(); - Theme::get_default()->get_icon_list(fromtype, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - theme->clear_icon(E->get(), fromtype); - } - } - { - names.clear(); - Theme::get_default()->get_stylebox_list(fromtype, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - theme->clear_stylebox(E->get(), fromtype); - } - } - { - names.clear(); - Theme::get_default()->get_font_list(fromtype, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - theme->clear_font(E->get(), fromtype); - } - } - { - names.clear(); - Theme::get_default()->get_font_size_list(fromtype, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - theme->clear_font_size(E->get(), fromtype); - } - } - { - names.clear(); - Theme::get_default()->get_color_list(fromtype, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - theme->clear_color(E->get(), fromtype); - } - } - { - names.clear(); - Theme::get_default()->get_constant_list(fromtype, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - theme->clear_constant(E->get(), fromtype); - } - } - - } break; - } -} - -void ThemeEditor::_theme_menu_cbk(int p_option) { - if (p_option == POPUP_CREATE_EMPTY || p_option == POPUP_CREATE_EDITOR_EMPTY || p_option == POPUP_IMPORT_EDITOR_THEME) { - bool import = (p_option == POPUP_IMPORT_EDITOR_THEME); - - Ref<Theme> base_theme; - - if (p_option == POPUP_CREATE_EMPTY) { - base_theme = Theme::get_default(); - } else { - base_theme = EditorNode::get_singleton()->get_theme_base()->get_theme(); - } - - { - List<StringName> types; - base_theme->get_type_list(&types); - - for (List<StringName>::Element *T = types.front(); T; T = T->next()) { - StringName type = T->get(); - - List<StringName> icons; - base_theme->get_icon_list(type, &icons); - - for (List<StringName>::Element *E = icons.front(); E; E = E->next()) { - theme->set_icon(E->get(), type, import ? base_theme->get_icon(E->get(), type) : Ref<Texture2D>()); - } - - List<StringName> styleboxs; - base_theme->get_stylebox_list(type, &styleboxs); - - for (List<StringName>::Element *E = styleboxs.front(); E; E = E->next()) { - theme->set_stylebox(E->get(), type, import ? base_theme->get_stylebox(E->get(), type) : Ref<StyleBox>()); - } - - List<StringName> fonts; - base_theme->get_font_list(type, &fonts); - - for (List<StringName>::Element *E = fonts.front(); E; E = E->next()) { - theme->set_font(E->get(), type, Ref<Font>()); - } - - List<StringName> font_sizes; - base_theme->get_font_size_list(type, &font_sizes); - - for (List<StringName>::Element *E = font_sizes.front(); E; E = E->next()) { - theme->set_font_size(E->get(), type, base_theme->get_font_size(E->get(), type)); - } - - List<StringName> colors; - base_theme->get_color_list(type, &colors); - - for (List<StringName>::Element *E = colors.front(); E; E = E->next()) { - theme->set_color(E->get(), type, import ? base_theme->get_color(E->get(), type) : Color()); - } - - List<StringName> constants; - base_theme->get_constant_list(type, &constants); - - for (List<StringName>::Element *E = constants.front(); E; E = E->next()) { - theme->set_constant(E->get(), type, base_theme->get_constant(E->get(), type)); - } - } - } - return; - } +void ThemeEditor::_theme_create_menu_cbk(int p_option) { + bool import = (p_option == POPUP_IMPORT_EDITOR_THEME); Ref<Theme> base_theme; - name_select_label->show(); - name_hbc->show(); - type_select_label->show(); - type_select->show(); - - if (p_option == POPUP_ADD) { // Add. - - add_del_dialog->set_title(TTR("Add Item")); - add_del_dialog->get_ok_button()->set_text(TTR("Add")); - add_del_dialog->popup_centered(Size2(490, 85) * EDSCALE); - + if (p_option == POPUP_CREATE_EMPTY) { base_theme = Theme::get_default(); + } else { + base_theme = EditorNode::get_singleton()->get_theme_base()->get_theme(); + } - } else if (p_option == POPUP_CLASS_ADD) { // Add. - - add_del_dialog->set_title(TTR("Add All Items")); - add_del_dialog->get_ok_button()->set_text(TTR("Add All")); - add_del_dialog->popup_centered(Size2(240, 85) * EDSCALE); - - base_theme = Theme::get_default(); + { + List<StringName> types; + base_theme->get_type_list(&types); - name_select_label->hide(); - name_hbc->hide(); - type_select_label->hide(); - type_select->hide(); + for (List<StringName>::Element *T = types.front(); T; T = T->next()) { + StringName type = T->get(); - } else if (p_option == POPUP_REMOVE) { - add_del_dialog->set_title(TTR("Remove Item")); - add_del_dialog->get_ok_button()->set_text(TTR("Remove")); - add_del_dialog->popup_centered(Size2(490, 85) * EDSCALE); + List<StringName> icons; + base_theme->get_icon_list(type, &icons); - base_theme = theme; + for (List<StringName>::Element *E = icons.front(); E; E = E->next()) { + theme->set_icon(E->get(), type, import ? base_theme->get_icon(E->get(), type) : Ref<Texture2D>()); + } - } else if (p_option == POPUP_CLASS_REMOVE) { - add_del_dialog->set_title(TTR("Remove All Items")); - add_del_dialog->get_ok_button()->set_text(TTR("Remove All")); - add_del_dialog->popup_centered(Size2(240, 85) * EDSCALE); + List<StringName> styleboxs; + base_theme->get_stylebox_list(type, &styleboxs); - base_theme = Theme::get_default(); + for (List<StringName>::Element *E = styleboxs.front(); E; E = E->next()) { + theme->set_stylebox(E->get(), type, import ? base_theme->get_stylebox(E->get(), type) : Ref<StyleBox>()); + } - name_select_label->hide(); - name_hbc->hide(); - type_select_label->hide(); - type_select->hide(); - } - popup_mode = p_option; + List<StringName> fonts; + base_theme->get_font_list(type, &fonts); - ERR_FAIL_COND(theme.is_null()); + for (List<StringName>::Element *E = fonts.front(); E; E = E->next()) { + theme->set_font(E->get(), type, Ref<Font>()); + } - List<StringName> types; - base_theme->get_type_list(&types); + List<StringName> font_sizes; + base_theme->get_font_size_list(type, &font_sizes); - type_menu->get_popup()->clear(); + for (List<StringName>::Element *E = font_sizes.front(); E; E = E->next()) { + theme->set_font_size(E->get(), type, base_theme->get_font_size(E->get(), type)); + } - if (p_option == 0 || p_option == 1) { // Add. + List<StringName> colors; + base_theme->get_color_list(type, &colors); - List<StringName> new_types; - theme->get_type_list(&new_types); - for (List<StringName>::Element *F = new_types.front(); F; F = F->next()) { - bool found = false; - for (List<StringName>::Element *E = types.front(); E; E = E->next()) { - if (E->get() == F->get()) { - found = true; - break; - } + for (List<StringName>::Element *E = colors.front(); E; E = E->next()) { + theme->set_color(E->get(), type, import ? base_theme->get_color(E->get(), type) : Color()); } - if (!found) { - types.push_back(F->get()); + List<StringName> constants; + base_theme->get_constant_list(type, &constants); + + for (List<StringName>::Element *E = constants.front(); E; E = E->next()) { + theme->set_constant(E->get(), type, base_theme->get_constant(E->get(), type)); } } } +} - types.sort_custom<StringName::AlphCompare>(); - for (List<StringName>::Element *E = types.front(); E; E = E->next()) { - type_menu->get_popup()->add_item(E->get()); - } +void ThemeEditor::_theme_edit_button_cbk() { + theme_edit_dialog->popup_centered(Size2(800, 640) * EDSCALE); } void ThemeEditor::_notification(int p_what) { @@ -636,9 +1046,6 @@ void ThemeEditor::_notification(int p_what) { _refresh_interval(); } } break; - case NOTIFICATION_THEME_CHANGED: { - theme_menu->set_icon(get_theme_icon("Theme", "EditorIcons")); - } break; } } @@ -646,27 +1053,28 @@ void ThemeEditor::_bind_methods() { } ThemeEditor::ThemeEditor() { - time_left = 0; - HBoxContainer *top_menu = memnew(HBoxContainer); add_child(top_menu); top_menu->add_child(memnew(Label(TTR("Preview:")))); top_menu->add_spacer(false); - theme_menu = memnew(MenuButton); - theme_menu->set_text(TTR("Edit Theme")); - theme_menu->set_tooltip(TTR("Theme editing menu.")); - theme_menu->get_popup()->add_item(TTR("Add Item"), POPUP_ADD); - theme_menu->get_popup()->add_item(TTR("Add Class Items"), POPUP_CLASS_ADD); - theme_menu->get_popup()->add_item(TTR("Remove Item"), POPUP_REMOVE); - theme_menu->get_popup()->add_item(TTR("Remove Class Items"), POPUP_CLASS_REMOVE); - theme_menu->get_popup()->add_separator(); - theme_menu->get_popup()->add_item(TTR("Create Empty Template"), POPUP_CREATE_EMPTY); - theme_menu->get_popup()->add_item(TTR("Create Empty Editor Template"), POPUP_CREATE_EDITOR_EMPTY); - theme_menu->get_popup()->add_item(TTR("Create From Current Editor Theme"), POPUP_IMPORT_EDITOR_THEME); - top_menu->add_child(theme_menu); - theme_menu->get_popup()->connect("id_pressed", callable_mp(this, &ThemeEditor::_theme_menu_cbk)); + theme_create_menu = memnew(MenuButton); + theme_create_menu->set_text(TTR("Create Theme...")); + theme_create_menu->set_tooltip(TTR("Create a new Theme.")); + theme_create_menu->get_popup()->add_item(TTR("Empty Template"), POPUP_CREATE_EMPTY); + theme_create_menu->get_popup()->add_separator(); + theme_create_menu->get_popup()->add_item(TTR("Empty Editor Template"), POPUP_CREATE_EDITOR_EMPTY); + theme_create_menu->get_popup()->add_item(TTR("From Current Editor Theme"), POPUP_IMPORT_EDITOR_THEME); + top_menu->add_child(theme_create_menu); + theme_create_menu->get_popup()->connect("id_pressed", callable_mp(this, &ThemeEditor::_theme_create_menu_cbk)); + + theme_edit_button = memnew(Button); + theme_edit_button->set_text(TTR("Edit Theme Items")); + theme_edit_button->set_tooltip(TTR("Customize Theme items.")); + theme_edit_button->set_flat(true); + theme_edit_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_edit_button_cbk)); + top_menu->add_child(theme_edit_button); ScrollContainer *scroll = memnew(ScrollContainer); add_child(scroll); @@ -849,66 +1257,9 @@ ThemeEditor::ThemeEditor() { main_hb->add_theme_constant_override("separation", 20 * EDSCALE); - //////// - - add_del_dialog = memnew(ConfirmationDialog); - add_del_dialog->hide(); - add_child(add_del_dialog); - - VBoxContainer *dialog_vbc = memnew(VBoxContainer); - add_del_dialog->add_child(dialog_vbc); - - Label *l = memnew(Label); - l->set_text(TTR("Type:")); - dialog_vbc->add_child(l); - - type_hbc = memnew(HBoxContainer); - dialog_vbc->add_child(type_hbc); - - type_edit = memnew(LineEdit); - type_edit->set_h_size_flags(SIZE_EXPAND_FILL); - type_hbc->add_child(type_edit); - type_menu = memnew(MenuButton); - type_menu->set_flat(false); - type_menu->set_text("..."); - type_hbc->add_child(type_menu); - - type_menu->get_popup()->connect("id_pressed", callable_mp(this, &ThemeEditor::_type_menu_cbk)); - - l = memnew(Label); - l->set_text(TTR("Name:")); - dialog_vbc->add_child(l); - name_select_label = l; - - name_hbc = memnew(HBoxContainer); - dialog_vbc->add_child(name_hbc); - - name_edit = memnew(LineEdit); - name_edit->set_h_size_flags(SIZE_EXPAND_FILL); - name_hbc->add_child(name_edit); - name_menu = memnew(MenuButton); - type_menu->set_flat(false); - name_menu->set_text("..."); - name_hbc->add_child(name_menu); - - name_menu->get_popup()->connect("about_to_popup", callable_mp(this, &ThemeEditor::_name_menu_about_to_show)); - name_menu->get_popup()->connect("id_pressed", callable_mp(this, &ThemeEditor::_name_menu_cbk)); - - type_select_label = memnew(Label); - type_select_label->set_text(TTR("Data Type:")); - dialog_vbc->add_child(type_select_label); - - type_select = memnew(OptionButton); - type_select->add_item(TTR("Icon")); - type_select->add_item(TTR("Style")); - type_select->add_item(TTR("Font")); - type_select->add_item(TTR("Font Size")); - type_select->add_item(TTR("Color")); - type_select->add_item(TTR("Constant")); - - dialog_vbc->add_child(type_select); - - add_del_dialog->get_ok_button()->connect("pressed", callable_mp(this, &ThemeEditor::_dialog_cbk)); + theme_edit_dialog = memnew(ThemeItemEditorDialog); + theme_edit_dialog->hide(); + add_child(theme_edit_dialog); file_dialog = memnew(EditorFileDialog); file_dialog->add_filter("*.theme ; " + TTR("Theme File")); diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h index ab199f8e51..0a840aecd7 100644 --- a/editor/plugins/theme_editor_plugin.h +++ b/editor/plugins/theme_editor_plugin.h @@ -41,6 +41,77 @@ #include "editor/editor_node.h" +class ThemeItemEditorDialog : public AcceptDialog { + GDCLASS(ThemeItemEditorDialog, AcceptDialog); + + Ref<Theme> edited_theme; + + ItemList *edit_type_list; + OptionButton *edit_add_class_options; + LineEdit *edit_add_custom_value; + String edited_item_type; + + Button *edit_items_add_color; + Button *edit_items_add_constant; + Button *edit_items_add_font; + Button *edit_items_add_font_size; + Button *edit_items_add_icon; + Button *edit_items_add_stylebox; + Button *edit_items_remove_class; + Button *edit_items_remove_custom; + Button *edit_items_remove_all; + Tree *edit_items_tree; + + enum ItemsTreeAction { + ITEMS_TREE_RENAME_ITEM, + ITEMS_TREE_REMOVE_ITEM, + ITEMS_TREE_REMOVE_DATA_TYPE, + }; + + ConfirmationDialog *edit_theme_item_dialog; + VBoxContainer *edit_theme_item_old_vb; + Label *theme_item_old_name; + LineEdit *theme_item_name; + + enum ItemPopupMode { + CREATE_THEME_ITEM, + RENAME_THEME_ITEM, + ITEM_POPUP_MODE_MAX + }; + + ItemPopupMode item_popup_mode = ITEM_POPUP_MODE_MAX; + String edit_item_old_name; + Theme::DataType edit_item_data_type = Theme::DATA_TYPE_MAX; + + void _dialog_about_to_show(); + void _update_edit_types(); + void _edited_type_selected(int p_item_idx); + + void _update_edit_item_tree(String p_item_type); + void _item_tree_button_pressed(Object *p_item, int p_column, int p_id); + + void _add_class_type_items(); + void _add_custom_type(); + void _add_theme_item(Theme::DataType p_data_type, String p_item_name, String p_item_type); + void _remove_data_type_items(Theme::DataType p_data_type, String p_item_type); + void _remove_class_items(); + void _remove_custom_items(); + void _remove_all_items(); + + void _open_add_theme_item_dialog(int p_data_type); + void _open_rename_theme_item_dialog(Theme::DataType p_data_type, String p_item_name); + void _confirm_edit_theme_item(); + void _edit_theme_item_gui_input(const Ref<InputEvent> &p_event); + +protected: + void _notification(int p_what); + +public: + void set_edited_theme(const Ref<Theme> &p_theme); + + ThemeItemEditorDialog(); +}; + class ThemeEditor : public VBoxContainer { GDCLASS(ThemeEditor, VBoxContainer); @@ -50,40 +121,23 @@ class ThemeEditor : public VBoxContainer { EditorFileDialog *file_dialog; - double time_left; - - MenuButton *theme_menu; - ConfirmationDialog *add_del_dialog; - HBoxContainer *type_hbc; - MenuButton *type_menu; - LineEdit *type_edit; - HBoxContainer *name_hbc; - MenuButton *name_menu; - LineEdit *name_edit; - OptionButton *type_select; - Label *type_select_label; - Label *name_select_label; - - enum PopupMode { - POPUP_ADD, - POPUP_CLASS_ADD, - POPUP_REMOVE, - POPUP_CLASS_REMOVE, + double time_left = 0; + + Button *theme_edit_button; + MenuButton *theme_create_menu; + ThemeItemEditorDialog *theme_edit_dialog; + + enum CreatePopupMode { POPUP_CREATE_EMPTY, POPUP_CREATE_EDITOR_EMPTY, - POPUP_IMPORT_EDITOR_THEME + POPUP_IMPORT_EDITOR_THEME, }; - int popup_mode; - Tree *test_tree; void _save_template_cbk(String fname); - void _dialog_cbk(); - void _type_menu_cbk(int p_option); - void _name_menu_about_to_show(); - void _name_menu_cbk(int p_option); - void _theme_menu_cbk(int p_option); + void _theme_edit_button_cbk(); + void _theme_create_menu_cbk(int p_option); void _propagate_redraw(Control *p_at); void _refresh_interval(); diff --git a/main/main.cpp b/main/main.cpp index bf7b88bdc9..bb16c49983 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1253,6 +1253,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } GLOBAL_DEF("internationalization/rendering/force_right_to_left_layout_direction", false); + GLOBAL_DEF("internationalization/locale/include_text_server_data", false); if (!force_lowdpi) { OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", false); diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index 93642f2d5c..e601884486 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -824,10 +824,10 @@ bool BulletPhysicsServer3D::body_is_omitting_force_integration(RID p_body) const return body->get_omit_forces_integration(); } -void BulletPhysicsServer3D::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) { +void BulletPhysicsServer3D::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); - body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method, p_udata); + body->set_force_integration_callback(p_callable, p_udata); } void BulletPhysicsServer3D::body_set_ray_pickable(RID p_body, bool p_enable) { diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index 856ff74963..de0379c873 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -246,7 +246,7 @@ public: virtual void body_set_omit_force_integration(RID p_body, bool p_omit) override; virtual bool body_is_omitting_force_integration(RID p_body) const override; - virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) override; + virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) override; virtual void body_set_ray_pickable(RID p_body, bool p_enable) override; diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index 433bff8c38..675da1a597 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -346,16 +346,17 @@ void RigidBodyBullet::dispatch_callbacks() { Variant variantBodyDirect = bodyDirect; - Object *obj = ObjectDB::get_instance(force_integration_callback->id); + Object *obj = force_integration_callback->callable.get_object(); if (!obj) { // Remove integration callback - set_force_integration_callback(ObjectID(), StringName()); + set_force_integration_callback(Callable()); } else { const Variant *vp[2] = { &variantBodyDirect, &force_integration_callback->udata }; Callable::CallError responseCallError; int argc = (force_integration_callback->udata.get_type() == Variant::NIL) ? 1 : 2; - obj->call(force_integration_callback->method, vp, argc, responseCallError); + Variant rv; + force_integration_callback->callable.call(vp, argc, rv, responseCallError); } } @@ -371,16 +372,15 @@ void RigidBodyBullet::dispatch_callbacks() { previousActiveState = btBody->isActive(); } -void RigidBodyBullet::set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata) { +void RigidBodyBullet::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) { if (force_integration_callback) { memdelete(force_integration_callback); force_integration_callback = nullptr; } - if (p_id.is_valid()) { + if (p_callable.get_object()) { force_integration_callback = memnew(ForceIntegrationCallback); - force_integration_callback->id = p_id; - force_integration_callback->method = p_method; + force_integration_callback->callable = p_callable; force_integration_callback->udata = p_udata; } } diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h index a4be7f9e07..843ff4a7af 100644 --- a/modules/bullet/rigid_body_bullet.h +++ b/modules/bullet/rigid_body_bullet.h @@ -154,8 +154,7 @@ public: }; struct ForceIntegrationCallback { - ObjectID id; - StringName method; + Callable callable; Variant udata; }; @@ -240,7 +239,7 @@ public: virtual void set_space(SpaceBullet *p_space); virtual void dispatch_callbacks(); - void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant()); + void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant()); void scratch_space_override_modificator(); virtual void on_collision_filters_change(); diff --git a/modules/fbx/SCsub b/modules/fbx/SCsub index 84220a66fa..0311fddfee 100644 --- a/modules/fbx/SCsub +++ b/modules/fbx/SCsub @@ -8,6 +8,9 @@ env_fbx = env_modules.Clone() # Make includes relative to the folder path specified here so our includes are clean env_fbx.Prepend(CPPPATH=["#modules/fbx/"]) +if env["builtin_zlib"]: + env_fbx.Prepend(CPPPATH=["#thirdparty/zlib/"]) + # Godot's own source files env_fbx.add_source_files(env.modules_sources, "tools/*.cpp") env_fbx.add_source_files(env.modules_sources, "data/*.cpp") diff --git a/modules/fbx/fbx_parser/FBXParser.cpp b/modules/fbx/fbx_parser/FBXParser.cpp index 82d532e0b8..2a76c3f67c 100644 --- a/modules/fbx/fbx_parser/FBXParser.cpp +++ b/modules/fbx/fbx_parser/FBXParser.cpp @@ -74,8 +74,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the FBX parser and the rudimentary DOM that we use */ -#include "thirdparty/zlib/zlib.h" #include <stdlib.h> /* strtol */ +#include <zlib.h> #include "ByteSwapper.h" #include "FBXParseTools.h" diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp index 9f2373bf56..030633274c 100644 --- a/modules/gdscript/language_server/gdscript_text_document.cpp +++ b/modules/gdscript/language_server/gdscript_text_document.cpp @@ -400,6 +400,7 @@ GDScriptTextDocument::~GDScriptTextDocument() { void GDScriptTextDocument::sync_script_content(const String &p_path, const String &p_content) { String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(p_path); GDScriptLanguageProtocol::get_singleton()->get_workspace()->parse_script(path, p_content); + EditorFileSystem::get_singleton()->update_file(path); } void GDScriptTextDocument::show_native_symbol_in_editor(const String &p_symbol_id) { diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub index e7863f88a3..a55b6dc283 100644 --- a/modules/text_server_adv/SCsub +++ b/modules/text_server_adv/SCsub @@ -448,7 +448,7 @@ if env["builtin_icu"]: ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - icu_data_name = "icudt68l.dat" + icu_data_name = "icudt69l.dat" if env_icu["tools"]: env_icu.Depends("#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/" + icu_data_name) diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp index e288c16777..705891713f 100644 --- a/platform/android/file_access_android.cpp +++ b/platform/android/file_access_android.cpp @@ -114,7 +114,7 @@ uint8_t FileAccessAndroid::get_8() const { } int FileAccessAndroid::get_buffer(uint8_t *p_dst, int p_length) const { - ERR_FAIL_COND_V(!p_dst, -1); + ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); ERR_FAIL_COND_V(p_length < 0, -1); off_t r = AAsset_read(a, p_dst, p_length); diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index a18687afed..3f8201b559 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -35,6 +35,8 @@ #include "servers/navigation_server_2d.h" void NavigationAgent2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_rid"), &NavigationAgent2D::get_rid); + ClassDB::bind_method(D_METHOD("set_target_desired_distance", "desired_distance"), &NavigationAgent2D::set_target_desired_distance); ClassDB::bind_method(D_METHOD("get_target_desired_distance"), &NavigationAgent2D::get_target_desired_distance); @@ -88,9 +90,11 @@ void NavigationAgent2D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { agent_parent = Object::cast_to<Node2D>(get_parent()); - - NavigationServer2D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done"); - + if (agent_parent != nullptr) { + // place agent on navigation map first or else the RVO agent callback creation fails silently later + NavigationServer2D::get_singleton()->agent_set_map(get_rid(), agent_parent->get_world_2d()->get_navigation_map()); + NavigationServer2D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done"); + } set_physics_process_internal(true); } break; case NOTIFICATION_EXIT_TREE: { diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 69d146f2ea..3f2f6d6b1c 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -271,6 +271,7 @@ bool RigidBody2D::_test_motion(const Vector2 &p_motion, bool p_infinite_inertia, void RigidBody2D::_direct_state_changed(Object *p_state) { #ifdef DEBUG_ENABLED state = Object::cast_to<PhysicsDirectBodyState2D>(p_state); + ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState2D object as argument"); #else state = (PhysicsDirectBodyState2D *)p_state; //trust it #endif @@ -729,8 +730,6 @@ void RigidBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("test_motion", "motion", "infinite_inertia", "margin", "result"), &RigidBody2D::_test_motion, DEFVAL(true), DEFVAL(0.08), DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("_direct_state_changed"), &RigidBody2D::_direct_state_changed); - ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody2D::get_colliding_bodies); BIND_VMETHOD(MethodInfo("_integrate_forces", PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectBodyState2D"))); @@ -774,7 +773,7 @@ void RigidBody2D::_bind_methods() { RigidBody2D::RigidBody2D() : PhysicsBody2D(PhysicsServer2D::BODY_MODE_RIGID) { - PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &RigidBody2D::_direct_state_changed)); } RigidBody2D::~RigidBody2D() { @@ -1080,11 +1079,11 @@ void KinematicBody2D::set_sync_to_physics(bool p_enable) { } if (p_enable) { - PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &KinematicBody2D::_direct_state_changed)); set_only_update_transform_changes(true); set_notify_local_transform(true); } else { - PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), nullptr, ""); + PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), Callable()); set_only_update_transform_changes(false); set_notify_local_transform(false); } @@ -1100,6 +1099,7 @@ void KinematicBody2D::_direct_state_changed(Object *p_state) { } PhysicsDirectBodyState2D *state = Object::cast_to<PhysicsDirectBodyState2D>(p_state); + ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState2D object as argument"); last_valid_transform = state->get_transform(); set_notify_local_transform(false); @@ -1153,8 +1153,6 @@ void KinematicBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &KinematicBody2D::set_sync_to_physics); ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &KinematicBody2D::is_sync_to_physics_enabled); - ClassDB::bind_method(D_METHOD("_direct_state_changed"), &KinematicBody2D::_direct_state_changed); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "motion/sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled"); } diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index 7346f243ba..4f5e56e227 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -34,6 +34,8 @@ #include "servers/navigation_server_3d.h" void NavigationAgent3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_rid"), &NavigationAgent3D::get_rid); + ClassDB::bind_method(D_METHOD("set_target_desired_distance", "desired_distance"), &NavigationAgent3D::set_target_desired_distance); ClassDB::bind_method(D_METHOD("get_target_desired_distance"), &NavigationAgent3D::get_target_desired_distance); @@ -95,8 +97,11 @@ void NavigationAgent3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { agent_parent = Object::cast_to<Node3D>(get_parent()); - - NavigationServer3D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done"); + if (agent_parent != nullptr) { + // place agent on navigation map first or else the RVO agent callback creation fails silently later + NavigationServer3D::get_singleton()->agent_set_map(get_rid(), agent_parent->get_world_3d()->get_navigation_map()); + NavigationServer3D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done"); + } set_physics_process_internal(true); } break; case NOTIFICATION_EXIT_TREE: { diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index 2476cc3471..93d3e946fd 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -274,6 +274,7 @@ struct _RigidBodyInOut { void RigidBody3D::_direct_state_changed(Object *p_state) { #ifdef DEBUG_ENABLED state = Object::cast_to<PhysicsDirectBodyState3D>(p_state); + ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState3D object as argument"); #else state = (PhysicsDirectBodyState3D *)p_state; //trust it #endif @@ -712,8 +713,6 @@ void RigidBody3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody3D::set_can_sleep); ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody3D::is_able_to_sleep); - ClassDB::bind_method(D_METHOD("_direct_state_changed"), &RigidBody3D::_direct_state_changed); - ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &RigidBody3D::set_axis_lock); ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &RigidBody3D::get_axis_lock); @@ -759,7 +758,7 @@ void RigidBody3D::_bind_methods() { RigidBody3D::RigidBody3D() : PhysicsBody3D(PhysicsServer3D::BODY_MODE_RIGID) { - PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &RigidBody3D::_direct_state_changed)); } RigidBody3D::~RigidBody3D() { @@ -1093,8 +1092,6 @@ void KinematicBody3D::_notification(int p_what) { } void KinematicBody3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("_direct_state_changed"), &KinematicBody3D::_direct_state_changed); - ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody3D::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false)); ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody3D::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((real_t)45.0)), DEFVAL(true)); ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody3D::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((real_t)45.0)), DEFVAL(true)); @@ -1127,6 +1124,7 @@ void KinematicBody3D::_bind_methods() { void KinematicBody3D::_direct_state_changed(Object *p_state) { #ifdef DEBUG_ENABLED PhysicsDirectBodyState3D *state = Object::cast_to<PhysicsDirectBodyState3D>(p_state); + ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState3D object as argument"); #else PhysicsDirectBodyState3D *state = (PhysicsDirectBodyState3D *)p_state; //trust it #endif @@ -1138,7 +1136,7 @@ void KinematicBody3D::_direct_state_changed(Object *p_state) { KinematicBody3D::KinematicBody3D() : PhysicsBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) { set_safe_margin(0.001); - PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &KinematicBody3D::_direct_state_changed)); } KinematicBody3D::~KinematicBody3D() { @@ -1977,6 +1975,7 @@ void PhysicalBone3D::_direct_state_changed(Object *p_state) { #ifdef DEBUG_ENABLED state = Object::cast_to<PhysicsDirectBodyState3D>(p_state); + ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState3D object as argument"); #else state = (PhysicsDirectBodyState3D *)p_state; //trust it #endif @@ -1999,8 +1998,6 @@ void PhysicalBone3D::_bind_methods() { ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicalBone3D::apply_central_impulse); ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &PhysicalBone3D::apply_impulse, Vector3()); - ClassDB::bind_method(D_METHOD("_direct_state_changed"), &PhysicalBone3D::_direct_state_changed); - ClassDB::bind_method(D_METHOD("set_joint_type", "joint_type"), &PhysicalBone3D::set_joint_type); ClassDB::bind_method(D_METHOD("get_joint_type"), &PhysicalBone3D::get_joint_type); @@ -2479,7 +2476,7 @@ void PhysicalBone3D::_start_physics_simulation() { PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_RIGID); PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); - PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &PhysicalBone3D::_direct_state_changed)); set_as_top_level(true); _internal_simulate_physics = true; } @@ -2498,7 +2495,7 @@ void PhysicalBone3D::_stop_physics_simulation() { PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), 0); } if (_internal_simulate_physics) { - PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), nullptr, ""); + PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), Callable()); parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false); set_as_top_level(false); _internal_simulate_physics = false; diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp index edd58347f0..9493f686c4 100644 --- a/scene/3d/vehicle_body_3d.cpp +++ b/scene/3d/vehicle_body_3d.cpp @@ -803,6 +803,7 @@ void VehicleBody3D::_direct_state_changed(Object *p_state) { RigidBody3D::_direct_state_changed(p_state); state = Object::cast_to<PhysicsDirectBodyState3D>(p_state); + ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState3D object as argument"); real_t step = state->get_step(); @@ -922,7 +923,7 @@ void VehicleBody3D::_bind_methods() { VehicleBody3D::VehicleBody3D() { exclude.insert(get_rid()); - //PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + //PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &VehicleBody3D::_direct_state_changed)); set_mass(40); } diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 66f3a2ebde..a62c4ff770 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -1349,6 +1349,8 @@ SceneTree::SceneTree() { GLOBAL_DEF("debug/shapes/collision/draw_2d_outlines", true); + Math::randomize(); + // Create with mainloop. root = memnew(Window); diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index 036d11574c..e8b203417e 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -508,6 +508,10 @@ bool Theme::has_icon(const StringName &p_name, const StringName &p_node_type) co return (icon_map.has(p_node_type) && icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid()); } +bool Theme::has_icon_nocheck(const StringName &p_name, const StringName &p_node_type) const { + return (icon_map.has(p_node_type) && icon_map[p_node_type].has(p_name)); +} + void Theme::rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { ERR_FAIL_COND_MSG(!icon_map.has(p_node_type), "Cannot rename the icon '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); ERR_FAIL_COND_MSG(icon_map[p_node_type].has(p_name), "Cannot rename the icon '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); @@ -592,6 +596,10 @@ bool Theme::has_stylebox(const StringName &p_name, const StringName &p_node_type return (style_map.has(p_node_type) && style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid()); } +bool Theme::has_stylebox_nocheck(const StringName &p_name, const StringName &p_node_type) const { + return (style_map.has(p_node_type) && style_map[p_node_type].has(p_name)); +} + void Theme::rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { ERR_FAIL_COND_MSG(!style_map.has(p_node_type), "Cannot rename the stylebox '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); ERR_FAIL_COND_MSG(style_map[p_node_type].has(p_name), "Cannot rename the stylebox '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); @@ -678,6 +686,10 @@ bool Theme::has_font(const StringName &p_name, const StringName &p_node_type) co return ((font_map.has(p_node_type) && font_map[p_node_type].has(p_name) && font_map[p_node_type][p_name].is_valid()) || default_theme_font.is_valid()); } +bool Theme::has_font_nocheck(const StringName &p_name, const StringName &p_node_type) const { + return (font_map.has(p_node_type) && font_map[p_node_type].has(p_name)); +} + void Theme::rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { ERR_FAIL_COND_MSG(!font_map.has(p_node_type), "Cannot rename the font '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); ERR_FAIL_COND_MSG(font_map[p_node_type].has(p_name), "Cannot rename the font '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); @@ -755,6 +767,10 @@ bool Theme::has_font_size(const StringName &p_name, const StringName &p_node_typ return ((font_size_map.has(p_node_type) && font_size_map[p_node_type].has(p_name) && (font_size_map[p_node_type][p_name] > 0)) || (default_theme_font_size > 0)); } +bool Theme::has_font_size_nocheck(const StringName &p_name, const StringName &p_node_type) const { + return (font_size_map.has(p_node_type) && font_size_map[p_node_type].has(p_name)); +} + void Theme::rename_font_size(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { ERR_FAIL_COND_MSG(!font_size_map.has(p_node_type), "Cannot rename the font size '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); ERR_FAIL_COND_MSG(font_size_map[p_node_type].has(p_name), "Cannot rename the font size '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); @@ -826,6 +842,10 @@ bool Theme::has_color(const StringName &p_name, const StringName &p_node_type) c return (color_map.has(p_node_type) && color_map[p_node_type].has(p_name)); } +bool Theme::has_color_nocheck(const StringName &p_name, const StringName &p_node_type) const { + return (color_map.has(p_node_type) && color_map[p_node_type].has(p_name)); +} + void Theme::rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { ERR_FAIL_COND_MSG(!color_map.has(p_node_type), "Cannot rename the color '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); ERR_FAIL_COND_MSG(color_map[p_node_type].has(p_name), "Cannot rename the color '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); @@ -896,6 +916,10 @@ bool Theme::has_constant(const StringName &p_name, const StringName &p_node_type return (constant_map.has(p_node_type) && constant_map[p_node_type].has(p_name)); } +bool Theme::has_constant_nocheck(const StringName &p_name, const StringName &p_node_type) const { + return (constant_map.has(p_node_type) && constant_map[p_node_type].has(p_name)); +} + void Theme::rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { ERR_FAIL_COND_MSG(!constant_map.has(p_node_type), "Cannot rename the constant '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); ERR_FAIL_COND_MSG(constant_map[p_node_type].has(p_name), "Cannot rename the constant '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); @@ -1029,6 +1053,27 @@ bool Theme::has_theme_item(DataType p_data_type, const StringName &p_name, const return false; } +bool Theme::has_theme_item_nocheck(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const { + switch (p_data_type) { + case DATA_TYPE_COLOR: + return has_color_nocheck(p_name, p_node_type); + case DATA_TYPE_CONSTANT: + return has_constant_nocheck(p_name, p_node_type); + case DATA_TYPE_FONT: + return has_font_nocheck(p_name, p_node_type); + case DATA_TYPE_FONT_SIZE: + return has_font_size_nocheck(p_name, p_node_type); + case DATA_TYPE_ICON: + return has_icon_nocheck(p_name, p_node_type); + case DATA_TYPE_STYLEBOX: + return has_stylebox_nocheck(p_name, p_node_type); + case DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } + + return false; +} + void Theme::rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { switch (p_data_type) { case DATA_TYPE_COLOR: diff --git a/scene/resources/theme.h b/scene/resources/theme.h index eb918fac69..7e887b6343 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -119,6 +119,7 @@ public: void set_icon(const StringName &p_name, const StringName &p_node_type, const Ref<Texture2D> &p_icon); Ref<Texture2D> get_icon(const StringName &p_name, const StringName &p_node_type) const; bool has_icon(const StringName &p_name, const StringName &p_node_type) const; + bool has_icon_nocheck(const StringName &p_name, const StringName &p_node_type) const; void rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void clear_icon(const StringName &p_name, const StringName &p_node_type); void get_icon_list(StringName p_node_type, List<StringName> *p_list) const; @@ -128,6 +129,7 @@ public: void set_stylebox(const StringName &p_name, const StringName &p_node_type, const Ref<StyleBox> &p_style); Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_node_type) const; bool has_stylebox(const StringName &p_name, const StringName &p_node_type) const; + bool has_stylebox_nocheck(const StringName &p_name, const StringName &p_node_type) const; void rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void clear_stylebox(const StringName &p_name, const StringName &p_node_type); void get_stylebox_list(StringName p_node_type, List<StringName> *p_list) const; @@ -137,6 +139,7 @@ public: void set_font(const StringName &p_name, const StringName &p_node_type, const Ref<Font> &p_font); Ref<Font> get_font(const StringName &p_name, const StringName &p_node_type) const; bool has_font(const StringName &p_name, const StringName &p_node_type) const; + bool has_font_nocheck(const StringName &p_name, const StringName &p_node_type) const; void rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void clear_font(const StringName &p_name, const StringName &p_node_type); void get_font_list(StringName p_node_type, List<StringName> *p_list) const; @@ -146,6 +149,7 @@ public: void set_font_size(const StringName &p_name, const StringName &p_node_type, int p_font_size); int get_font_size(const StringName &p_name, const StringName &p_node_type) const; bool has_font_size(const StringName &p_name, const StringName &p_node_type) const; + bool has_font_size_nocheck(const StringName &p_name, const StringName &p_node_type) const; void rename_font_size(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void clear_font_size(const StringName &p_name, const StringName &p_node_type); void get_font_size_list(StringName p_node_type, List<StringName> *p_list) const; @@ -155,6 +159,7 @@ public: void set_color(const StringName &p_name, const StringName &p_node_type, const Color &p_color); Color get_color(const StringName &p_name, const StringName &p_node_type) const; bool has_color(const StringName &p_name, const StringName &p_node_type) const; + bool has_color_nocheck(const StringName &p_name, const StringName &p_node_type) const; void rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void clear_color(const StringName &p_name, const StringName &p_node_type); void get_color_list(StringName p_node_type, List<StringName> *p_list) const; @@ -164,6 +169,7 @@ public: void set_constant(const StringName &p_name, const StringName &p_node_type, int p_constant); int get_constant(const StringName &p_name, const StringName &p_node_type) const; bool has_constant(const StringName &p_name, const StringName &p_node_type) const; + bool has_constant_nocheck(const StringName &p_name, const StringName &p_node_type) const; void rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void clear_constant(const StringName &p_name, const StringName &p_node_type); void get_constant_list(StringName p_node_type, List<StringName> *p_list) const; @@ -173,6 +179,7 @@ public: void set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type, const Variant &p_value); Variant get_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const; bool has_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const; + bool has_theme_item_nocheck(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const; void rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); void clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type); void get_theme_item_list(DataType p_data_type, StringName p_node_type, List<StringName> *p_list) const; diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index 0a91931354..9306fea70c 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -591,16 +591,17 @@ void Body2DSW::call_queries() { Variant v = dbs; const Variant *vp[2] = { &v, &fi_callback->callback_udata }; - Object *obj = ObjectDB::get_instance(fi_callback->id); + Object *obj = fi_callback->callable.get_object(); if (!obj) { - set_force_integration_callback(ObjectID(), StringName()); + set_force_integration_callback(Callable()); } else { Callable::CallError ce; + Variant rv; if (fi_callback->callback_udata.get_type() != Variant::NIL) { - obj->call(fi_callback->method, vp, 2, ce); + fi_callback->callable.call(vp, 2, rv, ce); } else { - obj->call(fi_callback->method, vp, 1, ce); + fi_callback->callable.call(vp, 1, rv, ce); } } } @@ -625,16 +626,15 @@ bool Body2DSW::sleep_test(real_t p_step) { } } -void Body2DSW::set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata) { +void Body2DSW::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) { if (fi_callback) { memdelete(fi_callback); fi_callback = nullptr; } - if (p_id.is_valid()) { + if (p_callable.get_object()) { fi_callback = memnew(ForceIntegrationCallback); - fi_callback->id = p_id; - fi_callback->method = p_method; + fi_callback->callable = p_callable; fi_callback->callback_udata = p_udata; } } diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index 7ea4ac697c..b4a95651cb 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -117,8 +117,7 @@ class Body2DSW : public CollisionObject2DSW { int contact_count; struct ForceIntegrationCallback { - ObjectID id; - StringName method; + Callable callable; Variant callback_udata; }; @@ -131,7 +130,7 @@ class Body2DSW : public CollisionObject2DSW { friend class PhysicsDirectBodyState2DSW; // i give up, too many functions to expose public: - void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant()); + void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant()); _FORCE_INLINE_ void add_area(Area2DSW *p_area) { int index = areas.find(AreaCMP(p_area)); diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp index 1040437ca7..6d64f4126c 100644 --- a/servers/physics_2d/physics_server_2d_sw.cpp +++ b/servers/physics_2d/physics_server_2d_sw.cpp @@ -927,10 +927,10 @@ int PhysicsServer2DSW::body_get_max_contacts_reported(RID p_body) const { return body->get_max_contacts_reported(); } -void PhysicsServer2DSW::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) { +void PhysicsServer2DSW::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) { Body2DSW *body = body_owner.getornull(p_body); ERR_FAIL_COND(!body); - body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method, p_udata); + body->set_force_integration_callback(p_callable, p_udata); } bool PhysicsServer2DSW::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) { diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h index 65c5df0fce..efa0784245 100644 --- a/servers/physics_2d/physics_server_2d_sw.h +++ b/servers/physics_2d/physics_server_2d_sw.h @@ -242,7 +242,7 @@ public: virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) override; virtual int body_get_max_contacts_reported(RID p_body) const override; - virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) override; + virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) override; virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override; virtual void body_set_pickable(RID p_body, bool p_pickable) override; diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_2d/physics_server_2d_wrap_mt.h index 3577f706de..88ac742e40 100644 --- a/servers/physics_2d/physics_server_2d_wrap_mt.h +++ b/servers/physics_2d/physics_server_2d_wrap_mt.h @@ -245,7 +245,7 @@ public: FUNC2(body_set_omit_force_integration, RID, bool); FUNC1RC(bool, body_is_omitting_force_integration, RID); - FUNC4(body_set_force_integration_callback, RID, Object *, const StringName &, const Variant &); + FUNC3(body_set_force_integration_callback, RID, const Callable &, const Variant &); bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override { return physics_2d_server->body_collide_shape(p_body, p_body_shape, p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count); diff --git a/servers/physics_3d/body_3d_sw.cpp b/servers/physics_3d/body_3d_sw.cpp index cc414b7f30..d54345821d 100644 --- a/servers/physics_3d/body_3d_sw.cpp +++ b/servers/physics_3d/body_3d_sw.cpp @@ -693,15 +693,16 @@ void Body3DSW::call_queries() { Variant v = dbs; - Object *obj = ObjectDB::get_instance(fi_callback->id); + Object *obj = fi_callback->callable.get_object(); if (!obj) { - set_force_integration_callback(ObjectID(), StringName()); + set_force_integration_callback(Callable()); } else { const Variant *vp[2] = { &v, &fi_callback->udata }; Callable::CallError ce; int argc = (fi_callback->udata.get_type() == Variant::NIL) ? 1 : 2; - obj->call(fi_callback->method, vp, argc, ce); + Variant rv; + fi_callback->callable.call(vp, argc, rv, ce); } } } @@ -725,16 +726,15 @@ bool Body3DSW::sleep_test(real_t p_step) { } } -void Body3DSW::set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata) { +void Body3DSW::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) { if (fi_callback) { memdelete(fi_callback); fi_callback = nullptr; } - if (p_id.is_valid()) { + if (p_callable.get_object()) { fi_callback = memnew(ForceIntegrationCallback); - fi_callback->id = p_id; - fi_callback->method = p_method; + fi_callback->callable = p_callable; fi_callback->udata = p_udata; } } diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/body_3d_sw.h index 5790f43019..9afb8cd56f 100644 --- a/servers/physics_3d/body_3d_sw.h +++ b/servers/physics_3d/body_3d_sw.h @@ -127,8 +127,7 @@ class Body3DSW : public CollisionObject3DSW { int contact_count; struct ForceIntegrationCallback { - ObjectID id; - StringName method; + Callable callable; Variant udata; }; @@ -143,7 +142,7 @@ class Body3DSW : public CollisionObject3DSW { friend class PhysicsDirectBodyState3DSW; // i give up, too many functions to expose public: - void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant()); + void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant()); void set_kinematic_margin(real_t p_margin); _FORCE_INLINE_ real_t get_kinematic_margin() { return kinematic_safe_margin; } diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp index 3d0063b0fa..c08e2b5794 100644 --- a/servers/physics_3d/physics_server_3d_sw.cpp +++ b/servers/physics_3d/physics_server_3d_sw.cpp @@ -857,10 +857,10 @@ int PhysicsServer3DSW::body_get_max_contacts_reported(RID p_body) const { return body->get_max_contacts_reported(); } -void PhysicsServer3DSW::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) { +void PhysicsServer3DSW::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) { Body3DSW *body = body_owner.getornull(p_body); ERR_FAIL_COND(!body); - body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method, p_udata); + body->set_force_integration_callback(p_callable, p_udata); } void PhysicsServer3DSW::body_set_ray_pickable(RID p_body, bool p_enable) { diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h index f92652bfad..0b42f1d605 100644 --- a/servers/physics_3d/physics_server_3d_sw.h +++ b/servers/physics_3d/physics_server_3d_sw.h @@ -241,7 +241,7 @@ public: virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) override; virtual int body_get_max_contacts_reported(RID p_body) const override; - virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) override; + virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) override; virtual void body_set_ray_pickable(RID p_body, bool p_enable) override; diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.h b/servers/physics_3d/physics_server_3d_wrap_mt.h index 49ae60db92..69d0fcf3ed 100644 --- a/servers/physics_3d/physics_server_3d_wrap_mt.h +++ b/servers/physics_3d/physics_server_3d_wrap_mt.h @@ -249,7 +249,7 @@ public: FUNC2(body_set_omit_force_integration, RID, bool); FUNC1RC(bool, body_is_omitting_force_integration, RID); - FUNC4(body_set_force_integration_callback, RID, Object *, const StringName &, const Variant &); + FUNC3(body_set_force_integration_callback, RID, const Callable &, const Variant &); FUNC2(body_set_ray_pickable, RID, bool); diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index 83ebc0c55b..a4f13587da 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -647,7 +647,7 @@ void PhysicsServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("body_set_omit_force_integration", "body", "enable"), &PhysicsServer2D::body_set_omit_force_integration); ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration", "body"), &PhysicsServer2D::body_is_omitting_force_integration); - ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "receiver", "method", "userdata"), &PhysicsServer2D::body_set_force_integration_callback, DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "callable", "userdata"), &PhysicsServer2D::body_set_force_integration_callback, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "margin", "result"), &PhysicsServer2D::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant())); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index 28f22ce06b..40541f7838 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -477,7 +477,7 @@ public: virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0; virtual bool body_is_omitting_force_integration(RID p_body) const = 0; - virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) = 0; + virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) = 0; virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) = 0; diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index 586845de99..d16fbd3ff3 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -550,7 +550,7 @@ void PhysicsServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("body_set_omit_force_integration", "body", "enable"), &PhysicsServer3D::body_set_omit_force_integration); ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration", "body"), &PhysicsServer3D::body_is_omitting_force_integration); - ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "receiver", "method", "userdata"), &PhysicsServer3D::body_set_force_integration_callback, DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "callable", "userdata"), &PhysicsServer3D::body_set_force_integration_callback, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer3D::body_set_ray_pickable); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 69f5c1c0ad..3128092420 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -486,7 +486,7 @@ public: virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0; virtual bool body_is_omitting_force_integration(RID p_body) const = 0; - virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) = 0; + virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) = 0; virtual void body_set_ray_pickable(RID p_body, bool p_enable) = 0; diff --git a/tests/test_physics_2d.cpp b/tests/test_physics_2d.cpp index 047697e314..25b2871890 100644 --- a/tests/test_physics_2d.cpp +++ b/tests/test_physics_2d.cpp @@ -243,9 +243,7 @@ protected: Size2 imgsize(5, 5); //vs->texture_get_width(body_shape_data[p_shape].image), vs->texture_get_height(body_shape_data[p_shape].image)); vs->canvas_item_add_texture_rect(sprite, Rect2(-imgsize / 2.0, imgsize), body_shape_data[p_shape].image); - ps->body_set_force_integration_callback(body, this, "_body_moved", sprite); - //RID q = ps->query_create(this,"_body_moved",sprite); - //ps->query_body_state(q,body); + ps->body_set_force_integration_callback(body, callable_mp(this, &TestPhysics2DMainLoop::_body_moved), sprite); return body; } @@ -310,7 +308,6 @@ protected: } static void _bind_methods() { - ClassDB::bind_method(D_METHOD("_body_moved"), &TestPhysics2DMainLoop::_body_moved); ClassDB::bind_method(D_METHOD("_ray_query_callback"), &TestPhysics2DMainLoop::_ray_query_callback); } diff --git a/tests/test_physics_3d.cpp b/tests/test_physics_3d.cpp index bb324d8ffe..ac8078a0a8 100644 --- a/tests/test_physics_3d.cpp +++ b/tests/test_physics_3d.cpp @@ -77,10 +77,6 @@ class TestPhysics3DMainLoop : public MainLoop { bool quit; protected: - static void _bind_methods() { - ClassDB::bind_method("body_changed_transform", &TestPhysics3DMainLoop::body_changed_transform); - } - RID create_body(PhysicsServer3D::ShapeType p_shape, PhysicsServer3D::BodyMode p_body, const Transform p_location, bool p_active_default = true, const Transform &p_shape_xform = Transform()) { RenderingServer *vs = RenderingServer::get_singleton(); PhysicsServer3D *ps = PhysicsServer3D::get_singleton(); @@ -93,7 +89,7 @@ protected: ps->body_set_param(body, PhysicsServer3D::BODY_PARAM_BOUNCE, 0.0); //todo set space ps->body_add_shape(body, type_shape_map[p_shape]); - ps->body_set_force_integration_callback(body, this, "body_changed_transform", mesh_instance); + ps->body_set_force_integration_callback(body, callable_mp(this, &TestPhysics3DMainLoop::body_changed_transform), mesh_instance); ps->body_set_state(body, PhysicsServer3D::BODY_STATE_TRANSFORM, p_location); bodies.push_back(body); @@ -370,8 +366,7 @@ public: ps->body_set_space(character, space); //todo add space ps->body_add_shape(character, capsule_shape); - - ps->body_set_force_integration_callback(character, this, "body_changed_transform", mesh_instance); + ps->body_set_force_integration_callback(character, callable_mp(this, &TestPhysics3DMainLoop::body_changed_transform), mesh_instance); ps->body_set_state(character, PhysicsServer3D::BODY_STATE_TRANSFORM, Transform(Basis(), Vector3(-2, 5, -2))); bodies.push_back(character); diff --git a/thirdparty/README.md b/thirdparty/README.md index 33ce2423d9..97f21f8539 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -186,17 +186,17 @@ Files extracted from upstream source: ## icu4c - Upstream: https://github.com/unicode-org/icu -- Version: 68.2 (84e1f26ea77152936e70d53178a816dbfbf69989, 2020) +- Version: 69.1 (0e7b4428866f3133b4abba2d932ee3faa708db1d, 2021) - License: Unicode Files extracted from upstream source: - the `common` folder -- `APIChangeReport.md`, `LICENSE` +- `LICENSE` Files generated from upstream source: -- the `icudt68l.dat` built with the provided `godot_data.json` config file (see +- the `icudt69l.dat` built with the provided `godot_data.json` config file (see https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/buildtool.md for instructions) diff --git a/thirdparty/icu4c/APIChangeReport.md b/thirdparty/icu4c/APIChangeReport.md deleted file mode 100644 index 5385904fd1..0000000000 --- a/thirdparty/icu4c/APIChangeReport.md +++ /dev/null @@ -1,396 +0,0 @@ - - -<!-- - Copyright © 2019 and later: Unicode, Inc. and others. - License & terms of use: http://www.unicode.org/copyright.html ---> - -# ICU4C API Comparison: ICU 67 with ICU 68 - -> _Note_ Markdown format of this document is new for ICU 65. - -- [Removed from ICU 67](#removed) -- [Deprecated or Obsoleted in ICU 68](#deprecated) -- [Changed in ICU 68](#changed) -- [Promoted to stable in ICU 68](#promoted) -- [Added in ICU 68](#added) -- [Other existing drafts in ICU 68](#other) -- [Signature Simplifications](#simplifications) - -## Removed - -Removed from ICU 67 - -| File | API | ICU 67 | ICU 68 | -|---|---|---|---| -| fmtable.h | const UFormattable* icu::Formattable::toUFormattable() | StableICU 52 | (missing) -| measunit.h | LocalArray<MeasureUnit> icu::MeasureUnit::splitToSingleUnits(int32_t&, UErrorCode&) const | InternalICU 67 | (missing) -| measunit.h | int32_t icu::MeasureUnit::getIndex() const | Internal | (missing) -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::resolveUnitPerUnit(const MeasureUnit&, const MeasureUnit&, bool*) | Internal | (missing) -| measunit.h | <tt>static</tt> int32_t icu::MeasureUnit::getIndexCount() | Internal | (missing) -| measunit.h | <tt>static</tt> int32_t icu::MeasureUnit::internalGetIndexForTypeAndSubtype(const char*, const char*) | Internal | (missing) -| nounit.h | UClassID icu::NoUnit::getDynamicClassID() const | DraftICU 60 | (missing) -| nounit.h | icu::NoUnit::NoUnit(const NoUnit&) | DraftICU 60 | (missing) -| nounit.h | icu::NoUnit::~NoUnit() | DraftICU 60 | (missing) -| nounit.h | <tt>static</tt> NoUnit icu::NoUnit::base() | DraftICU 60 | (missing) -| nounit.h | <tt>static</tt> NoUnit icu::NoUnit::percent() | DraftICU 60 | (missing) -| nounit.h | <tt>static</tt> NoUnit icu::NoUnit::permille() | DraftICU 60 | (missing) -| nounit.h | <tt>static</tt> UClassID icu::NoUnit::getStaticClassID() | DraftICU 60 | (missing) -| nounit.h | void* icu::NoUnit::clone() const | DraftICU 60 | (missing) -| uniset.h | const USet* icu::UnicodeSet::toUSet() | StableICU 4.2 | (missing) - -## Deprecated - -Deprecated or Obsoleted in ICU 68 - -| File | API | ICU 67 | ICU 68 | -|---|---|---|---| -| numberrangeformatter.h | UnicodeString icu::number::FormattedNumberRange::getFirstDecimal(UErrorCode&) const | DraftICU 63 | DeprecatedICU 68 -| numberrangeformatter.h | UnicodeString icu::number::FormattedNumberRange::getSecondDecimal(UErrorCode&) const | DraftICU 63 | DeprecatedICU 68 -| umachine.h | <tt>#define</tt> FALSE | StableICU 2.0 | DeprecatedICU 68 -| umachine.h | <tt>#define</tt> TRUE | StableICU 2.0 | DeprecatedICU 68 - -## Changed - -Changed in ICU 68 (old, new) - - - -| File | API | ICU 67 | ICU 68 | -|---|---|---|---| -| bytestrie.h | BytesTrie& icu::BytesTrie::resetToState64(uint64_t) | Draft→StableICU 65 -| bytestrie.h | uint64_t icu::BytesTrie::getState64() const | Draft→StableICU 65 -| listformatter.h | <tt>static</tt> ListFormatter* icu::ListFormatter::createInstance(const Locale&, UListFormatterType, UListFormatterWidth, UErrorCode&) | Draft→StableICU 67 -| localebuilder.h | UBool icu::LocaleBuilder::copyErrorTo(UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::addSupportedLocale(const Locale&) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::operator=(Builder&&) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setDefaultLocale(const Locale*) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setDemotionPerDesiredLocale(ULocMatchDemotion) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setFavorSubtag(ULocMatchFavorSubtag) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setSupportedLocales(Iter, Iter) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setSupportedLocales(Locale::Iterator&) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setSupportedLocalesFromListString(StringPiece) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setSupportedLocalesViaConverter(Iter, Iter, Conv) | Draft→StableICU 65 -| localematcher.h | Locale icu::LocaleMatcher::Result::makeResolvedLocale(UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | LocaleMatcher icu::LocaleMatcher::Builder::build(UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | LocaleMatcher& icu::LocaleMatcher::operator=(LocaleMatcher&&) | Draft→StableICU 65 -| localematcher.h | Result icu::LocaleMatcher::getBestMatchResult(Locale::Iterator&, UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | Result icu::LocaleMatcher::getBestMatchResult(const Locale&, UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | Result& icu::LocaleMatcher::Result::operator=(Result&&) | Draft→StableICU 65 -| localematcher.h | UBool icu::LocaleMatcher::Builder::copyErrorTo(UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | const Locale* icu::LocaleMatcher::Result::getDesiredLocale() const | Draft→StableICU 65 -| localematcher.h | const Locale* icu::LocaleMatcher::Result::getSupportedLocale() const | Draft→StableICU 65 -| localematcher.h | const Locale* icu::LocaleMatcher::getBestMatch(Locale::Iterator&, UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | const Locale* icu::LocaleMatcher::getBestMatch(const Locale&, UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | const Locale* icu::LocaleMatcher::getBestMatchForListString(StringPiece, UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | <tt>enum</tt> ULocMatchDemotion::ULOCMATCH_DEMOTION_NONE | Draft→StableICU 65 -| localematcher.h | <tt>enum</tt> ULocMatchDemotion::ULOCMATCH_DEMOTION_REGION | Draft→StableICU 65 -| localematcher.h | <tt>enum</tt> ULocMatchFavorSubtag::ULOCMATCH_FAVOR_LANGUAGE | Draft→StableICU 65 -| localematcher.h | <tt>enum</tt> ULocMatchFavorSubtag::ULOCMATCH_FAVOR_SCRIPT | Draft→StableICU 65 -| localematcher.h | icu::LocaleMatcher::Builder::Builder() | Draft→StableICU 65 -| localematcher.h | icu::LocaleMatcher::Builder::Builder(Builder&&) | Draft→StableICU 65 -| localematcher.h | icu::LocaleMatcher::Builder::~Builder() | Draft→StableICU 65 -| localematcher.h | icu::LocaleMatcher::LocaleMatcher(LocaleMatcher&&) | Draft→StableICU 65 -| localematcher.h | icu::LocaleMatcher::Result::Result(Result&&) | Draft→StableICU 65 -| localematcher.h | icu::LocaleMatcher::Result::~Result() | Draft→StableICU 65 -| localematcher.h | icu::LocaleMatcher::~LocaleMatcher() | Draft→StableICU 65 -| localematcher.h | int32_t icu::LocaleMatcher::Result::getDesiredIndex() const | Draft→StableICU 65 -| localematcher.h | int32_t icu::LocaleMatcher::Result::getSupportedIndex() const | Draft→StableICU 65 -| locid.h | UBool icu::Locale::ConvertingIterator< Iter, Conv >::hasNext() const override | Draft→StableICU 65 -| locid.h | UBool icu::Locale::Iterator::hasNext() const | Draft→StableICU 65 -| locid.h | UBool icu::Locale::RangeIterator< Iter >::hasNext() const override | Draft→StableICU 65 -| locid.h | const Locale& icu::Locale::ConvertingIterator< Iter, Conv >::next() override | Draft→StableICU 65 -| locid.h | const Locale& icu::Locale::Iterator::next() | Draft→StableICU 65 -| locid.h | const Locale& icu::Locale::RangeIterator< Iter >::next() override | Draft→StableICU 65 -| locid.h | icu::Locale::ConvertingIterator< Iter, Conv >::ConvertingIterator(Iter, Iter, Conv) | Draft→StableICU 65 -| locid.h | icu::Locale::Iterator::~Iterator() | Draft→StableICU 65 -| locid.h | icu::Locale::RangeIterator< Iter >::RangeIterator(Iter, Iter) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getBar() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getDecade() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getDotPerCentimeter() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getDotPerInch() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getEm() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getMegapixel() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getPascal() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getPixel() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getPixelPerCentimeter() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getPixelPerInch() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getThermUs() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createBar(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createDecade(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createDotPerCentimeter(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createDotPerInch(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createEm(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createMegapixel(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createPascal(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createPixel(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createPixelPerCentimeter(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createPixelPerInch(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createThermUs(UErrorCode&) | Draft→StableICU 65 -| numberformatter.h | StringClass icu::number::FormattedNumber::toDecimalNumber(UErrorCode&) const | Draft→StableICU 65 -| numberrangeformatter.h | UnicodeString icu::number::FormattedNumberRange::getFirstDecimal(UErrorCode&) const | DraftICU 63 | DeprecatedICU 68 -| numberrangeformatter.h | UnicodeString icu::number::FormattedNumberRange::getSecondDecimal(UErrorCode&) const | DraftICU 63 | DeprecatedICU 68 -| reldatefmt.h | <tt>enum</tt> UDateAbsoluteUnit::UDAT_ABSOLUTE_HOUR | Draft→StableICU 65 -| reldatefmt.h | <tt>enum</tt> UDateAbsoluteUnit::UDAT_ABSOLUTE_MINUTE | Draft→StableICU 65 -| stringpiece.h | icu::StringPiece::StringPiece(T) | Draft→StableICU 65 -| ucal.h | int32_t ucal_getHostTimeZone(UChar*, int32_t, UErrorCode*) | Draft→StableICU 65 -| ucharstrie.h | UCharsTrie& icu::UCharsTrie::resetToState64(uint64_t) | Draft→StableICU 65 -| ucharstrie.h | uint64_t icu::UCharsTrie::getState64() const | Draft→StableICU 65 -| ulistformatter.h | UListFormatter* ulistfmt_openForType(const char*, UListFormatterType, UListFormatterWidth, UErrorCode*) | Draft→StableICU 67 -| ulistformatter.h | <tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_AND | Draft→StableICU 67 -| ulistformatter.h | <tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_OR | Draft→StableICU 67 -| ulistformatter.h | <tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_UNITS | Draft→StableICU 67 -| ulistformatter.h | <tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_NARROW | Draft→StableICU 67 -| ulistformatter.h | <tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_SHORT | Draft→StableICU 67 -| ulistformatter.h | <tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_WIDE | Draft→StableICU 67 -| uloc.h | UEnumeration* uloc_openAvailableByType(ULocAvailableType, UErrorCode*) | Draft→StableICU 65 -| uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_DEFAULT | Draft→StableICU 65 -| uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_ONLY_LEGACY_ALIASES | Draft→StableICU 65 -| uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_WITH_LEGACY_ALIASES | Draft→StableICU 65 -| umachine.h | <tt>#define</tt> FALSE | StableICU 2.0 | DeprecatedICU 68 -| umachine.h | <tt>#define</tt> TRUE | StableICU 2.0 | DeprecatedICU 68 -| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UDATA_BUNDLE | Draft→StableICU 65 -| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UDATA_DATA_FILE | Draft→StableICU 65 -| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UDATA_RES_FILE | Draft→StableICU 65 -| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UDATA_START | Draft→StableICU 65 - -## Promoted - -Promoted to stable in ICU 68 - -| File | API | ICU 67 | ICU 68 | -|---|---|---|---| -| bytestrie.h | BytesTrie& icu::BytesTrie::resetToState64(uint64_t) | Draft→StableICU 65 -| bytestrie.h | uint64_t icu::BytesTrie::getState64() const | Draft→StableICU 65 -| fmtable.h | UFormattable* icu::Formattable::toUFormattable() | (missing) | StableICU 52 -| listformatter.h | <tt>static</tt> ListFormatter* icu::ListFormatter::createInstance(const Locale&, UListFormatterType, UListFormatterWidth, UErrorCode&) | Draft→StableICU 67 -| localebuilder.h | UBool icu::LocaleBuilder::copyErrorTo(UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::addSupportedLocale(const Locale&) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::operator=(Builder&&) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setDefaultLocale(const Locale*) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setDemotionPerDesiredLocale(ULocMatchDemotion) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setFavorSubtag(ULocMatchFavorSubtag) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setSupportedLocales(Iter, Iter) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setSupportedLocales(Locale::Iterator&) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setSupportedLocalesFromListString(StringPiece) | Draft→StableICU 65 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setSupportedLocalesViaConverter(Iter, Iter, Conv) | Draft→StableICU 65 -| localematcher.h | Locale icu::LocaleMatcher::Result::makeResolvedLocale(UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | LocaleMatcher icu::LocaleMatcher::Builder::build(UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | LocaleMatcher& icu::LocaleMatcher::operator=(LocaleMatcher&&) | Draft→StableICU 65 -| localematcher.h | Result icu::LocaleMatcher::getBestMatchResult(Locale::Iterator&, UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | Result icu::LocaleMatcher::getBestMatchResult(const Locale&, UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | Result& icu::LocaleMatcher::Result::operator=(Result&&) | Draft→StableICU 65 -| localematcher.h | UBool icu::LocaleMatcher::Builder::copyErrorTo(UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | const Locale* icu::LocaleMatcher::Result::getDesiredLocale() const | Draft→StableICU 65 -| localematcher.h | const Locale* icu::LocaleMatcher::Result::getSupportedLocale() const | Draft→StableICU 65 -| localematcher.h | const Locale* icu::LocaleMatcher::getBestMatch(Locale::Iterator&, UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | const Locale* icu::LocaleMatcher::getBestMatch(const Locale&, UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | const Locale* icu::LocaleMatcher::getBestMatchForListString(StringPiece, UErrorCode&) const | Draft→StableICU 65 -| localematcher.h | <tt>enum</tt> ULocMatchDemotion::ULOCMATCH_DEMOTION_NONE | Draft→StableICU 65 -| localematcher.h | <tt>enum</tt> ULocMatchDemotion::ULOCMATCH_DEMOTION_REGION | Draft→StableICU 65 -| localematcher.h | <tt>enum</tt> ULocMatchFavorSubtag::ULOCMATCH_FAVOR_LANGUAGE | Draft→StableICU 65 -| localematcher.h | <tt>enum</tt> ULocMatchFavorSubtag::ULOCMATCH_FAVOR_SCRIPT | Draft→StableICU 65 -| localematcher.h | icu::LocaleMatcher::Builder::Builder() | Draft→StableICU 65 -| localematcher.h | icu::LocaleMatcher::Builder::Builder(Builder&&) | Draft→StableICU 65 -| localematcher.h | icu::LocaleMatcher::Builder::~Builder() | Draft→StableICU 65 -| localematcher.h | icu::LocaleMatcher::LocaleMatcher(LocaleMatcher&&) | Draft→StableICU 65 -| localematcher.h | icu::LocaleMatcher::Result::Result(Result&&) | Draft→StableICU 65 -| localematcher.h | icu::LocaleMatcher::Result::~Result() | Draft→StableICU 65 -| localematcher.h | icu::LocaleMatcher::~LocaleMatcher() | Draft→StableICU 65 -| localematcher.h | int32_t icu::LocaleMatcher::Result::getDesiredIndex() const | Draft→StableICU 65 -| localematcher.h | int32_t icu::LocaleMatcher::Result::getSupportedIndex() const | Draft→StableICU 65 -| locid.h | UBool icu::Locale::ConvertingIterator< Iter, Conv >::hasNext() const override | Draft→StableICU 65 -| locid.h | UBool icu::Locale::Iterator::hasNext() const | Draft→StableICU 65 -| locid.h | UBool icu::Locale::RangeIterator< Iter >::hasNext() const override | Draft→StableICU 65 -| locid.h | const Locale& icu::Locale::ConvertingIterator< Iter, Conv >::next() override | Draft→StableICU 65 -| locid.h | const Locale& icu::Locale::Iterator::next() | Draft→StableICU 65 -| locid.h | const Locale& icu::Locale::RangeIterator< Iter >::next() override | Draft→StableICU 65 -| locid.h | icu::Locale::ConvertingIterator< Iter, Conv >::ConvertingIterator(Iter, Iter, Conv) | Draft→StableICU 65 -| locid.h | icu::Locale::Iterator::~Iterator() | Draft→StableICU 65 -| locid.h | icu::Locale::RangeIterator< Iter >::RangeIterator(Iter, Iter) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getBar() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getDecade() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getDotPerCentimeter() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getDotPerInch() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getEm() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getMegapixel() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getPascal() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getPixel() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getPixelPerCentimeter() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getPixelPerInch() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getThermUs() | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createBar(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createDecade(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createDotPerCentimeter(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createDotPerInch(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createEm(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createMegapixel(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createPascal(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createPixel(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createPixelPerCentimeter(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createPixelPerInch(UErrorCode&) | Draft→StableICU 65 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createThermUs(UErrorCode&) | Draft→StableICU 65 -| numberformatter.h | StringClass icu::number::FormattedNumber::toDecimalNumber(UErrorCode&) const | Draft→StableICU 65 -| reldatefmt.h | <tt>enum</tt> UDateAbsoluteUnit::UDAT_ABSOLUTE_HOUR | Draft→StableICU 65 -| reldatefmt.h | <tt>enum</tt> UDateAbsoluteUnit::UDAT_ABSOLUTE_MINUTE | Draft→StableICU 65 -| stringpiece.h | icu::StringPiece::StringPiece(T) | Draft→StableICU 65 -| ucal.h | int32_t ucal_getHostTimeZone(UChar*, int32_t, UErrorCode*) | Draft→StableICU 65 -| ucharstrie.h | UCharsTrie& icu::UCharsTrie::resetToState64(uint64_t) | Draft→StableICU 65 -| ucharstrie.h | uint64_t icu::UCharsTrie::getState64() const | Draft→StableICU 65 -| ulistformatter.h | UListFormatter* ulistfmt_openForType(const char*, UListFormatterType, UListFormatterWidth, UErrorCode*) | Draft→StableICU 67 -| ulistformatter.h | <tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_AND | Draft→StableICU 67 -| ulistformatter.h | <tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_OR | Draft→StableICU 67 -| ulistformatter.h | <tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_UNITS | Draft→StableICU 67 -| ulistformatter.h | <tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_NARROW | Draft→StableICU 67 -| ulistformatter.h | <tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_SHORT | Draft→StableICU 67 -| ulistformatter.h | <tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_WIDE | Draft→StableICU 67 -| uloc.h | UEnumeration* uloc_openAvailableByType(ULocAvailableType, UErrorCode*) | Draft→StableICU 65 -| uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_DEFAULT | Draft→StableICU 65 -| uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_ONLY_LEGACY_ALIASES | Draft→StableICU 65 -| uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_WITH_LEGACY_ALIASES | Draft→StableICU 65 -| uniset.h | USet* icu::UnicodeSet::toUSet() | (missing) | StableICU 4.2 -| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UDATA_BUNDLE | Draft→StableICU 65 -| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UDATA_DATA_FILE | Draft→StableICU 65 -| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UDATA_RES_FILE | Draft→StableICU 65 -| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UDATA_START | Draft→StableICU 65 - -## Added - -Added in ICU 68 - -| File | API | ICU 67 | ICU 68 | -|---|---|---|---| -| dtitvfmt.h | UDisplayContext icu::DateIntervalFormat::getContext(UDisplayContextType, UErrorCode&) const | (missing) | DraftICU 68 -| dtitvfmt.h | void icu::DateIntervalFormat::setContext(UDisplayContext, UErrorCode&) | (missing) | DraftICU 68 -| dtptngen.h | <tt>static</tt> DateTimePatternGenerator* icu::DateTimePatternGenerator::createInstanceNoStdPat(const Locale&, UErrorCode&) | (missing) | Internal -| fmtable.h | UFormattable* icu::Formattable::toUFormattable() | (missing) | StableICU 52 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setMaxDistance(const Locale&, const Locale&) | (missing) | DraftICU 68 -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setNoDefaultLocale() | (missing) | DraftICU 68 -| localematcher.h | UBool icu::LocaleMatcher::isMatch(const Locale&, const Locale&, UErrorCode&) const | (missing) | DraftICU 68 -| measunit.h | int32_t icu::MeasureUnit::getOffset() const | (missing) | Internal -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getCandela() | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getDessertSpoon() | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getDessertSpoonImperial() | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getDot() | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getDram() | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getDrop() | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getEarthRadius() | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getGrain() | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getJigger() | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getLumen() | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getPinch() | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::getQuartImperial() | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createCandela(UErrorCode&) | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createDessertSpoon(UErrorCode&) | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createDessertSpoonImperial(UErrorCode&) | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createDot(UErrorCode&) | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createDram(UErrorCode&) | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createDrop(UErrorCode&) | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createEarthRadius(UErrorCode&) | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createGrain(UErrorCode&) | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createJigger(UErrorCode&) | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createLumen(UErrorCode&) | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createPinch(UErrorCode&) | (missing) | DraftICU 68 -| measunit.h | <tt>static</tt> MeasureUnit* icu::MeasureUnit::createQuartImperial(UErrorCode&) | (missing) | DraftICU 68 -| measunit.h | std::pair< LocalArray< MeasureUnit >, int32_t > icu::MeasureUnit::splitToSingleUnits(UErrorCode&) const | (missing) | DraftICU 68 -| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::usage(StringPiece) const& | (missing) | DraftICU 68 -| numberformatter.h | Derived icu::number::NumberFormatterSettings< Derived >::usage(StringPiece)&& | (missing) | DraftICU 68 -| numberformatter.h | MeasureUnit icu::number::FormattedNumber::getOutputUnit(UErrorCode&) const | (missing) | DraftICU 68 -| numberformatter.h | Usage& icu::number::impl::Usage::operator=(Usage&&) | (missing) | Internal -| numberformatter.h | Usage& icu::number::impl::Usage::operator=(const Usage&) | (missing) | Internal -| numberformatter.h | bool icu::number::impl::Usage::isSet() const | (missing) | Internal -| numberformatter.h | icu::number::impl::Usage::Usage(Usage&&) | (missing) | Internal -| numberformatter.h | icu::number::impl::Usage::Usage(const Usage&) | (missing) | Internal -| numberformatter.h | icu::number::impl::Usage::~Usage() | (missing) | Internal -| numberformatter.h | int16_t icu::number::impl::Usage::length() const | (missing) | Internal -| numberformatter.h | void icu::number::impl::Usage::set(StringPiece) | (missing) | Internal -| numberrangeformatter.h | std::pair< StringClass, StringClass > icu::number::FormattedNumberRange::getDecimalNumbers(UErrorCode&) const | (missing) | DraftICU 68 -| plurrule.h | UnicodeString icu::PluralRules::select(const number::FormattedNumberRange&, UErrorCode&) const | (missing) | DraftICU 68 -| plurrule.h | UnicodeString icu::PluralRules::select(const number::impl::UFormattedNumberRangeData*, UErrorCode&) const | (missing) | Internal -| plurrule.h | int32_t icu::PluralRules::getSamples(const UnicodeString&, FixedDecimal*, int32_t, UErrorCode&) | (missing) | Internal -| timezone.h | <tt>static</tt> TimeZone* icu::TimeZone::forLocaleOrDefault(const Locale&) | (missing) | Internal -| ucurr.h | <tt>enum</tt> UCurrNameStyle::UCURR_FORMAL_SYMBOL_NAME | (missing) | DraftICU 68 -| ucurr.h | <tt>enum</tt> UCurrNameStyle::UCURR_VARIANT_SYMBOL_NAME | (missing) | DraftICU 68 -| udateintervalformat.h | UDisplayContext udtitvfmt_getContext(const UDateIntervalFormat*, UDisplayContextType, UErrorCode*) | (missing) | DraftICU 68 -| udateintervalformat.h | void udtitvfmt_setContext(UDateIntervalFormat*, UDisplayContext, UErrorCode*) | (missing) | DraftICU 68 -| umachine.h | <tt>#define</tt> U_DEFINE_FALSE_AND_TRUE | (missing) | InternalICU 68 -| uniset.h | USet* icu::UnicodeSet::toUSet() | (missing) | StableICU 4.2 -| unum.h | <tt>enum</tt> UNumberFormatMinimumGroupingDigits::UNUM_MINIMUM_GROUPING_DIGITS_AUTO | (missing) | DraftICU 68 -| unum.h | <tt>enum</tt> UNumberFormatMinimumGroupingDigits::UNUM_MINIMUM_GROUPING_DIGITS_MIN2 | (missing) | DraftICU 68 -| unumberformatter.h | <tt>enum</tt> UNumberUnitWidth::UNUM_UNIT_WIDTH_FORMAL | (missing) | DraftICU 68 -| unumberformatter.h | <tt>enum</tt> UNumberUnitWidth::UNUM_UNIT_WIDTH_VARIANT | (missing) | DraftICU 68 -| unumberformatter.h | int32_t unumf_resultToDecimalNumber(const UFormattedNumber*, char*, int32_t, UErrorCode*) | (missing) | DraftICU 68 -| unumberrangeformatter.h | UFormattedNumberRange* unumrf_openResult(UErrorCode*) | (missing) | DraftICU 68 -| unumberrangeformatter.h | UNumberRangeFormatter* unumrf_openForSkeletonWithCollapseAndIdentityFallback(const UChar*, int32_t, UNumberRangeCollapse, UNumberRangeIdentityFallback, const char*, UParseError*, UErrorCode*) | (missing) | DraftICU 68 -| unumberrangeformatter.h | UNumberRangeIdentityResult unumrf_resultGetIdentityResult(const UFormattedNumberRange*, UErrorCode*) | (missing) | DraftICU 68 -| unumberrangeformatter.h | const UFormattedValue* unumrf_resultAsValue(const UFormattedNumberRange*, UErrorCode*) | (missing) | DraftICU 68 -| unumberrangeformatter.h | int32_t unumrf_resultGetFirstDecimalNumber(const UFormattedNumberRange*, char*, int32_t, UErrorCode*) | (missing) | DraftICU 68 -| unumberrangeformatter.h | int32_t unumrf_resultGetSecondDecimalNumber(const UFormattedNumberRange*, char*, int32_t, UErrorCode*) | (missing) | DraftICU 68 -| unumberrangeformatter.h | void unumrf_close(UNumberRangeFormatter*) | (missing) | DraftICU 68 -| unumberrangeformatter.h | void unumrf_closeResult(UFormattedNumberRange*) | (missing) | DraftICU 68 -| unumberrangeformatter.h | void unumrf_formatDecimalRange(const UNumberRangeFormatter*, const char*, int32_t, const char*, int32_t, UFormattedNumberRange*, UErrorCode*) | (missing) | DraftICU 68 -| unumberrangeformatter.h | void unumrf_formatDoubleRange(const UNumberRangeFormatter*, double, double, UFormattedNumberRange*, UErrorCode*) | (missing) | DraftICU 68 -| upluralrules.h | int32_t uplrules_selectForRange(const UPluralRules*, const struct UFormattedNumberRange*, UChar*, int32_t, UErrorCode*) | (missing) | DraftICU 68 - -## Other - -Other existing drafts in ICU 68 - -| File | API | ICU 67 | ICU 68 | -|---|---|---|---| -| bytestream.h | void icu::ByteSink::AppendU8(const char*, int32_t) | DraftICU 67 | -| bytestream.h | void icu::ByteSink::AppendU8(const char8_t*, int32_t) | DraftICU 67 | -| dtptngen.h | UDateFormatHourCycle icu::DateTimePatternGenerator::getDefaultHourCycle(UErrorCode&) const | DraftICU 67 | -| localematcher.h | Builder& icu::LocaleMatcher::Builder::setDirection(ULocMatchDirection) | DraftICU 67 | -| localematcher.h | <tt>enum</tt> ULocMatchDirection::ULOCMATCH_DIRECTION_ONLY_TWO_WAY | DraftICU 67 | -| localematcher.h | <tt>enum</tt> ULocMatchDirection::ULOCMATCH_DIRECTION_WITH_ONE_WAY | DraftICU 67 | -| locid.h | void icu::Locale::canonicalize(UErrorCode&) | DraftICU 67 | -| measfmt.h | void icu::MeasureFormat::parseObject(const UnicodeString&, Formattable&, ParsePosition&) const | DraftICU 53 | -| measunit.h | MeasureUnit icu::MeasureUnit::product(const MeasureUnit&, UErrorCode&) const | DraftICU 67 | -| measunit.h | MeasureUnit icu::MeasureUnit::reciprocal(UErrorCode&) const | DraftICU 67 | -| measunit.h | MeasureUnit icu::MeasureUnit::withDimensionality(int32_t, UErrorCode&) const | DraftICU 67 | -| measunit.h | MeasureUnit icu::MeasureUnit::withSIPrefix(UMeasureSIPrefix, UErrorCode&) const | DraftICU 67 | -| measunit.h | MeasureUnit& icu::MeasureUnit::operator=(MeasureUnit&&) noexcept | DraftICU 67 | -| measunit.h | UMeasureSIPrefix icu::MeasureUnit::getSIPrefix(UErrorCode&) const | DraftICU 67 | -| measunit.h | UMeasureUnitComplexity icu::MeasureUnit::getComplexity(UErrorCode&) const | DraftICU 67 | -| measunit.h | const char* icu::MeasureUnit::getIdentifier() const | DraftICU 67 | -| measunit.h | icu::MeasureUnit::MeasureUnit(MeasureUnit&&) noexcept | DraftICU 67 | -| measunit.h | int32_t icu::MeasureUnit::getDimensionality(UErrorCode&) const | DraftICU 67 | -| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::forIdentifier(StringPiece, UErrorCode&) | DraftICU 67 | -| stringpiece.h | icu::StringPiece::StringPiece(const char8_t*) | DraftICU 67 | -| stringpiece.h | icu::StringPiece::StringPiece(const char8_t*, int32_t) | DraftICU 67 | -| stringpiece.h | icu::StringPiece::StringPiece(const std::u8string&) | DraftICU 67 | -| stringpiece.h | icu::StringPiece::StringPiece(std::nullptr_t) | DraftICU 67 | -| stringpiece.h | int32_t icu::StringPiece::compare(StringPiece) | DraftICU 67 | -| stringpiece.h | int32_t icu::StringPiece::find(StringPiece, int32_t) | DraftICU 67 | -| stringpiece.h | void icu::StringPiece::set(const char8_t*) | DraftICU 67 | -| stringpiece.h | void icu::StringPiece::set(const char8_t*, int32_t) | DraftICU 67 | -| udat.h | <tt>enum</tt> UDateFormatHourCycle::UDAT_HOUR_CYCLE_11 | DraftICU 67 | -| udat.h | <tt>enum</tt> UDateFormatHourCycle::UDAT_HOUR_CYCLE_12 | DraftICU 67 | -| udat.h | <tt>enum</tt> UDateFormatHourCycle::UDAT_HOUR_CYCLE_23 | DraftICU 67 | -| udat.h | <tt>enum</tt> UDateFormatHourCycle::UDAT_HOUR_CYCLE_24 | DraftICU 67 | -| udateintervalformat.h | void udtitvfmt_formatCalendarToResult(const UDateIntervalFormat*, UCalendar*, UCalendar*, UFormattedDateInterval*, UErrorCode*) | DraftICU 67 | -| udateintervalformat.h | void udtitvfmt_formatToResult(const UDateIntervalFormat*, UDate, UDate, UFormattedDateInterval*, UErrorCode*) | DraftICU 67 | -| udatpg.h | UDateFormatHourCycle udatpg_getDefaultHourCycle(const UDateTimePatternGenerator*, UErrorCode*) | DraftICU 67 | -| uregex.h | <tt>enum</tt> URegexpFlag::UREGEX_CANON_EQ | DraftICU 2.4 | -| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UBRK_CREATE_BREAK_ENGINE | DraftICU 67 | -| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UBRK_CREATE_CHARACTER | DraftICU 67 | -| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UBRK_CREATE_LINE | DraftICU 67 | -| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UBRK_CREATE_SENTENCE | DraftICU 67 | -| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UBRK_CREATE_TITLE | DraftICU 67 | -| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UBRK_CREATE_WORD | DraftICU 67 | -| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UBRK_START | DraftICU 67 | - -## Simplifications - -This section shows cases where the signature was "simplified" for the sake of comparison. The simplified form is in bold, followed by - all possible variations in "original" form. - - -## Colophon - -Contents generated by StableAPI tool on Fri Oct 23 11:32:42 PDT 2020 - -Copyright © 2019 and later: Unicode, Inc. and others. -License & terms of use: http://www.unicode.org/copyright.html -
\ No newline at end of file diff --git a/thirdparty/icu4c/common/bytestriebuilder.cpp b/thirdparty/icu4c/common/bytestriebuilder.cpp index ec1ab7d8f5..28256f272a 100644 --- a/thirdparty/icu4c/common/bytestriebuilder.cpp +++ b/thirdparty/icu4c/common/bytestriebuilder.cpp @@ -474,31 +474,39 @@ BytesTrieBuilder::writeDeltaTo(int32_t jumpTarget) { U_ASSERT(i>=0); if(i<=BytesTrie::kMaxOneByteDelta) { return write(i); + } else { + char intBytes[5]; + return write(intBytes, internalEncodeDelta(i, intBytes)); } - char intBytes[5]; - int32_t length; +} + +int32_t +BytesTrieBuilder::internalEncodeDelta(int32_t i, char intBytes[]) { + U_ASSERT(i>=0); + if(i<=BytesTrie::kMaxOneByteDelta) { + intBytes[0]=(char)i; + return 1; + } + int32_t length=1; if(i<=BytesTrie::kMaxTwoByteDelta) { intBytes[0]=(char)(BytesTrie::kMinTwoByteDeltaLead+(i>>8)); - length=1; } else { if(i<=BytesTrie::kMaxThreeByteDelta) { intBytes[0]=(char)(BytesTrie::kMinThreeByteDeltaLead+(i>>16)); - length=2; } else { if(i<=0xffffff) { intBytes[0]=(char)BytesTrie::kFourByteDeltaLead; - length=3; } else { intBytes[0]=(char)BytesTrie::kFiveByteDeltaLead; intBytes[1]=(char)(i>>24); - length=4; + length=2; } - intBytes[1]=(char)(i>>16); + intBytes[length++]=(char)(i>>16); } - intBytes[1]=(char)(i>>8); + intBytes[length++]=(char)(i>>8); } intBytes[length++]=(char)i; - return write(intBytes, length); + return length; } U_NAMESPACE_END diff --git a/thirdparty/icu4c/common/charstr.cpp b/thirdparty/icu4c/common/charstr.cpp index 318a185b3f..c35622882c 100644 --- a/thirdparty/icu4c/common/charstr.cpp +++ b/thirdparty/icu4c/common/charstr.cpp @@ -14,6 +14,8 @@ * created by: Markus W. Scherer */ +#include <cstdlib> + #include "unicode/utypes.h" #include "unicode/putil.h" #include "charstr.h" @@ -141,6 +143,38 @@ CharString &CharString::append(const char *s, int32_t sLength, UErrorCode &error return *this; } +CharString &CharString::appendNumber(int32_t number, UErrorCode &status) { + if (number < 0) { + this->append('-', status); + if (U_FAILURE(status)) { + return *this; + } + } + + if (number == 0) { + this->append('0', status); + return *this; + } + + int32_t numLen = 0; + while (number != 0) { + int32_t residue = number % 10; + number /= 10; + this->append(std::abs(residue) + '0', status); + numLen++; + if (U_FAILURE(status)) { + return *this; + } + } + + int32_t start = this->length() - numLen, end = this->length() - 1; + while(start < end) { + std::swap(this->data()[start++], this->data()[end--]); + } + + return *this; +} + char *CharString::getAppendBuffer(int32_t minCapacity, int32_t desiredCapacityHint, int32_t &resultCapacity, diff --git a/thirdparty/icu4c/common/charstr.h b/thirdparty/icu4c/common/charstr.h index 6619faac61..175acd1c0a 100644 --- a/thirdparty/icu4c/common/charstr.h +++ b/thirdparty/icu4c/common/charstr.h @@ -127,6 +127,9 @@ public: return append(s.data(), s.length(), errorCode); } CharString &append(const char *s, int32_t sLength, UErrorCode &status); + + CharString &appendNumber(int32_t number, UErrorCode &status); + /** * Returns a writable buffer for appending and writes the buffer's capacity to * resultCapacity. Guarantees resultCapacity>=minCapacity if U_SUCCESS(). diff --git a/thirdparty/icu4c/common/cmemory.h b/thirdparty/icu4c/common/cmemory.h index a9d9424b4e..f03b7dcce6 100644 --- a/thirdparty/icu4c/common/cmemory.h +++ b/thirdparty/icu4c/common/cmemory.h @@ -31,14 +31,63 @@ #include <stddef.h> #include <string.h> #include "unicode/localpointer.h" +#include "uassert.h" #if U_DEBUG && defined(UPRV_MALLOC_COUNT) #include <stdio.h> #endif - -#define uprv_memcpy(dst, src, size) U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size) -#define uprv_memmove(dst, src, size) U_STANDARD_CPP_NAMESPACE memmove(dst, src, size) +// uprv_memcpy and uprv_memmove +#if defined(__clang__) +#define uprv_memcpy(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \ + /* Suppress warnings about addresses that will never be NULL */ \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Waddress\"") \ + U_ASSERT(dst != NULL); \ + U_ASSERT(src != NULL); \ + _Pragma("clang diagnostic pop") \ + U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size); \ +} UPRV_BLOCK_MACRO_END +#define uprv_memmove(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \ + /* Suppress warnings about addresses that will never be NULL */ \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Waddress\"") \ + U_ASSERT(dst != NULL); \ + U_ASSERT(src != NULL); \ + _Pragma("clang diagnostic pop") \ + U_STANDARD_CPP_NAMESPACE memmove(dst, src, size); \ +} UPRV_BLOCK_MACRO_END +#elif defined(__GNUC__) +#define uprv_memcpy(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \ + /* Suppress warnings about addresses that will never be NULL */ \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Waddress\"") \ + U_ASSERT(dst != NULL); \ + U_ASSERT(src != NULL); \ + _Pragma("GCC diagnostic pop") \ + U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size); \ +} UPRV_BLOCK_MACRO_END +#define uprv_memmove(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \ + /* Suppress warnings about addresses that will never be NULL */ \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Waddress\"") \ + U_ASSERT(dst != NULL); \ + U_ASSERT(src != NULL); \ + _Pragma("GCC diagnostic pop") \ + U_STANDARD_CPP_NAMESPACE memmove(dst, src, size); \ +} UPRV_BLOCK_MACRO_END +#else +#define uprv_memcpy(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \ + U_ASSERT(dst != NULL); \ + U_ASSERT(src != NULL); \ + U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size); \ +} UPRV_BLOCK_MACRO_END +#define uprv_memmove(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \ + U_ASSERT(dst != NULL); \ + U_ASSERT(src != NULL); \ + U_STANDARD_CPP_NAMESPACE memmove(dst, src, size); \ +} UPRV_BLOCK_MACRO_END +#endif /** * \def UPRV_LENGTHOF diff --git a/thirdparty/icu4c/common/dictbe.cpp b/thirdparty/icu4c/common/dictbe.cpp index b42cdf03fa..44285755f3 100644 --- a/thirdparty/icu4c/common/dictbe.cpp +++ b/thirdparty/icu4c/common/dictbe.cpp @@ -265,13 +265,9 @@ ThaiBreakEngine::divideUpDictionaryRange( UText *text, goto foundBest; } do { - int32_t wordsMatched = 1; if (words[(wordsFound + 1) % THAI_LOOKAHEAD].candidates(text, fDictionary, rangeEnd) > 0) { - if (wordsMatched < 2) { - // Followed by another dictionary word; mark first word as a good candidate - words[wordsFound%THAI_LOOKAHEAD].markCurrent(); - wordsMatched = 2; - } + // Followed by another dictionary word; mark first word as a good candidate + words[wordsFound%THAI_LOOKAHEAD].markCurrent(); // If we're already at the end of the range, we're done if ((int32_t)utext_getNativeIndex(text) >= rangeEnd) { @@ -503,13 +499,9 @@ LaoBreakEngine::divideUpDictionaryRange( UText *text, goto foundBest; } do { - int32_t wordsMatched = 1; if (words[(wordsFound + 1) % LAO_LOOKAHEAD].candidates(text, fDictionary, rangeEnd) > 0) { - if (wordsMatched < 2) { - // Followed by another dictionary word; mark first word as a good candidate - words[wordsFound%LAO_LOOKAHEAD].markCurrent(); - wordsMatched = 2; - } + // Followed by another dictionary word; mark first word as a good candidate + words[wordsFound%LAO_LOOKAHEAD].markCurrent(); // If we're already at the end of the range, we're done if ((int32_t)utext_getNativeIndex(text) >= rangeEnd) { @@ -699,13 +691,9 @@ BurmeseBreakEngine::divideUpDictionaryRange( UText *text, goto foundBest; } do { - int32_t wordsMatched = 1; if (words[(wordsFound + 1) % BURMESE_LOOKAHEAD].candidates(text, fDictionary, rangeEnd) > 0) { - if (wordsMatched < 2) { - // Followed by another dictionary word; mark first word as a good candidate - words[wordsFound%BURMESE_LOOKAHEAD].markCurrent(); - wordsMatched = 2; - } + // Followed by another dictionary word; mark first word as a good candidate + words[wordsFound%BURMESE_LOOKAHEAD].markCurrent(); // If we're already at the end of the range, we're done if ((int32_t)utext_getNativeIndex(text) >= rangeEnd) { @@ -908,13 +896,9 @@ KhmerBreakEngine::divideUpDictionaryRange( UText *text, goto foundBest; } do { - int32_t wordsMatched = 1; if (words[(wordsFound + 1) % KHMER_LOOKAHEAD].candidates(text, fDictionary, rangeEnd) > 0) { - if (wordsMatched < 2) { - // Followed by another dictionary word; mark first word as a good candidate - words[wordsFound % KHMER_LOOKAHEAD].markCurrent(); - wordsMatched = 2; - } + // Followed by another dictionary word; mark first word as a good candidate + words[wordsFound % KHMER_LOOKAHEAD].markCurrent(); // If we're already at the end of the range, we're done if ((int32_t)utext_getNativeIndex(text) >= rangeEnd) { diff --git a/thirdparty/icu4c/common/edits.cpp b/thirdparty/icu4c/common/edits.cpp index 95f0c19a72..92ca36fb5d 100644 --- a/thirdparty/icu4c/common/edits.cpp +++ b/thirdparty/icu4c/common/edits.cpp @@ -86,6 +86,7 @@ Edits &Edits::moveArray(Edits &src) U_NOEXCEPT { } Edits &Edits::operator=(const Edits &other) { + if (this == &other) { return *this; } // self-assignment: no-op length = other.length; delta = other.delta; numChanges = other.numChanges; diff --git a/thirdparty/icu4c/common/filteredbrk.cpp b/thirdparty/icu4c/common/filteredbrk.cpp index c07128cbce..25080f9d33 100644 --- a/thirdparty/icu4c/common/filteredbrk.cpp +++ b/thirdparty/icu4c/common/filteredbrk.cpp @@ -20,6 +20,7 @@ #include "ubrkimpl.h" // U_ICUDATA_BRKITR #include "uvector.h" #include "cmemory.h" +#include "umutex.h" U_NAMESPACE_BEGIN @@ -139,13 +140,30 @@ class SimpleFilteredSentenceBreakData : public UMemory { public: SimpleFilteredSentenceBreakData(UCharsTrie *forwards, UCharsTrie *backwards ) : fForwardsPartialTrie(forwards), fBackwardsTrie(backwards), refcount(1) { } - SimpleFilteredSentenceBreakData *incr() { refcount++; return this; } - SimpleFilteredSentenceBreakData *decr() { if((--refcount) <= 0) delete this; return 0; } - virtual ~SimpleFilteredSentenceBreakData(); + SimpleFilteredSentenceBreakData *incr() { + umtx_atomic_inc(&refcount); + return this; + } + SimpleFilteredSentenceBreakData *decr() { + if(umtx_atomic_dec(&refcount) <= 0) { + delete this; + } + return 0; + } + virtual ~SimpleFilteredSentenceBreakData(); + + bool hasForwardsPartialTrie() const { return fForwardsPartialTrie.isValid(); } + bool hasBackwardsTrie() const { return fBackwardsTrie.isValid(); } - LocalPointer<UCharsTrie> fForwardsPartialTrie; // Has ".a" for "a.M." - LocalPointer<UCharsTrie> fBackwardsTrie; // i.e. ".srM" for Mrs. - int32_t refcount; + const UCharsTrie &getForwardsPartialTrie() const { return *fForwardsPartialTrie; } + const UCharsTrie &getBackwardsTrie() const { return *fBackwardsTrie; } + +private: + // These tries own their data arrays. + // They are shared and must therefore not be modified. + LocalPointer<UCharsTrie> fForwardsPartialTrie; // Has ".a" for "a.M." + LocalPointer<UCharsTrie> fBackwardsTrie; // i.e. ".srM" for Mrs. + u_atomic_int32_t refcount; }; SimpleFilteredSentenceBreakData::~SimpleFilteredSentenceBreakData() {} @@ -244,7 +262,13 @@ SimpleFilteredSentenceBreakIterator::SimpleFilteredSentenceBreakIterator(BreakIt fData(new SimpleFilteredSentenceBreakData(forwards, backwards)), fDelegate(adopt) { - // all set.. + if (fData == nullptr) { + delete forwards; + delete backwards; + if (U_SUCCESS(status)) { + status = U_MEMORY_ALLOCATION_ERROR; + } + } } SimpleFilteredSentenceBreakIterator::~SimpleFilteredSentenceBreakIterator() { @@ -261,59 +285,62 @@ SimpleFilteredSentenceBreakIterator::breakExceptionAt(int32_t n) { int32_t bestValue = -1; // loops while 'n' points to an exception. utext_setNativeIndex(fText.getAlias(), n); // from n.. - fData->fBackwardsTrie->reset(); - UChar32 uch; //if(debug2) u_printf(" n@ %d\n", n); // Assume a space is following the '.' (so we handle the case: "Mr. /Brown") - if((uch=utext_previous32(fText.getAlias()))==(UChar32)0x0020) { // TODO: skip a class of chars here?? + if(utext_previous32(fText.getAlias())==u' ') { // TODO: skip a class of chars here?? // TODO only do this the 1st time? //if(debug2) u_printf("skipping prev: |%C| \n", (UChar)uch); } else { //if(debug2) u_printf("not skipping prev: |%C| \n", (UChar)uch); - uch = utext_next32(fText.getAlias()); + utext_next32(fText.getAlias()); //if(debug2) u_printf(" -> : |%C| \n", (UChar)uch); } - UStringTrieResult r = USTRINGTRIE_INTERMEDIATE_VALUE; - - while((uch=utext_previous32(fText.getAlias()))!=U_SENTINEL && // more to consume backwards and.. - USTRINGTRIE_HAS_NEXT(r=fData->fBackwardsTrie->nextForCodePoint(uch))) {// more in the trie - if(USTRINGTRIE_HAS_VALUE(r)) { // remember the best match so far - bestPosn = utext_getNativeIndex(fText.getAlias()); - bestValue = fData->fBackwardsTrie->getValue(); - } - //if(debug2) u_printf("rev< /%C/ cont?%d @%d\n", (UChar)uch, r, utext_getNativeIndex(fText.getAlias())); + { + // Do not modify the shared trie! + UCharsTrie iter(fData->getBackwardsTrie()); + UChar32 uch; + while((uch=utext_previous32(fText.getAlias()))!=U_SENTINEL) { // more to consume backwards + UStringTrieResult r = iter.nextForCodePoint(uch); + if(USTRINGTRIE_HAS_VALUE(r)) { // remember the best match so far + bestPosn = utext_getNativeIndex(fText.getAlias()); + bestValue = iter.getValue(); + } + if(!USTRINGTRIE_HAS_NEXT(r)) { + break; + } + //if(debug2) u_printf("rev< /%C/ cont?%d @%d\n", (UChar)uch, r, utext_getNativeIndex(fText.getAlias())); + } } - if(USTRINGTRIE_MATCHES(r)) { // exact match? - //if(debug2) u_printf("rev<?/%C/?end of seq.. r=%d, bestPosn=%d, bestValue=%d\n", (UChar)uch, r, bestPosn, bestValue); - bestValue = fData->fBackwardsTrie->getValue(); - bestPosn = utext_getNativeIndex(fText.getAlias()); - //if(debug2) u_printf("rev<+/%C/+end of seq.. r=%d, bestPosn=%d, bestValue=%d\n", (UChar)uch, r, bestPosn, bestValue); - } + //if(bestValue >= 0) { + //if(debug2) u_printf("rev<+/%C/+end of seq.. r=%d, bestPosn=%d, bestValue=%d\n", (UChar)uch, r, bestPosn, bestValue); + //} if(bestPosn>=0) { //if(debug2) u_printf("rev< /%C/ end of seq.. r=%d, bestPosn=%d, bestValue=%d\n", (UChar)uch, r, bestPosn, bestValue); //if(USTRINGTRIE_MATCHES(r)) { // matched - so, now what? - //int32_t bestValue = fBackwardsTrie->getValue(); + //int32_t bestValue = iter.getValue(); ////if(debug2) u_printf("rev< /%C/ matched, skip..%d bestValue=%d\n", (UChar)uch, r, bestValue); if(bestValue == kMATCH) { // exact match! //if(debug2) u_printf(" exact backward match\n"); return kExceptionHere; // See if the next is another exception. } else if(bestValue == kPARTIAL - && fData->fForwardsPartialTrie.isValid()) { // make sure there's a forward trie + && fData->hasForwardsPartialTrie()) { // make sure there's a forward trie //if(debug2) u_printf(" partial backward match\n"); // We matched the "Ph." in "Ph.D." - now we need to run everything through the forwards trie // to see if it matches something going forward. - fData->fForwardsPartialTrie->reset(); UStringTrieResult rfwd = USTRINGTRIE_INTERMEDIATE_VALUE; utext_setNativeIndex(fText.getAlias(), bestPosn); // hope that's close .. //if(debug2) u_printf("Retrying at %d\n", bestPosn); + // Do not modify the shared trie! + UCharsTrie iter(fData->getForwardsPartialTrie()); + UChar32 uch; while((uch=utext_next32(fText.getAlias()))!=U_SENTINEL && - USTRINGTRIE_HAS_NEXT(rfwd=fData->fForwardsPartialTrie->nextForCodePoint(uch))) { + USTRINGTRIE_HAS_NEXT(rfwd=iter.nextForCodePoint(uch))) { //if(debug2) u_printf("fwd> /%C/ cont?%d @%d\n", (UChar)uch, rfwd, utext_getNativeIndex(fText.getAlias())); } if(USTRINGTRIE_MATCHES(rfwd)) { @@ -339,7 +366,7 @@ SimpleFilteredSentenceBreakIterator::breakExceptionAt(int32_t n) { int32_t SimpleFilteredSentenceBreakIterator::internalNext(int32_t n) { if(n == UBRK_DONE || // at end or - fData->fBackwardsTrie.isNull()) { // .. no backwards table loaded == no exceptions + !fData->hasBackwardsTrie()) { // .. no backwards table loaded == no exceptions return n; } // OK, do we need to break here? @@ -369,7 +396,7 @@ SimpleFilteredSentenceBreakIterator::internalNext(int32_t n) { int32_t SimpleFilteredSentenceBreakIterator::internalPrev(int32_t n) { if(n == 0 || n == UBRK_DONE || // at end or - fData->fBackwardsTrie.isNull()) { // .. no backwards table loaded == no exceptions + !fData->hasBackwardsTrie()) { // .. no backwards table loaded == no exceptions return n; } // OK, do we need to break here? @@ -420,7 +447,7 @@ SimpleFilteredSentenceBreakIterator::previous(void) { UBool SimpleFilteredSentenceBreakIterator::isBoundary(int32_t offset) { if (!fDelegate->isBoundary(offset)) return false; // no break to suppress - if (fData->fBackwardsTrie.isNull()) return true; // no data = no suppressions + if (!fData->hasBackwardsTrie()) return true; // no data = no suppressions UErrorCode status = U_ZERO_ERROR; resetState(status); diff --git a/thirdparty/icu4c/common/hash.h b/thirdparty/icu4c/common/hash.h index f02cb7087a..b927ddb3c3 100644 --- a/thirdparty/icu4c/common/hash.h +++ b/thirdparty/icu4c/common/hash.h @@ -85,16 +85,22 @@ public: inline int32_t puti(const UnicodeString& key, int32_t value, UErrorCode& status); + inline int32_t putiAllowZero(const UnicodeString& key, int32_t value, UErrorCode& status); + inline void* get(const UnicodeString& key) const; inline int32_t geti(const UnicodeString& key) const; + inline int32_t getiAndFound(const UnicodeString& key, UBool &found) const; + inline void* remove(const UnicodeString& key); inline int32_t removei(const UnicodeString& key); inline void removeAll(void); + inline UBool containsKey(const UnicodeString& key) const; + inline const UHashElement* find(const UnicodeString& key) const; /** @@ -203,6 +209,11 @@ inline int32_t Hashtable::puti(const UnicodeString& key, int32_t value, UErrorCo return uhash_puti(hash, new UnicodeString(key), value, &status); } +inline int32_t Hashtable::putiAllowZero(const UnicodeString& key, int32_t value, + UErrorCode& status) { + return uhash_putiAllowZero(hash, new UnicodeString(key), value, &status); +} + inline void* Hashtable::get(const UnicodeString& key) const { return uhash_get(hash, &key); } @@ -211,6 +222,10 @@ inline int32_t Hashtable::geti(const UnicodeString& key) const { return uhash_geti(hash, &key); } +inline int32_t Hashtable::getiAndFound(const UnicodeString& key, UBool &found) const { + return uhash_getiAndFound(hash, &key, &found); +} + inline void* Hashtable::remove(const UnicodeString& key) { return uhash_remove(hash, &key); } @@ -219,6 +234,10 @@ inline int32_t Hashtable::removei(const UnicodeString& key) { return uhash_removei(hash, &key); } +inline UBool Hashtable::containsKey(const UnicodeString& key) const { + return uhash_containsKey(hash, &key); +} + inline const UHashElement* Hashtable::find(const UnicodeString& key) const { return uhash_find(hash, &key); } diff --git a/thirdparty/icu4c/common/localematcher.cpp b/thirdparty/icu4c/common/localematcher.cpp index 5795cbf87e..132aee290e 100644 --- a/thirdparty/icu4c/common/localematcher.cpp +++ b/thirdparty/icu4c/common/localematcher.cpp @@ -345,9 +345,8 @@ UBool compareLSRs(const UHashTok t1, const UHashTok t2) { int32_t LocaleMatcher::putIfAbsent(const LSR &lsr, int32_t i, int32_t suppLength, UErrorCode &errorCode) { if (U_FAILURE(errorCode)) { return suppLength; } - int32_t index = uhash_geti(supportedLsrToIndex, &lsr); - if (index == 0) { - uhash_puti(supportedLsrToIndex, const_cast<LSR *>(&lsr), i + 1, &errorCode); + if (!uhash_containsKey(supportedLsrToIndex, &lsr)) { + uhash_putiAllowZero(supportedLsrToIndex, const_cast<LSR *>(&lsr), i, &errorCode); if (U_SUCCESS(errorCode)) { supportedLSRs[suppLength] = &lsr; supportedIndexes[suppLength++] = i; @@ -685,12 +684,11 @@ int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remai int32_t bestSupportedLsrIndex = -1; for (int32_t bestShiftedDistance = LocaleDistance::shiftDistance(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; + UBool found = false; + int32_t suppIndex = uhash_getiAndFound(supportedLsrToIndex, &desiredLSR, &found); + if (found) { if (remainingIter != nullptr) { remainingIter->rememberCurrent(desiredIndex, errorCode); } diff --git a/thirdparty/icu4c/common/localeprioritylist.cpp b/thirdparty/icu4c/common/localeprioritylist.cpp index 8916b121be..4455eedb75 100644 --- a/thirdparty/icu4c/common/localeprioritylist.cpp +++ b/thirdparty/icu4c/common/localeprioritylist.cpp @@ -187,17 +187,18 @@ bool LocalePriorityList::add(const Locale &locale, int32_t weight, UErrorCode &e if (U_FAILURE(errorCode)) { return false; } } LocalPointer<Locale> clone; - int32_t index = uhash_geti(map, &locale); - if (index != 0) { + UBool found = false; + int32_t index = uhash_getiAndFound(map, &locale, &found); + if (found) { // Duplicate: Remove the old item and append it anew. - LocaleAndWeight &lw = list->array[index - 1]; + LocaleAndWeight &lw = list->array[index]; clone.adoptInstead(lw.locale); lw.locale = nullptr; lw.weight = 0; ++numRemoved; } if (weight <= 0) { // do not add q=0 - if (index != 0) { + if (found) { // Not strictly necessary but cleaner. uhash_removei(map, &locale); } @@ -217,7 +218,7 @@ bool LocalePriorityList::add(const Locale &locale, int32_t weight, UErrorCode &e return false; } } - uhash_puti(map, clone.getAlias(), listLength + 1, &errorCode); + uhash_putiAllowZero(map, clone.getAlias(), listLength, &errorCode); if (U_FAILURE(errorCode)) { return false; } LocaleAndWeight &lw = list->array[listLength]; lw.locale = clone.orphan(); diff --git a/thirdparty/icu4c/common/locdispnames.cpp b/thirdparty/icu4c/common/locdispnames.cpp index 47c0667417..96af3f9aa8 100644 --- a/thirdparty/icu4c/common/locdispnames.cpp +++ b/thirdparty/icu4c/common/locdispnames.cpp @@ -698,7 +698,7 @@ uloc_getDisplayName(const char *locale, } /* end switch */ if (len>0) { - /* we addeed a component, so add separator and write it if there's room. */ + /* we added a component, so add separator and write it if there's room. */ if(len+sepLen<=cap) { const UChar * plimit = p + len; for (; p < plimit; p++) { diff --git a/thirdparty/icu4c/common/locid.cpp b/thirdparty/icu4c/common/locid.cpp index 874e4a7055..0d506293a9 100644 --- a/thirdparty/icu4c/common/locid.cpp +++ b/thirdparty/icu4c/common/locid.cpp @@ -254,7 +254,7 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Locale) Locale::~Locale() { - if (baseName != fullName) { + if ((baseName != fullName) && (baseName != fullNameBuffer)) { uprv_free(baseName); } baseName = NULL; @@ -466,7 +466,7 @@ Locale& Locale::operator=(const Locale& other) { } Locale& Locale::operator=(Locale&& other) U_NOEXCEPT { - if (baseName != fullName) uprv_free(baseName); + if ((baseName != fullName) && (baseName != fullNameBuffer)) uprv_free(baseName); if (fullName != fullNameBuffer) uprv_free(fullName); if (other.fullName == other.fullNameBuffer) { @@ -524,7 +524,7 @@ static const char* const KNOWN_CANONICALIZED[] = { "km", "km_KH", "kn", "kn_IN", "ko", "ko_KR", "ky", "ky_KG", "lo", "lo_LA", "lt", "lt_LT", "lv", "lv_LV", "mk", "mk_MK", "ml", "ml_IN", "mn", "mn_MN", "mr", "mr_IN", "ms", "ms_MY", "my", "my_MM", "nb", "nb_NO", "ne", "ne_NP", - "nl", "nl_NL", "or", "or_IN", "pa", "pa_IN", "pl", "pl_PL", "ps", "ps_AF", + "nl", "nl_NL", "no", "or", "or_IN", "pa", "pa_IN", "pl", "pl_PL", "ps", "ps_AF", "pt", "pt_BR", "pt_PT", "ro", "ro_RO", "ru", "ru_RU", "sd", "sd_IN", "si", "si_LK", "sk", "sk_SK", "sl", "sl_SI", "so", "so_SO", "sq", "sq_AL", "sr", "sr_Cyrl_RS", "sr_Latn", "sr_RS", "sv", "sv_SE", "sw", "sw_TZ", "ta", @@ -627,6 +627,17 @@ private: LocalMemory<const char*>& types, LocalMemory<int32_t>& replacementIndexes, int32_t &length, UErrorCode &status); + + // Read the subdivisionAlias data from alias to + // strings+types+replacementIndexes + // Allocate length items for types, to store the type field. + // Allocate length items for replacementIndexes, + // to store the index in the strings for the replacement variant. + void readSubdivisionAlias(UResourceBundle* alias, + UniqueCharStrings* strings, + LocalMemory<const char*>& types, + LocalMemory<int32_t>& replacementIndexes, + int32_t &length, UErrorCode &status); }; /** @@ -647,6 +658,7 @@ public: const CharStringMap& scriptMap() const { return script; } const CharStringMap& territoryMap() const { return territory; } const CharStringMap& variantMap() const { return variant; } + const CharStringMap& subdivisionMap() const { return subdivision; } static void U_CALLCONV loadData(UErrorCode &status); static UBool U_CALLCONV cleanup(); @@ -658,11 +670,13 @@ private: CharStringMap scriptMap, CharStringMap territoryMap, CharStringMap variantMap, + CharStringMap subdivisionMap, CharString* strings) : language(std::move(languageMap)), script(std::move(scriptMap)), territory(std::move(territoryMap)), variant(std::move(variantMap)), + subdivision(std::move(subdivisionMap)), strings(strings) { } @@ -676,6 +690,7 @@ private: CharStringMap script; CharStringMap territory; CharStringMap variant; + CharStringMap subdivision; CharString* strings; friend class AliasDataBuilder; @@ -867,6 +882,34 @@ AliasDataBuilder::readVariantAlias( } /** + * Read the subdivisionAlias data from alias to strings+types+replacementIndexes. + * Allocate length items for types, to store the type field. Allocate length + * items for replacementIndexes, to store the index in the strings for the + * replacement regions. + */ +void +AliasDataBuilder::readSubdivisionAlias( + UResourceBundle* alias, + UniqueCharStrings* strings, + LocalMemory<const char*>& types, + LocalMemory<int32_t>& replacementIndexes, + int32_t &length, + UErrorCode &status) +{ + return readAlias( + alias, strings, types, replacementIndexes, length, +#if U_DEBUG + [](const char* type) { + U_ASSERT(uprv_strlen(type) >= 3 && uprv_strlen(type) <= 8); + }, +#else + [](const char*) {}, +#endif + [](const UnicodeString&) { }, + status); +} + +/** * Initializes the alias data from the ICU resource bundles. The alias data * contains alias of language, country, script and variants. * @@ -905,12 +948,14 @@ AliasDataBuilder::build(UErrorCode &status) { ures_getByKey(metadataAlias.getAlias(), "territory", nullptr, &status)); LocalUResourceBundlePointer variantAlias( ures_getByKey(metadataAlias.getAlias(), "variant", nullptr, &status)); + LocalUResourceBundlePointer subdivisionAlias( + ures_getByKey(metadataAlias.getAlias(), "subdivision", nullptr, &status)); if (U_FAILURE(status)) { return nullptr; } int32_t languagesLength = 0, scriptLength = 0, territoryLength = 0, - variantLength = 0; + variantLength = 0, subdivisionLength = 0; // Read the languageAlias into languageTypes, languageReplacementIndexes // and strings @@ -955,6 +1000,16 @@ AliasDataBuilder::build(UErrorCode &status) { variantReplacementIndexes, variantLength, status); + // Read the subdivisionAlias into subdivisionTypes, subdivisionReplacementIndexes + // and strings + LocalMemory<const char*> subdivisionTypes; + LocalMemory<int32_t> subdivisionReplacementIndexes; + readSubdivisionAlias(subdivisionAlias.getAlias(), + &strings, + subdivisionTypes, + subdivisionReplacementIndexes, + subdivisionLength, status); + if (U_FAILURE(status)) { return nullptr; } @@ -994,6 +1049,14 @@ AliasDataBuilder::build(UErrorCode &status) { status); } + // Build the subdivisionMap from subdivisionTypes & subdivisionReplacementIndexes. + CharStringMap subdivisionMap(2, status); + for (int32_t i = 0; U_SUCCESS(status) && i < subdivisionLength; i++) { + subdivisionMap.put(subdivisionTypes[i], + strings.get(subdivisionReplacementIndexes[i]), + status); + } + if (U_FAILURE(status)) { return nullptr; } @@ -1004,6 +1067,7 @@ AliasDataBuilder::build(UErrorCode &status) { std::move(scriptMap), std::move(territoryMap), std::move(variantMap), + std::move(subdivisionMap), strings.orphanCharStrings()); if (data == nullptr) { @@ -1105,6 +1169,14 @@ private: // Replace by using variantAlias. bool replaceVariant(UErrorCode& status); + + // Replace by using subdivisionAlias. + bool replaceSubdivision(StringPiece subdivision, + CharString& output, UErrorCode& status); + + // Replace transformed extensions. + bool replaceTransformedExtensions( + CharString& transformedExtensions, CharString& output, UErrorCode& status); }; CharString& @@ -1294,7 +1366,6 @@ AliasReplacer::replaceLanguage( } } if (replacedExtensions != nullptr) { - // TODO(ICU-21292) // DO NOTHING // UTS35 does not specifiy what should we do if we have extensions in the // replacement. Currently we know only the following 4 "BCP47 LegacyRules" have @@ -1435,6 +1506,106 @@ AliasReplacer::replaceVariant(UErrorCode& status) return false; } +bool +AliasReplacer::replaceSubdivision( + StringPiece subdivision, CharString& output, UErrorCode& status) +{ + if (U_FAILURE(status)) { + return false; + } + const char *replacement = data->subdivisionMap().get(subdivision.data()); + if (replacement != nullptr) { + const char* firstSpace = uprv_strchr(replacement, ' '); + // Found replacement data for this subdivision. + size_t len = (firstSpace != nullptr) ? + (firstSpace - replacement) : uprv_strlen(replacement); + if (2 <= len && len <= 8) { + output.append(replacement, (int32_t)len, status); + if (2 == len) { + // Add 'zzzz' based on changes to UTS #35 for CLDR-14312. + output.append("zzzz", 4, status); + } + } + return true; + } + return false; +} + +bool +AliasReplacer::replaceTransformedExtensions( + CharString& transformedExtensions, CharString& output, UErrorCode& status) +{ + // The content of the transformedExtensions will be modified in this + // function to NULL-terminating (tkey-tvalue) pairs. + if (U_FAILURE(status)) { + return false; + } + int32_t len = transformedExtensions.length(); + const char* str = transformedExtensions.data(); + const char* tkey = ultag_getTKeyStart(str); + int32_t tlangLen = (tkey == str) ? 0 : + ((tkey == nullptr) ? len : static_cast<int32_t>((tkey - str - 1))); + CharStringByteSink sink(&output); + if (tlangLen > 0) { + Locale tlang = LocaleBuilder() + .setLanguageTag(StringPiece(str, tlangLen)) + .build(status); + tlang.canonicalize(status); + tlang.toLanguageTag(sink, status); + if (U_FAILURE(status)) { + return false; + } + T_CString_toLowerCase(output.data()); + } + if (tkey != nullptr) { + // We need to sort the tfields by tkey + UVector tfields(status); + if (U_FAILURE(status)) { + return false; + } + do { + const char* tvalue = uprv_strchr(tkey, '-'); + if (tvalue == nullptr) { + status = U_ILLEGAL_ARGUMENT_ERROR; + } + const char* nextTKey = ultag_getTKeyStart(tvalue); + if (nextTKey != nullptr) { + *((char*)(nextTKey-1)) = '\0'; // NULL terminate tvalue + } + tfields.insertElementAt((void*)tkey, tfields.size(), status); + if (U_FAILURE(status)) { + return false; + } + tkey = nextTKey; + } while (tkey != nullptr); + tfields.sort([](UElement e1, UElement e2) -> int8_t { + // uprv_strcmp return int and in some platform, such as arm64-v8a, + // it may return positive values > 127 which cause the casted value + // of int8_t negative. + int res = uprv_strcmp( + (const char*)e1.pointer, (const char*)e2.pointer); + return (res == 0) ? 0 : ((res > 0) ? 1 : -1); + }, status); + for (int32_t i = 0; i < tfields.size(); i++) { + if (output.length() > 0) { + output.append('-', status); + } + const char* tfield = (const char*) tfields.elementAt(i); + const char* tvalue = uprv_strchr(tfield, '-'); + // Split the "tkey-tvalue" pair string so that we can canonicalize the tvalue. + U_ASSERT(tvalue != nullptr); + *((char*)tvalue++) = '\0'; // NULL terminate tkey + output.append(tfield, status).append('-', status); + const char* bcpTValue = ulocimp_toBcpType(tfield, tvalue, nullptr, nullptr); + output.append((bcpTValue == nullptr) ? tvalue : bcpTValue, status); + } + } + if (U_FAILURE(status)) { + return false; + } + return true; +} + CharString& AliasReplacer::outputToString( CharString& out, UErrorCode status) @@ -1453,8 +1624,12 @@ AliasReplacer::outputToString( out.append(SEP_CHAR, status); } variants.sort([](UElement e1, UElement e2) -> int8_t { - return uprv_strcmp( + // uprv_strcmp return int and in some platform, such as arm64-v8a, + // it may return positive values > 127 which cause the casted value + // of int8_t negative. + int res = uprv_strcmp( (const char*)e1.pointer, (const char*)e2.pointer); + return (res == 0) ? 0 : ((res > 0) ? 1 : -1); }, status); int32_t variantsStart = out.length(); for (int32_t i = 0; i < variants.size(); i++) { @@ -1497,7 +1672,6 @@ AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode& status region = nullptr; } const char* variantsStr = locale.getVariant(); - const char* extensionsStr = locale_getKeywordsStart(locale.getName()); CharString variantsBuff(variantsStr, -1, status); if (!variantsBuff.isEmpty()) { if (U_FAILURE(status)) { return false; } @@ -1516,8 +1690,12 @@ AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode& status // Sort the variants variants.sort([](UElement e1, UElement e2) -> int8_t { - return uprv_strcmp( + // uprv_strcmp return int and in some platform, such as arm64-v8a, + // it may return positive values > 127 which cause the casted value + // of int8_t negative. + int res = uprv_strcmp( (const char*)e1.pointer, (const char*)e2.pointer); + return (res == 0) ? 0 : ((res > 0) ? 1 : -1); }, status); // A changed count to assert when loop too many times. @@ -1561,11 +1739,52 @@ AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode& status if (U_FAILURE(status)) { return false; } // Nothing changed and we know the order of the vaiants are not change // because we have no variant or only one. - if (changed == 0 && variants.size() <= 1) { + const char* extensionsStr = locale_getKeywordsStart(locale.getName()); + if (changed == 0 && variants.size() <= 1 && extensionsStr == nullptr) { return false; } outputToString(out, status); + if (U_FAILURE(status)) { + return false; + } if (extensionsStr != nullptr) { + changed = 0; + Locale temp(locale); + LocalPointer<icu::StringEnumeration> iter(locale.createKeywords(status)); + if (U_SUCCESS(status) && !iter.isNull()) { + const char* key; + while ((key = iter->next(nullptr, status)) != nullptr) { + if (uprv_strcmp("sd", key) == 0 || uprv_strcmp("rg", key) == 0 || + uprv_strcmp("t", key) == 0) { + CharString value; + CharStringByteSink valueSink(&value); + locale.getKeywordValue(key, valueSink, status); + if (U_FAILURE(status)) { + status = U_ZERO_ERROR; + continue; + } + CharString replacement; + if (uprv_strlen(key) == 2) { + if (replaceSubdivision(value.toStringPiece(), replacement, status)) { + changed++; + temp.setKeywordValue(key, replacement.data(), status); + } + } else { + U_ASSERT(uprv_strcmp(key, "t") == 0); + if (replaceTransformedExtensions(value, replacement, status)) { + changed++; + temp.setKeywordValue(key, replacement.data(), status); + } + } + if (U_FAILURE(status)) { + return false; + } + } + } + } + if (changed != 0) { + extensionsStr = locale_getKeywordsStart(temp.getName()); + } out.append(extensionsStr, status); } if (U_FAILURE(status)) { @@ -1573,8 +1792,6 @@ AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode& status } // If the tag is not changed, return. if (uprv_strcmp(out.data(), locale.getName()) == 0) { - U_ASSERT(changed == 0); - U_ASSERT(variants.size() > 1); out.clear(); return false; } @@ -1636,7 +1853,7 @@ Locale& Locale::init(const char* localeID, UBool canonicalize) { fIsBogus = FALSE; /* Free our current storage */ - if (baseName != fullName) { + if ((baseName != fullName) && (baseName != fullNameBuffer)) { uprv_free(baseName); } baseName = NULL; @@ -1672,6 +1889,7 @@ Locale& Locale::init(const char* localeID, UBool canonicalize) uloc_getName(localeID, fullName, sizeof(fullNameBuffer), &err); if(err == U_BUFFER_OVERFLOW_ERROR || length >= (int32_t)sizeof(fullNameBuffer)) { + U_ASSERT(baseName == nullptr); /*Go to heap for the fullName if necessary*/ fullName = (char *)uprv_malloc(sizeof(char)*(length + 1)); if(fullName == 0) { @@ -1825,7 +2043,7 @@ Locale::hashCode() const void Locale::setToBogus() { /* Free our current storage */ - if(baseName != fullName) { + if((baseName != fullName) && (baseName != fullNameBuffer)) { uprv_free(baseName); } baseName = NULL; diff --git a/thirdparty/icu4c/common/loclikelysubtags.cpp b/thirdparty/icu4c/common/loclikelysubtags.cpp index a031bfa587..aa592e6ea8 100644 --- a/thirdparty/icu4c/common/loclikelysubtags.cpp +++ b/thirdparty/icu4c/common/loclikelysubtags.cpp @@ -320,7 +320,8 @@ XLikelySubtags::~XLikelySubtags() { 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... + // Private use language tag x-subtag-subtag... which CLDR changes to + // und-x-subtag-subtag... return LSR(name, "", "", LSR::EXPLICIT_LSR); } return makeMaximizedLsr(locale.getLanguage(), locale.getScript(), locale.getCountry(), diff --git a/thirdparty/icu4c/common/norm2allmodes.h b/thirdparty/icu4c/common/norm2allmodes.h index e8bd52c6ae..584835da57 100644 --- a/thirdparty/icu4c/common/norm2allmodes.h +++ b/thirdparty/icu4c/common/norm2allmodes.h @@ -38,7 +38,7 @@ public: virtual UnicodeString & normalize(const UnicodeString &src, UnicodeString &dest, - UErrorCode &errorCode) const { + UErrorCode &errorCode) const U_OVERRIDE { if(U_FAILURE(errorCode)) { dest.setToBogus(); return dest; @@ -64,13 +64,13 @@ public: virtual UnicodeString & normalizeSecondAndAppend(UnicodeString &first, const UnicodeString &second, - UErrorCode &errorCode) const { + UErrorCode &errorCode) const U_OVERRIDE { return normalizeSecondAndAppend(first, second, true, errorCode); } virtual UnicodeString & append(UnicodeString &first, const UnicodeString &second, - UErrorCode &errorCode) const { + UErrorCode &errorCode) const U_OVERRIDE { return normalizeSecondAndAppend(first, second, false, errorCode); } UnicodeString & @@ -107,7 +107,7 @@ public: UnicodeString &safeMiddle, ReorderingBuffer &buffer, UErrorCode &errorCode) const = 0; virtual UBool - getDecomposition(UChar32 c, UnicodeString &decomposition) const { + getDecomposition(UChar32 c, UnicodeString &decomposition) const U_OVERRIDE { UChar buffer[4]; int32_t length; const UChar *d=impl.getDecomposition(c, buffer, length); @@ -122,7 +122,7 @@ public: return true; } virtual UBool - getRawDecomposition(UChar32 c, UnicodeString &decomposition) const { + getRawDecomposition(UChar32 c, UnicodeString &decomposition) const U_OVERRIDE { UChar buffer[30]; int32_t length; const UChar *d=impl.getRawDecomposition(c, buffer, length); @@ -137,18 +137,18 @@ public: return true; } virtual UChar32 - composePair(UChar32 a, UChar32 b) const { + composePair(UChar32 a, UChar32 b) const U_OVERRIDE { return impl.composePair(a, b); } virtual uint8_t - getCombiningClass(UChar32 c) const { + getCombiningClass(UChar32 c) const U_OVERRIDE { return impl.getCC(impl.getNorm16(c)); } // quick checks virtual UBool - isNormalized(const UnicodeString &s, UErrorCode &errorCode) const { + isNormalized(const UnicodeString &s, UErrorCode &errorCode) const U_OVERRIDE { if(U_FAILURE(errorCode)) { return false; } @@ -161,11 +161,11 @@ public: return sLimit==spanQuickCheckYes(sArray, sLimit, errorCode); } virtual UNormalizationCheckResult - quickCheck(const UnicodeString &s, UErrorCode &errorCode) const { + quickCheck(const UnicodeString &s, UErrorCode &errorCode) const U_OVERRIDE { return Normalizer2WithImpl::isNormalized(s, errorCode) ? UNORM_YES : UNORM_NO; } virtual int32_t - spanQuickCheckYes(const UnicodeString &s, UErrorCode &errorCode) const { + spanQuickCheckYes(const UnicodeString &s, UErrorCode &errorCode) const U_OVERRIDE { if(U_FAILURE(errorCode)) { return 0; } @@ -194,27 +194,57 @@ public: private: virtual void normalize(const UChar *src, const UChar *limit, - ReorderingBuffer &buffer, UErrorCode &errorCode) const { + ReorderingBuffer &buffer, UErrorCode &errorCode) const U_OVERRIDE { impl.decompose(src, limit, &buffer, errorCode); } using Normalizer2WithImpl::normalize; // Avoid warning about hiding base class function. virtual void normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize, UnicodeString &safeMiddle, - ReorderingBuffer &buffer, UErrorCode &errorCode) const { + ReorderingBuffer &buffer, UErrorCode &errorCode) const U_OVERRIDE { impl.decomposeAndAppend(src, limit, doNormalize, safeMiddle, buffer, errorCode); } + + void + normalizeUTF8(uint32_t options, StringPiece src, ByteSink &sink, + Edits *edits, UErrorCode &errorCode) const U_OVERRIDE { + if (U_FAILURE(errorCode)) { + return; + } + if (edits != nullptr && (options & U_EDITS_NO_RESET) == 0) { + edits->reset(); + } + const uint8_t *s = reinterpret_cast<const uint8_t *>(src.data()); + impl.decomposeUTF8(options, s, s + src.length(), &sink, edits, errorCode); + sink.Flush(); + } + virtual UBool + isNormalizedUTF8(StringPiece sp, UErrorCode &errorCode) const U_OVERRIDE { + if(U_FAILURE(errorCode)) { + return false; + } + const uint8_t *s = reinterpret_cast<const uint8_t *>(sp.data()); + const uint8_t *sLimit = s + sp.length(); + return sLimit == impl.decomposeUTF8(0, s, sLimit, nullptr, nullptr, errorCode); + } + virtual const UChar * - spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCode) const { + spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCode) const U_OVERRIDE { return impl.decompose(src, limit, NULL, errorCode); } using Normalizer2WithImpl::spanQuickCheckYes; // Avoid warning about hiding base class function. - virtual UNormalizationCheckResult getQuickCheck(UChar32 c) const { + virtual UNormalizationCheckResult getQuickCheck(UChar32 c) const U_OVERRIDE { return impl.isDecompYes(impl.getNorm16(c)) ? UNORM_YES : UNORM_NO; } - virtual UBool hasBoundaryBefore(UChar32 c) const { return impl.hasDecompBoundaryBefore(c); } - virtual UBool hasBoundaryAfter(UChar32 c) const { return impl.hasDecompBoundaryAfter(c); } - virtual UBool isInert(UChar32 c) const { return impl.isDecompInert(c); } + virtual UBool hasBoundaryBefore(UChar32 c) const U_OVERRIDE { + return impl.hasDecompBoundaryBefore(c); + } + virtual UBool hasBoundaryAfter(UChar32 c) const U_OVERRIDE { + return impl.hasDecompBoundaryAfter(c); + } + virtual UBool isInert(UChar32 c) const U_OVERRIDE { + return impl.isDecompInert(c); + } }; class ComposeNormalizer2 : public Normalizer2WithImpl { @@ -321,24 +351,30 @@ public: private: virtual void normalize(const UChar *src, const UChar *limit, - ReorderingBuffer &buffer, UErrorCode &errorCode) const { + ReorderingBuffer &buffer, UErrorCode &errorCode) const U_OVERRIDE { impl.makeFCD(src, limit, &buffer, errorCode); } using Normalizer2WithImpl::normalize; // Avoid warning about hiding base class function. virtual void normalizeAndAppend(const UChar *src, const UChar *limit, UBool doNormalize, UnicodeString &safeMiddle, - ReorderingBuffer &buffer, UErrorCode &errorCode) const { + ReorderingBuffer &buffer, UErrorCode &errorCode) const U_OVERRIDE { impl.makeFCDAndAppend(src, limit, doNormalize, safeMiddle, buffer, errorCode); } virtual const UChar * - spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCode) const { + spanQuickCheckYes(const UChar *src, const UChar *limit, UErrorCode &errorCode) const U_OVERRIDE { return impl.makeFCD(src, limit, NULL, errorCode); } using Normalizer2WithImpl::spanQuickCheckYes; // Avoid warning about hiding base class function. - virtual UBool hasBoundaryBefore(UChar32 c) const { return impl.hasFCDBoundaryBefore(c); } - virtual UBool hasBoundaryAfter(UChar32 c) const { return impl.hasFCDBoundaryAfter(c); } - virtual UBool isInert(UChar32 c) const { return impl.isFCDInert(c); } + virtual UBool hasBoundaryBefore(UChar32 c) const U_OVERRIDE { + return impl.hasFCDBoundaryBefore(c); + } + virtual UBool hasBoundaryAfter(UChar32 c) const U_OVERRIDE { + return impl.hasFCDBoundaryAfter(c); + } + virtual UBool isInert(UChar32 c) const U_OVERRIDE { + return impl.isFCDInert(c); + } }; struct Norm2AllModes : public UMemory { diff --git a/thirdparty/icu4c/common/normalizer2impl.cpp b/thirdparty/icu4c/common/normalizer2impl.cpp index cbf6b4d980..c0ad5c69f3 100644 --- a/thirdparty/icu4c/common/normalizer2impl.cpp +++ b/thirdparty/icu4c/common/normalizer2impl.cpp @@ -731,9 +731,131 @@ UBool Normalizer2Impl::decompose(UChar32 c, uint16_t norm16, return buffer.append((const UChar *)mapping+1, length, TRUE, leadCC, trailCC, errorCode); } +// Dual functionality: +// sink != nullptr: normalize +// sink == nullptr: isNormalized/spanQuickCheckYes +const uint8_t * +Normalizer2Impl::decomposeUTF8(uint32_t options, + const uint8_t *src, const uint8_t *limit, + ByteSink *sink, Edits *edits, UErrorCode &errorCode) const { + U_ASSERT(limit != nullptr); + UnicodeString s16; + uint8_t minNoLead = leadByteForCP(minDecompNoCP); + + const uint8_t *prevBoundary = src; + // only for quick check + uint8_t prevCC = 0; + + for (;;) { + // Fast path: Scan over a sequence of characters below the minimum "no" code point, + // or with (decompYes && ccc==0) properties. + const uint8_t *fastStart = src; + const uint8_t *prevSrc; + uint16_t norm16 = 0; + + for (;;) { + if (src == limit) { + if (prevBoundary != limit && sink != nullptr) { + ByteSinkUtil::appendUnchanged(prevBoundary, limit, + *sink, options, edits, errorCode); + } + return src; + } + if (*src < minNoLead) { + ++src; + } else { + prevSrc = src; + UCPTRIE_FAST_U8_NEXT(normTrie, UCPTRIE_16, src, limit, norm16); + if (!isMostDecompYesAndZeroCC(norm16)) { + break; + } + } + } + // isMostDecompYesAndZeroCC(norm16) is false, that is, norm16>=minYesNo, + // and the current character at [prevSrc..src[ is not a common case with cc=0 + // (MIN_NORMAL_MAYBE_YES or JAMO_VT). + // It could still be a maybeYes with cc=0. + if (prevSrc != fastStart) { + // The fast path looped over yes/0 characters before the current one. + if (sink != nullptr && + !ByteSinkUtil::appendUnchanged(prevBoundary, prevSrc, + *sink, options, edits, errorCode)) { + break; + } + prevBoundary = prevSrc; + prevCC = 0; + } + + // Medium-fast path: Quick check. + if (isMaybeOrNonZeroCC(norm16)) { + // Does not decompose. + uint8_t cc = getCCFromYesOrMaybe(norm16); + if (prevCC <= cc || cc == 0) { + prevCC = cc; + if (cc <= 1) { + if (sink != nullptr && + !ByteSinkUtil::appendUnchanged(prevBoundary, src, + *sink, options, edits, errorCode)) { + break; + } + prevBoundary = src; + } + continue; + } + } + if (sink == nullptr) { + return prevBoundary; // quick check: "no" or cc out of order + } + + // Slow path + // Decompose up to and including the current character. + if (prevBoundary != prevSrc && norm16HasDecompBoundaryBefore(norm16)) { + if (!ByteSinkUtil::appendUnchanged(prevBoundary, prevSrc, + *sink, options, edits, errorCode)) { + break; + } + prevBoundary = prevSrc; + } + ReorderingBuffer buffer(*this, s16, errorCode); + if (U_FAILURE(errorCode)) { + break; + } + decomposeShort(prevBoundary, src, STOP_AT_LIMIT, FALSE /* onlyContiguous */, + buffer, errorCode); + // Decompose until the next boundary. + if (buffer.getLastCC() > 1) { + src = decomposeShort(src, limit, STOP_AT_DECOMP_BOUNDARY, FALSE /* onlyContiguous */, + buffer, errorCode); + } + if (U_FAILURE(errorCode)) { + break; + } + if ((src - prevSrc) > INT32_MAX) { // guard before buffer.equals() + errorCode = U_INDEX_OUTOFBOUNDS_ERROR; + break; + } + // We already know there was a change if the original character decomposed; + // otherwise compare. + if (isMaybeOrNonZeroCC(norm16) && buffer.equals(prevBoundary, src)) { + if (!ByteSinkUtil::appendUnchanged(prevBoundary, src, + *sink, options, edits, errorCode)) { + break; + } + } else { + if (!ByteSinkUtil::appendChange(prevBoundary, src, buffer.getStart(), buffer.length(), + *sink, edits, errorCode)) { + break; + } + } + prevBoundary = src; + prevCC = 0; + } + return src; +} + const uint8_t * Normalizer2Impl::decomposeShort(const uint8_t *src, const uint8_t *limit, - UBool stopAtCompBoundary, UBool onlyContiguous, + StopAt stopAt, UBool onlyContiguous, ReorderingBuffer &buffer, UErrorCode &errorCode) const { if (U_FAILURE(errorCode)) { return nullptr; @@ -746,21 +868,28 @@ Normalizer2Impl::decomposeShort(const uint8_t *src, const uint8_t *limit, UChar32 c = U_SENTINEL; if (norm16 >= limitNoNo) { if (isMaybeOrNonZeroCC(norm16)) { - // No boundaries around this character. + // No comp boundaries around this character. + uint8_t cc = getCCFromYesOrMaybe(norm16); + if (cc == 0 && stopAt == STOP_AT_DECOMP_BOUNDARY) { + return prevSrc; + } c = codePointFromValidUTF8(prevSrc, src); - if (!buffer.append(c, getCCFromYesOrMaybe(norm16), errorCode)) { + if (!buffer.append(c, cc, errorCode)) { return nullptr; } + if (stopAt == STOP_AT_DECOMP_BOUNDARY && buffer.getLastCC() <= 1) { + return src; + } continue; } // Maps to an isCompYesAndZeroCC. - if (stopAtCompBoundary) { + if (stopAt != STOP_AT_LIMIT) { return prevSrc; } c = codePointFromValidUTF8(prevSrc, src); c = mapAlgorithmic(c, norm16); norm16 = getRawNorm16(c); - } else if (stopAtCompBoundary && norm16 < minNoNoCompNoMaybeCC) { + } else if (stopAt != STOP_AT_LIMIT && norm16 < minNoNoCompNoMaybeCC) { return prevSrc; } // norm16!=INERT guarantees that [prevSrc, src[ is valid UTF-8. @@ -768,7 +897,8 @@ Normalizer2Impl::decomposeShort(const uint8_t *src, const uint8_t *limit, // its norm16==INERT is normalization-inert, // so it gets copied unchanged in the fast path, // and we stop the slow path where invalid UTF-8 begins. - U_ASSERT(norm16 != INERT); + // c >= 0 is the result of an algorithmic mapping. + U_ASSERT(c >= 0 || norm16 != INERT); if (norm16 < minYesNo) { if (c < 0) { c = codePointFromValidUTF8(prevSrc, src); @@ -798,11 +928,15 @@ Normalizer2Impl::decomposeShort(const uint8_t *src, const uint8_t *limit, } else { leadCC = 0; } + if (leadCC == 0 && stopAt == STOP_AT_DECOMP_BOUNDARY) { + return prevSrc; + } if (!buffer.append((const char16_t *)mapping+1, length, TRUE, leadCC, trailCC, errorCode)) { return nullptr; } } - if (stopAtCompBoundary && norm16HasCompBoundaryAfter(norm16, onlyContiguous)) { + if ((stopAt == STOP_AT_COMP_BOUNDARY && norm16HasCompBoundaryAfter(norm16, onlyContiguous)) || + (stopAt == STOP_AT_DECOMP_BOUNDARY && buffer.getLastCC() <= 1)) { return src; } } @@ -1954,10 +2088,10 @@ Normalizer2Impl::composeUTF8(uint32_t options, UBool onlyContiguous, break; } // We know there is not a boundary here. - decomposeShort(prevSrc, src, FALSE /* !stopAtCompBoundary */, onlyContiguous, + decomposeShort(prevSrc, src, STOP_AT_LIMIT, onlyContiguous, buffer, errorCode); // Decompose until the next boundary. - src = decomposeShort(src, limit, TRUE /* stopAtCompBoundary */, onlyContiguous, + src = decomposeShort(src, limit, STOP_AT_COMP_BOUNDARY, onlyContiguous, buffer, errorCode); if (U_FAILURE(errorCode)) { break; diff --git a/thirdparty/icu4c/common/normalizer2impl.h b/thirdparty/icu4c/common/normalizer2impl.h index 4218a30a34..bdb6767a92 100644 --- a/thirdparty/icu4c/common/normalizer2impl.h +++ b/thirdparty/icu4c/common/normalizer2impl.h @@ -491,6 +491,12 @@ public: UnicodeString &safeMiddle, ReorderingBuffer &buffer, UErrorCode &errorCode) const; + + /** sink==nullptr: isNormalized()/spanQuickCheckYes() */ + const uint8_t *decomposeUTF8(uint32_t options, + const uint8_t *src, const uint8_t *limit, + ByteSink *sink, Edits *edits, UErrorCode &errorCode) const; + UBool compose(const UChar *src, const UChar *limit, UBool onlyContiguous, UBool doCompose, @@ -649,6 +655,9 @@ private: UChar32 minNeedDataCP, ReorderingBuffer *buffer, UErrorCode &errorCode) const; + + enum StopAt { STOP_AT_LIMIT, STOP_AT_DECOMP_BOUNDARY, STOP_AT_COMP_BOUNDARY }; + const UChar *decomposeShort(const UChar *src, const UChar *limit, UBool stopAtCompBoundary, UBool onlyContiguous, ReorderingBuffer &buffer, UErrorCode &errorCode) const; @@ -656,7 +665,7 @@ private: ReorderingBuffer &buffer, UErrorCode &errorCode) const; const uint8_t *decomposeShort(const uint8_t *src, const uint8_t *limit, - UBool stopAtCompBoundary, UBool onlyContiguous, + StopAt stopAt, UBool onlyContiguous, ReorderingBuffer &buffer, UErrorCode &errorCode) const; static int32_t combine(const uint16_t *list, UChar32 trail); diff --git a/thirdparty/icu4c/common/pluralmap.h b/thirdparty/icu4c/common/pluralmap.h index d898ac4671..2a14a07af1 100644 --- a/thirdparty/icu4c/common/pluralmap.h +++ b/thirdparty/icu4c/common/pluralmap.h @@ -24,7 +24,7 @@ class U_COMMON_API PluralMapBase : public UMemory { public: /** * The names of all the plural categories. NONE is not an actual plural - * category, but rather represents the absense of a plural category. + * category, but rather represents the absence of a plural category. */ enum Category { NONE = -1, diff --git a/thirdparty/icu4c/common/putil.cpp b/thirdparty/icu4c/common/putil.cpp index 3ed6a05d22..ffcbbcce59 100644 --- a/thirdparty/icu4c/common/putil.cpp +++ b/thirdparty/icu4c/common/putil.cpp @@ -1139,7 +1139,7 @@ uprv_tzname(int n) #endif if (tzid != NULL && isValidOlsonID(tzid) #if U_PLATFORM == U_PF_SOLARIS - /* When TZ equals localtime on Solaris, check the /etc/localtime file. */ + /* Don't misinterpret TZ "localtime" on Solaris as a time zone name. */ && uprv_strcmp(tzid, TZ_ENV_CHECK) != 0 #endif ) { @@ -1361,7 +1361,7 @@ uprv_pathIsAbsolute(const char *path) /* Backup setting of ICU_DATA_DIR_PREFIX_ENV_VAR (needed for some Darwin ICU build environments) */ -#if U_PLATFORM_IS_DARWIN_BASED && TARGET_OS_SIMULATOR +#if U_PLATFORM_IS_DARWIN_BASED && defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR # if !defined(ICU_DATA_DIR_PREFIX_ENV_VAR) # define ICU_DATA_DIR_PREFIX_ENV_VAR "IPHONE_SIMULATOR_ROOT" # endif diff --git a/thirdparty/icu4c/common/putilimp.h b/thirdparty/icu4c/common/putilimp.h index a325c6c359..5b95a68418 100644 --- a/thirdparty/icu4c/common/putilimp.h +++ b/thirdparty/icu4c/common/putilimp.h @@ -527,7 +527,7 @@ U_CAPI void * U_EXPORT2 uprv_maximumPtr(void *base); * on the destination pointer and capacity cannot overflow. * * The pinned capacity must fulfill the following conditions (for positive capacities): - * - dest + capacity is a valid pointer according to the machine arcitecture (AS/400, 64-bit, etc.) + * - dest + capacity is a valid pointer according to the machine architecture (AS/400, 64-bit, etc.) * - (dest + capacity) >= dest * - The size (in bytes) of T[capacity] does not exceed 0x7fffffff * diff --git a/thirdparty/icu4c/common/rbbi.cpp b/thirdparty/icu4c/common/rbbi.cpp index 9b7e70c3cf..b821ca4463 100644 --- a/thirdparty/icu4c/common/rbbi.cpp +++ b/thirdparty/icu4c/common/rbbi.cpp @@ -812,7 +812,7 @@ int32_t RuleBasedBreakIterator::handleNext() { } #endif - // handleNext alway sets the break tag value. + // handleNext always sets the break tag value. // Set the default for it. fRuleStatusIndex = 0; diff --git a/thirdparty/icu4c/common/rbbi_cache.cpp b/thirdparty/icu4c/common/rbbi_cache.cpp index 63ff3001c7..44f19d8697 100644 --- a/thirdparty/icu4c/common/rbbi_cache.cpp +++ b/thirdparty/icu4c/common/rbbi_cache.cpp @@ -258,7 +258,7 @@ void RuleBasedBreakIterator::BreakCache::preceding(int32_t startPos, UErrorCode previous(status); } else { // seek() leaves the BreakCache positioned at the preceding boundary - // if the requested position is between two bounaries. + // if the requested position is between two boundaries. // current() pushes the BreakCache position out to the BreakIterator itself. U_ASSERT(startPos > fTextIdx); current(); diff --git a/thirdparty/icu4c/common/rbbiscan.cpp b/thirdparty/icu4c/common/rbbiscan.cpp index 9c406af671..45911b1cfe 100644 --- a/thirdparty/icu4c/common/rbbiscan.cpp +++ b/thirdparty/icu4c/common/rbbiscan.cpp @@ -284,7 +284,7 @@ UBool RBBIRuleScanner::doParseActions(int32_t action) case doEndAssign: { - // We have reached the end of an assignement statement. + // We have reached the end of an assignment statement. // Current scan char is the ';' that terminates the assignment. // Terminate expression, leaves expression parse tree rooted in TOS node. @@ -856,6 +856,10 @@ UChar32 RBBIRuleScanner::nextCharLL() { return (UChar32)-1; } ch = fRB->fRules.char32At(fNextIndex); + if (U_IS_SURROGATE(ch)) { + error(U_ILLEGAL_CHAR_FOUND); + return U_SENTINEL; + } fNextIndex = fRB->fRules.moveIndex32(fNextIndex, 1); if (ch == chCR || diff --git a/thirdparty/icu4c/common/rbbitblb.cpp b/thirdparty/icu4c/common/rbbitblb.cpp index 70e260fc08..dd76337bc6 100644 --- a/thirdparty/icu4c/common/rbbitblb.cpp +++ b/thirdparty/icu4c/common/rbbitblb.cpp @@ -151,7 +151,7 @@ void RBBITableBuilder::buildForwardTable() { // // calculate the functions nullable, firstpos, lastpos and followpos on // nodes in the parse tree. - // See the alogrithm description in Aho. + // See the algorithm description in Aho. // Understanding how this works by looking at the code alone will be // nearly impossible. // diff --git a/thirdparty/icu4c/common/resource.h b/thirdparty/icu4c/common/resource.h index 3795694412..48f5b9fa6e 100644 --- a/thirdparty/icu4c/common/resource.h +++ b/thirdparty/icu4c/common/resource.h @@ -274,8 +274,10 @@ public: * * @param key The key string of the enumeration-start resource. * Empty if the enumeration starts at the top level of the bundle. - * @param value Call getArray() or getTable() as appropriate. - * Then reuse for output values from Array and Table getters. + * @param value Call getArray() or getTable() as appropriate. Then reuse for + * output values from Array and Table getters. Note: ResourceTable and + * ResourceArray instances must outlive the ResourceValue instance for + * ResourceTracer to be happy. * @param noFallback true if the bundle has no parent; * that is, its top-level table has the nofallback attribute, * or it is the root bundle of a locale tree. diff --git a/thirdparty/icu4c/common/restrace.cpp b/thirdparty/icu4c/common/restrace.cpp index 5c6498850e..1f83372d68 100644 --- a/thirdparty/icu4c/common/restrace.cpp +++ b/thirdparty/icu4c/common/restrace.cpp @@ -54,6 +54,9 @@ void ResourceTracer::traceOpen() const { CharString& ResourceTracer::getFilePath(CharString& output, UErrorCode& status) const { if (fResB) { + // Note: if you get a segfault around here, check that ResourceTable and + // ResourceArray instances outlive ResourceValue instances referring to + // their contents: output.append(fResB->fData->fPath, status); output.append('/', status); output.append(fResB->fData->fName, status); diff --git a/thirdparty/icu4c/common/servnotf.h b/thirdparty/icu4c/common/servnotf.h index 305570c1e6..73ce38c772 100644 --- a/thirdparty/icu4c/common/servnotf.h +++ b/thirdparty/icu4c/common/servnotf.h @@ -82,7 +82,7 @@ public: /** * Add a listener to be notified when notifyChanged is called. * The listener must not be null. AcceptsListener must return - * true for the listener. Attempts to concurrently + * true for the listener. Attempts to concurrently * register the identical listener more than once will be * silently ignored. */ @@ -90,7 +90,7 @@ public: /** * Stop notifying this listener. The listener must - * not be null. Attemps to remove a listener that is + * not be null. Attempts to remove a listener that is * not registered will be silently ignored. */ virtual void removeListener(const EventListener* l, UErrorCode& status); diff --git a/thirdparty/icu4c/common/ubrk.cpp b/thirdparty/icu4c/common/ubrk.cpp index f8bdf5a6b6..bb5bdd1b50 100644 --- a/thirdparty/icu4c/common/ubrk.cpp +++ b/thirdparty/icu4c/common/ubrk.cpp @@ -174,6 +174,18 @@ ubrk_safeClone( return (UBreakIterator *)newBI; } +U_CAPI UBreakIterator * U_EXPORT2 +ubrk_clone(const UBreakIterator *bi, UErrorCode *status) { + if (U_FAILURE(*status)) { + return nullptr; + } + BreakIterator *newBI = ((BreakIterator *)bi)->clone(); + if (newBI == nullptr) { + *status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + return (UBreakIterator *)newBI; +} U_CAPI void U_EXPORT2 diff --git a/thirdparty/icu4c/common/ucase.cpp b/thirdparty/icu4c/common/ucase.cpp index 2b142f5bc2..4f4c274d60 100644 --- a/thirdparty/icu4c/common/ucase.cpp +++ b/thirdparty/icu4c/common/ucase.cpp @@ -681,7 +681,7 @@ ucase_isCaseSensitive(UChar32 c) { * - In [CoreProps], C has one of the properties Uppercase, or Lowercase * - Given D = NFD(C), then it is not the case that: * D = UCD_lower(D) = UCD_upper(D) = UCD_title(D) - * (This third criterium does not add any characters to the list + * (This third criterion does not add any characters to the list * for Unicode 3.2. Ignored.) * * D2. A character C is defined to be case-ignorable diff --git a/thirdparty/icu4c/common/uchar.cpp b/thirdparty/icu4c/common/uchar.cpp index eb14e4c75d..61e9c3d900 100644 --- a/thirdparty/icu4c/common/uchar.cpp +++ b/thirdparty/icu4c/common/uchar.cpp @@ -194,7 +194,7 @@ u_isISOControl(UChar32 c) { /* Some control characters that are used as space. */ #define IS_THAT_CONTROL_SPACE(c) \ - (c<=0x9f && ((c>=TAB && c<=CR) || (c>=0x1c && c <=0x1f) || c==NL)) + (c<=0x9f && ((c>=TAB && c<=CR) || (c>=0x1c && c <=0x1f) || c==0x85)) /* Java has decided that U+0085 New Line is not whitespace any more. */ #define IS_THAT_ASCII_CONTROL_SPACE(c) \ @@ -677,14 +677,14 @@ uchar_addPropertyStarts(const USetAdder *sa, UErrorCode *pErrorCode) { sa->add(sa->set, CR+1); /* range TAB..CR */ sa->add(sa->set, 0x1c); sa->add(sa->set, 0x1f+1); - USET_ADD_CP_AND_NEXT(sa, NL); + USET_ADD_CP_AND_NEXT(sa, 0x85); // NEXT LINE (NEL) /* add for u_isIDIgnorable() what was not added above */ - sa->add(sa->set, DEL); /* range DEL..NBSP-1, NBSP added below */ + sa->add(sa->set, 0x7f); /* range DEL..NBSP-1, NBSP added below */ sa->add(sa->set, HAIRSP); sa->add(sa->set, RLM+1); - sa->add(sa->set, INHSWAP); - sa->add(sa->set, NOMDIG+1); + sa->add(sa->set, 0x206a); // INHIBIT SYMMETRIC SWAPPING + sa->add(sa->set, 0x206f+1); // NOMINAL DIGIT SHAPES USET_ADD_CP_AND_NEXT(sa, ZWNBSP); /* add no-break spaces for u_isWhitespace() what was not added above */ @@ -693,23 +693,25 @@ uchar_addPropertyStarts(const USetAdder *sa, UErrorCode *pErrorCode) { USET_ADD_CP_AND_NEXT(sa, NNBSP); /* add for u_digit() */ - sa->add(sa->set, U_a); - sa->add(sa->set, U_z+1); - sa->add(sa->set, U_A); - sa->add(sa->set, U_Z+1); - sa->add(sa->set, U_FW_a); - sa->add(sa->set, U_FW_z+1); - sa->add(sa->set, U_FW_A); - sa->add(sa->set, U_FW_Z+1); + sa->add(sa->set, u'a'); + sa->add(sa->set, u'z'+1); + sa->add(sa->set, u'A'); + sa->add(sa->set, u'Z'+1); + // fullwidth + sa->add(sa->set, u'a'); + sa->add(sa->set, u'z'+1); + sa->add(sa->set, u'A'); + sa->add(sa->set, u'Z'+1); /* add for u_isxdigit() */ - sa->add(sa->set, U_f+1); - sa->add(sa->set, U_F+1); - sa->add(sa->set, U_FW_f+1); - sa->add(sa->set, U_FW_F+1); + sa->add(sa->set, u'f'+1); + sa->add(sa->set, u'F'+1); + // fullwidth + sa->add(sa->set, u'f'+1); + sa->add(sa->set, u'F'+1); /* add for UCHAR_DEFAULT_IGNORABLE_CODE_POINT what was not added above */ - sa->add(sa->set, WJ); /* range WJ..NOMDIG */ + sa->add(sa->set, 0x2060); /* range 2060..206f */ sa->add(sa->set, 0xfff0); sa->add(sa->set, 0xfffb+1); sa->add(sa->set, 0xe0000); diff --git a/thirdparty/icu4c/common/ucnv2022.cpp b/thirdparty/icu4c/common/ucnv2022.cpp index 169ad4c526..1726440b94 100644 --- a/thirdparty/icu4c/common/ucnv2022.cpp +++ b/thirdparty/icu4c/common/ucnv2022.cpp @@ -820,7 +820,7 @@ getKey_2022(char c,int32_t* key,int32_t* offset){ return INVALID_2022; } -/*runs through a state machine to determine the escape sequence - codepage correspondance +/*runs through a state machine to determine the escape sequence - codepage correspondence */ static void changeState_2022(UConverter* _this, @@ -1424,7 +1424,7 @@ toUnicodeCallback(UConverter *cnv, * KSC5601 : alias to ibm-949 mapping table * GB2312 : alias to ibm-1386 mapping table * ISO-8859-1 : Algorithmic implemented as LATIN1 case -* ISO-8859-7 : alisas to ibm-9409 mapping table +* ISO-8859-7 : alias to ibm-9409 mapping table */ /* preference order of JP charsets */ @@ -2324,7 +2324,7 @@ endloop: /*************************************************************** * Rules for ISO-2022-KR encoding * i) The KSC5601 designator sequence should appear only once in a file, -* at the begining of a line before any KSC5601 characters. This usually +* at the beginning of a line before any KSC5601 characters. This usually * means that it appears by itself on the first line of the file * ii) There are only 2 shifting sequences SO to shift into double byte mode * and SI to shift into single byte mode diff --git a/thirdparty/icu4c/common/ucnv_bld.cpp b/thirdparty/icu4c/common/ucnv_bld.cpp index 0e198892f1..d08eec7369 100644 --- a/thirdparty/icu4c/common/ucnv_bld.cpp +++ b/thirdparty/icu4c/common/ucnv_bld.cpp @@ -427,7 +427,7 @@ getAlgorithmicTypeFromName(const char *realName) #define UCNV_CACHE_LOAD_FACTOR 2 /* Puts the shared data in the static hashtable SHARED_DATA_HASHTABLE */ -/* Will always be called with the cnvCacheMutex alrady being held */ +/* Will always be called with the cnvCacheMutex already being held */ /* by the calling function. */ /* Stores the shared data in the SHARED_DATA_HASHTABLE * @param data The shared data diff --git a/thirdparty/icu4c/common/ucnv_err.cpp b/thirdparty/icu4c/common/ucnv_err.cpp index 6b738face5..e1f2b934aa 100644 --- a/thirdparty/icu4c/common/ucnv_err.cpp +++ b/thirdparty/icu4c/common/ucnv_err.cpp @@ -321,7 +321,7 @@ UCNV_FROM_U_CALLBACK_ESCAPE ( case UCNV_PRV_ESCAPE_CSS2: valueString[valueStringLength++] = (UChar) UNICODE_RS_CODEPOINT; /* adding \ */ valueStringLength += uprv_itou (valueString + valueStringLength, VALUE_STRING_LENGTH - valueStringLength, codePoint, 16, 0); - /* Always add space character, becase the next character might be whitespace, + /* Always add space character, because the next character might be whitespace, which would erroneously be considered the termination of the escape sequence. */ valueString[valueStringLength++] = (UChar) UNICODE_SPACE_CODEPOINT; break; diff --git a/thirdparty/icu4c/common/ucnv_lmb.cpp b/thirdparty/icu4c/common/ucnv_lmb.cpp index 168392837b..41317d1cc0 100644 --- a/thirdparty/icu4c/common/ucnv_lmb.cpp +++ b/thirdparty/icu4c/common/ucnv_lmb.cpp @@ -81,7 +81,7 @@ [G] D1 [D2] That is, a sometimes-optional 'group' byte, followed by 1 and sometimes 2 - data bytes. The maximum size of a LMBCS chjaracter is 3 bytes: + data bytes. The maximum size of a LMBCS character is 3 bytes: */ #define ULMBCS_CHARSIZE_MAX 3 /* @@ -164,7 +164,7 @@ beginning of internal 'system' range names: */ /* Then we needed a place to put all the other ansi control characters that must be moved to different values because LMBCS reserves those values for other purposes. To represent the control characters, we start -with a first byte of 0xF & add the control chaarcter value as the +with a first byte of 0xF & add the control character value as the second byte */ #define ULMBCS_GRP_CTRL 0x0F diff --git a/thirdparty/icu4c/common/ucnv_u7.cpp b/thirdparty/icu4c/common/ucnv_u7.cpp index 87ba8cf37e..de9f3f42ec 100644 --- a/thirdparty/icu4c/common/ucnv_u7.cpp +++ b/thirdparty/icu4c/common/ucnv_u7.cpp @@ -814,7 +814,7 @@ const UConverterSharedData _UTF7Data= * the use of "~" in some servers as a home directory indicator. * * 5) UTF-7 permits multiple alternate forms to represent the same - * string; in particular, printable US-ASCII chararacters can be + * string; in particular, printable US-ASCII characters can be * represented in encoded form. * * In modified UTF-7, printable US-ASCII characters except for "&" diff --git a/thirdparty/icu4c/common/ucnvisci.cpp b/thirdparty/icu4c/common/ucnvisci.cpp index 44a7c05a3c..ffb8c7ac3e 100644 --- a/thirdparty/icu4c/common/ucnvisci.cpp +++ b/thirdparty/icu4c/common/ucnvisci.cpp @@ -992,7 +992,7 @@ UConverter_fromUnicode_ISCII_OFFSETS_LOGIC( if (converterData->currentDeltaFromUnicode == PNJ_DELTA) { if (sourceChar == PNJ_TIPPI) { - /* Make sure Tippi is converterd to Bindi. */ + /* Make sure Tippi is converted to Bindi. */ sourceChar = PNJ_BINDI; } else if (sourceChar == PNJ_ADHAK) { /* This is for consonant cluster handling. */ @@ -1147,7 +1147,7 @@ static const uint16_t lookupTable[][2]={ /* is the code point valid in current script? */ \ if(sourceChar> ASCII_END && \ (validityTable[(targetUniChar & 0x7F)] & data->currentMaskToUnicode)==0){ \ - /* Vocallic RR is assigne in ISCII Telugu and Unicode */ \ + /* Vocallic RR is assigned in ISCII Telugu and Unicode */ \ if(data->currentDeltaToUnicode!=(TELUGU_DELTA) || \ targetUniChar!=VOCALLIC_RR){ \ targetUniChar=missingCharMarker; \ @@ -1272,7 +1272,7 @@ UConverter_toUnicode_ISCII_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, UErrorCo goto CALLBACK; } else if (*contextCharToUnicode==ISCII_INV) { if (sourceChar==ISCII_HALANT) { - targetUniChar = 0x0020; /* replace with space accoding to Indic FAQ */ + targetUniChar = 0x0020; /* replace with space according to Indic FAQ */ } else { targetUniChar = ZWJ; } diff --git a/thirdparty/icu4c/common/ucurr.cpp b/thirdparty/icu4c/common/ucurr.cpp index 0e14cddcff..20bbd51488 100644 --- a/thirdparty/icu4c/common/ucurr.cpp +++ b/thirdparty/icu4c/common/ucurr.cpp @@ -844,7 +844,7 @@ typedef struct { #endif -// Comparason function used in quick sort. +// Comparison function used in quick sort. static int U_CALLCONV currencyNameComparator(const void* a, const void* b) { const CurrencyNameStruct* currName_1 = (const CurrencyNameStruct*)a; const CurrencyNameStruct* currName_2 = (const CurrencyNameStruct*)b; @@ -1530,7 +1530,7 @@ uprv_parseCurrency(const char* locale, int32_t max = 0; int32_t matchIndex = -1; - // case in-sensitive comparision against currency names + // case in-sensitive comparison against currency names searchCurrencyName(currencyNames, total_currency_name_count, upperText, textLen, partialMatchLen, &max, &matchIndex); diff --git a/thirdparty/icu4c/common/uhash.cpp b/thirdparty/icu4c/common/uhash.cpp index 86311ceb0b..67c7c36354 100644 --- a/thirdparty/icu4c/common/uhash.cpp +++ b/thirdparty/icu4c/common/uhash.cpp @@ -133,8 +133,10 @@ static const float RESIZE_POLICY_RATIO_TABLE[6] = { * or a pointer. If a hint bit is zero, then the associated * token is assumed to be an integer. */ +#define HINT_BOTH_INTEGERS (0) #define HINT_KEY_POINTER (1) #define HINT_VALUE_POINTER (2) +#define HINT_ALLOW_ZERO (4) /******************************************************************** * PRIVATE Implementation @@ -479,8 +481,9 @@ _uhash_put(UHashtable *hash, goto err; } U_ASSERT(hash != NULL); - /* Cannot always check pointer here or iSeries sees NULL every time. */ - if ((hint & HINT_VALUE_POINTER) && value.pointer == NULL) { + if ((hint & HINT_VALUE_POINTER) ? + value.pointer == NULL : + value.integer == 0 && (hint & HINT_ALLOW_ZERO) == 0) { /* Disallow storage of NULL values, since NULL is returned by * get() to indicate an absent key. Storing NULL == removing. */ @@ -687,6 +690,28 @@ uhash_igeti(const UHashtable *hash, return _uhash_find(hash, keyholder, hash->keyHasher(keyholder))->value.integer; } +U_CAPI int32_t U_EXPORT2 +uhash_getiAndFound(const UHashtable *hash, + const void *key, + UBool *found) { + UHashTok keyholder; + keyholder.pointer = (void *)key; + const UHashElement *e = _uhash_find(hash, keyholder, hash->keyHasher(keyholder)); + *found = !IS_EMPTY_OR_DELETED(e->hashcode); + return e->value.integer; +} + +U_CAPI int32_t U_EXPORT2 +uhash_igetiAndFound(const UHashtable *hash, + int32_t key, + UBool *found) { + UHashTok keyholder; + keyholder.integer = key; + const UHashElement *e = _uhash_find(hash, keyholder, hash->keyHasher(keyholder)); + *found = !IS_EMPTY_OR_DELETED(e->hashcode); + return e->value.integer; +} + U_CAPI void* U_EXPORT2 uhash_put(UHashtable *hash, void* key, @@ -736,7 +761,34 @@ uhash_iputi(UHashtable *hash, keyholder.integer = key; valueholder.integer = value; return _uhash_put(hash, keyholder, valueholder, - 0, /* neither is a ptr */ + HINT_BOTH_INTEGERS, + status).integer; +} + +U_CAPI int32_t U_EXPORT2 +uhash_putiAllowZero(UHashtable *hash, + void *key, + int32_t value, + UErrorCode *status) { + UHashTok keyholder, valueholder; + keyholder.pointer = key; + valueholder.integer = value; + return _uhash_put(hash, keyholder, valueholder, + HINT_KEY_POINTER | HINT_ALLOW_ZERO, + status).integer; +} + + +U_CAPI int32_t U_EXPORT2 +uhash_iputiAllowZero(UHashtable *hash, + int32_t key, + int32_t value, + UErrorCode *status) { + UHashTok keyholder, valueholder; + keyholder.integer = key; + valueholder.integer = value; + return _uhash_put(hash, keyholder, valueholder, + HINT_BOTH_INTEGERS | HINT_ALLOW_ZERO, status).integer; } @@ -785,6 +837,29 @@ uhash_removeAll(UHashtable *hash) { U_ASSERT(hash->count == 0); } +U_CAPI UBool U_EXPORT2 +uhash_containsKey(const UHashtable *hash, const void *key) { + UHashTok keyholder; + keyholder.pointer = (void *)key; + const UHashElement *e = _uhash_find(hash, keyholder, hash->keyHasher(keyholder)); + return !IS_EMPTY_OR_DELETED(e->hashcode); +} + +/** + * Returns true if the UHashtable contains an item with this integer key. + * + * @param hash The target UHashtable. + * @param key An integer key stored in a hashtable + * @return true if the key is found. + */ +U_CAPI UBool U_EXPORT2 +uhash_icontainsKey(const UHashtable *hash, int32_t key) { + UHashTok keyholder; + keyholder.integer = key; + const UHashElement *e = _uhash_find(hash, keyholder, hash->keyHasher(keyholder)); + return !IS_EMPTY_OR_DELETED(e->hashcode); +} + U_CAPI const UHashElement* U_EXPORT2 uhash_find(const UHashtable *hash, const void* key) { UHashTok keyholder; diff --git a/thirdparty/icu4c/common/uhash.h b/thirdparty/icu4c/common/uhash.h index b59d2711bb..af75999860 100644 --- a/thirdparty/icu4c/common/uhash.h +++ b/thirdparty/icu4c/common/uhash.h @@ -23,7 +23,7 @@ /** * UHashtable stores key-value pairs and does moderately fast lookup * based on keys. It provides a good tradeoff between access time and - * storage space. As elements are added to it, it grows to accomodate + * storage space. As elements are added to it, it grows to accommodate * them. By default, the table never shrinks, even if all elements * are removed from it. * @@ -54,6 +54,13 @@ * uhash_remove() on that key. This keeps uhash_get(), uhash_count(), * and uhash_nextElement() consistent with one another. * + * Keys and values can be integers. + * Functions that work with an integer key have an "i" prefix. + * Functions that work with an integer value have an "i" suffix. + * As with putting a NULL value pointer, putting a zero value integer removes the item. + * Except, there are pairs of functions that allow setting zero values + * and fetching (value, found) pairs. + * * To see everything in a hashtable, use uhash_nextElement() to * iterate through its contents. Each call to this function returns a * UHashElement pointer. A hash element contains a key, value, and @@ -406,6 +413,44 @@ uhash_iputi(UHashtable *hash, UErrorCode *status); /** + * Put a (key=pointer, value=integer) item in a UHashtable. If the + * keyDeleter is non-NULL, then the hashtable owns 'key' after this + * call. valueDeleter must be NULL. + * Storing a 0 value is possible; call uhash_igetiAndFound() to retrieve values including zero. + * + * @param hash The target UHashtable. + * @param key The key to store. + * @param value The integer value to store. + * @param status A pointer to an UErrorCode to receive any errors. + * @return The previous value, or 0 if none. + * @see uhash_getiAndFound + */ +U_CAPI int32_t U_EXPORT2 +uhash_putiAllowZero(UHashtable *hash, + void *key, + int32_t value, + UErrorCode *status); + +/** + * Put a (key=integer, value=integer) item in a UHashtable. If the + * keyDeleter is non-NULL, then the hashtable owns 'key' after this + * call. valueDeleter must be NULL. + * Storing a 0 value is possible; call uhash_igetiAndFound() to retrieve values including zero. + * + * @param hash The target UHashtable. + * @param key The key to store. + * @param value The integer value to store. + * @param status A pointer to an UErrorCode to receive any errors. + * @return The previous value, or 0 if none. + * @see uhash_igetiAndFound + */ +U_CAPI int32_t U_EXPORT2 +uhash_iputiAllowZero(UHashtable *hash, + int32_t key, + int32_t value, + UErrorCode *status); + +/** * Retrieve a pointer value from a UHashtable using a pointer key, * as previously stored by uhash_put(). * @param hash The target UHashtable. @@ -449,6 +494,34 @@ uhash_igeti(const UHashtable *hash, int32_t key); /** + * Retrieves an integer value from a UHashtable using a pointer key, + * as previously stored by uhash_putiAllowZero() or uhash_puti(). + * + * @param hash The target UHashtable. + * @param key A pointer key stored in a hashtable + * @param found A pointer to a boolean which will be set for whether the key was found. + * @return The requested item, or 0 if not found. + */ +U_CAPI int32_t U_EXPORT2 +uhash_getiAndFound(const UHashtable *hash, + const void *key, + UBool *found); + +/** + * Retrieves an integer value from a UHashtable using an integer key, + * as previously stored by uhash_iputiAllowZero() or uhash_iputi(). + * + * @param hash The target UHashtable. + * @param key An integer key stored in a hashtable + * @param found A pointer to a boolean which will be set for whether the key was found. + * @return The requested item, or 0 if not found. + */ +U_CAPI int32_t U_EXPORT2 +uhash_igetiAndFound(const UHashtable *hash, + int32_t key, + UBool *found); + +/** * Remove an item from a UHashtable stored by uhash_put(). * @param hash The target UHashtable. * @param key A key stored in a hashtable @@ -496,6 +569,26 @@ U_CAPI void U_EXPORT2 uhash_removeAll(UHashtable *hash); /** + * Returns true if the UHashtable contains an item with this pointer key. + * + * @param hash The target UHashtable. + * @param key A pointer key stored in a hashtable + * @return true if the key is found. + */ +U_CAPI UBool U_EXPORT2 +uhash_containsKey(const UHashtable *hash, const void *key); + +/** + * Returns true if the UHashtable contains an item with this integer key. + * + * @param hash The target UHashtable. + * @param key An integer key stored in a hashtable + * @return true if the key is found. + */ +U_CAPI UBool U_EXPORT2 +uhash_icontainsKey(const UHashtable *hash, int32_t key); + +/** * Locate an element of a UHashtable. The caller must not modify the * returned object. The primary use of this function is to obtain the * stored key when it may not be identical to the search key. For diff --git a/thirdparty/icu4c/common/uloc.cpp b/thirdparty/icu4c/common/uloc.cpp index ebfbb50650..d96e79b8fd 100644 --- a/thirdparty/icu4c/common/uloc.cpp +++ b/thirdparty/icu4c/common/uloc.cpp @@ -143,7 +143,7 @@ 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", "mo", + "ml", "mn", "mnc", "mni", "moh", "mos", "mr", "mrj", "ms", "mt", "mua", "mul", "mus", "mwl", "mwr", "mwv", "my", "mye", "myv", "mzn", @@ -166,9 +166,9 @@ static const char * const LANGUAGES[] = { "sl", "sli", "sly", "sm", "sma", "smj", "smn", "sms", "sn", "snk", "so", "sog", "sq", "sr", "srn", "srr", "ss", "ssy", "st", "stq", "su", "suk", "sus", "sux", - "sv", "sw", "swb", "swc", "syc", "syr", "szl", + "sv", "sw", "swb", "syc", "syr", "szl", "ta", "tcy", "te", "tem", "teo", "ter", "tet", "tg", - "th", "ti", "tig", "tiv", "tk", "tkl", "tkr", "tl", + "th", "ti", "tig", "tiv", "tk", "tkl", "tkr", "tlh", "tli", "tly", "tmh", "tn", "to", "tog", "tpi", "tr", "tru", "trv", "ts", "tsd", "tsi", "tt", "ttt", "tum", "tvl", "tw", "twq", "ty", "tyv", "tzm", @@ -181,7 +181,7 @@ static const char * const LANGUAGES[] = { "za", "zap", "zbl", "zea", "zen", "zgh", "zh", "zu", "zun", "zxx", "zza", NULL, - "in", "iw", "ji", "jw", "sh", /* obsolete language codes */ + "in", "iw", "ji", "jw", "mo", "sh", "swc", "tl", /* obsolete language codes */ NULL }; @@ -260,7 +260,7 @@ 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", "mol", + "mal", "mon", "mnc", "mni", "moh", "mos", "mar", "mrj", "msa", "mlt", "mua", "mul", "mus", "mwl", "mwr", "mwv", "mya", "mye", "myv", "mzn", @@ -283,9 +283,9 @@ static const char * const LANGUAGES_3[] = { "slv", "sli", "sly", "smo", "sma", "smj", "smn", "sms", "sna", "snk", "som", "sog", "sqi", "srp", "srn", "srr", "ssw", "ssy", "sot", "stq", "sun", "suk", "sus", "sux", - "swe", "swa", "swb", "swc", "syc", "syr", "szl", + "swe", "swa", "swb", "syc", "syr", "szl", "tam", "tcy", "tel", "tem", "teo", "ter", "tet", "tgk", - "tha", "tir", "tig", "tiv", "tuk", "tkl", "tkr", "tgl", + "tha", "tir", "tig", "tiv", "tuk", "tkl", "tkr", "tlh", "tli", "tly", "tmh", "tsn", "ton", "tog", "tpi", "tur", "tru", "trv", "tso", "tsd", "tsi", "tat", "ttt", "tum", "tvl", "twi", "twq", "tah", "tyv", "tzm", @@ -298,8 +298,8 @@ static const char * const LANGUAGES_3[] = { "zha", "zap", "zbl", "zea", "zen", "zgh", "zho", "zul", "zun", "zxx", "zza", NULL, -/* "in", "iw", "ji", "jw", "sh", */ - "ind", "heb", "yid", "jaw", "srp", +/* "in", "iw", "ji", "jw", "mo", "sh", "swc", "tl", */ + "ind", "heb", "yid", "jaw", "mol", "srp", "swc", "tgl", NULL }; @@ -334,13 +334,13 @@ static const char * const COUNTRIES[] = { "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", - "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", - "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", + "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DG", "DJ", "DK", + "DM", "DO", "DZ", "EA", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", - "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", + "IC", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", @@ -357,7 +357,7 @@ static const char * const COUNTRIES[] = { "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", - "WS", "YE", "YT", "ZA", "ZM", "ZW", + "WS", "XK", "YE", "YT", "ZA", "ZM", "ZW", NULL, "AN", "BU", "CS", "FX", "RO", "SU", "TP", "YD", "YU", "ZR", /* obsolete country codes */ NULL @@ -397,10 +397,10 @@ static const char * const COUNTRIES_3[] = { "BWA", "BLR", "BLZ", "CAN", "CCK", "COD", "CAF", "COG", /* "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", */ "CHE", "CIV", "COK", "CHL", "CMR", "CHN", "COL", "CRI", -/* "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", */ - "CUB", "CPV", "CUW", "CXR", "CYP", "CZE", "DEU", "DJI", "DNK", -/* "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", */ - "DMA", "DOM", "DZA", "ECU", "EST", "EGY", "ESH", "ERI", +/* "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DG", "DJ", "DK", */ + "CUB", "CPV", "CUW", "CXR", "CYP", "CZE", "DEU", "DGA", "DJI", "DNK", +/* "DM", "DO", "DZ", "EA", "EC", "EE", "EG", "EH", "ER", */ + "DMA", "DOM", "DZA", "XEA", "ECU", "EST", "EGY", "ESH", "ERI", /* "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", */ "ESP", "ETH", "FIN", "FJI", "FLK", "FSM", "FRO", "FRA", /* "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", */ @@ -409,8 +409,8 @@ static const char * const COUNTRIES_3[] = { "GMB", "GIN", "GLP", "GNQ", "GRC", "SGS", "GTM", "GUM", /* "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", */ "GNB", "GUY", "HKG", "HMD", "HND", "HRV", "HTI", "HUN", -/* "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS" */ - "IDN", "IRL", "ISR", "IMN", "IND", "IOT", "IRQ", "IRN", "ISL", +/* "IC", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS" */ + "XIC", "IDN", "IRL", "ISR", "IMN", "IND", "IOT", "IRQ", "IRN", "ISL", /* "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", */ "ITA", "JEY", "JAM", "JOR", "JPN", "KEN", "KGZ", "KHM", "KIR", /* "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", */ @@ -443,8 +443,8 @@ static const char * const COUNTRIES_3[] = { "TWN", "TZA", "UKR", "UGA", "UMI", "USA", "URY", "UZB", /* "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", */ "VAT", "VCT", "VEN", "VGB", "VIR", "VNM", "VUT", "WLF", -/* "WS", "YE", "YT", "ZA", "ZM", "ZW", */ - "WSM", "YEM", "MYT", "ZAF", "ZMB", "ZWE", +/* "WS", "XK", "YE", "YT", "ZA", "ZM", "ZW", */ + "WSM", "XXK", "YEM", "MYT", "ZAF", "ZMB", "ZWE", NULL, /* "AN", "BU", "CS", "FX", "RO", "SU", "TP", "YD", "YU", "ZR" */ "ANT", "BUR", "SCG", "FXX", "ROM", "SUN", "TMP", "YMD", "YUG", "ZAR", diff --git a/thirdparty/icu4c/common/uloc_keytype.cpp b/thirdparty/icu4c/common/uloc_keytype.cpp index 019da058cf..c289ebe76f 100644 --- a/thirdparty/icu4c/common/uloc_keytype.cpp +++ b/thirdparty/icu4c/common/uloc_keytype.cpp @@ -271,7 +271,7 @@ initFromResourceBundle(UErrorCode& sts) { if (U_FAILURE(sts)) { break; } - // check if this is an alias of canoncal legacy type + // check if this is an alias of canonical legacy type if (uprv_compareInvWithUChar(NULL, legacyTypeId, -1, to, toLen) == 0) { const char* from = ures_getKey(typeAliasDataEntry.getAlias()); if (isTZ) { diff --git a/thirdparty/icu4c/common/uloc_tag.cpp b/thirdparty/icu4c/common/uloc_tag.cpp index 7f7fd9119e..1235081bf3 100644 --- a/thirdparty/icu4c/common/uloc_tag.cpp +++ b/thirdparty/icu4c/common/uloc_tag.cpp @@ -129,7 +129,6 @@ static const char* const LEGACY[] = { // Legacy tags with no preferred value in the IANA // registry. Kept for now for the backward compatibility // because ICU has mapped them this way. - "cel-gaulish", "xtg-x-cel-gaulish", "i-default", "en-x-i-default", "i-enochian", "und-x-i-enochian", "i-mingo", "see-x-i-mingo", @@ -647,6 +646,22 @@ _isTKey(const char* s, int32_t len) return FALSE; } +U_CAPI const char * U_EXPORT2 +ultag_getTKeyStart(const char *localeID) { + const char *result = localeID; + const char *sep; + while((sep = uprv_strchr(result, SEP)) != nullptr) { + if (_isTKey(result, static_cast<int32_t>(sep - result))) { + return result; + } + result = ++sep; + } + if (_isTKey(result, -1)) { + return result; + } + return nullptr; +} + static UBool _isTValue(const char* s, int32_t len) { @@ -671,9 +686,13 @@ _isTransformedExtensionSubtag(int32_t& state, const char* s, int32_t len) const int32_t kGotTKey = -1; // Got tkey, wait for tvalue. ERROR if stop here. const int32_t kGotTValue = 6; // Got tvalue, wait for tkey, tvalue or end + + if (len < 0) { + len = (int32_t)uprv_strlen(s); + } switch (state) { case kStart: - if (ultag_isLanguageSubtag(s, len)) { + if (ultag_isLanguageSubtag(s, len) && len != 4) { state = kGotLanguage; return TRUE; } @@ -1775,11 +1794,6 @@ _appendKeywords(ULanguageTag* langtag, icu::ByteSink& sink, UErrorCode* status) return; } - /* Determine if variants already exists */ - if (ultag_getVariantsSize(langtag)) { - posixVariant = TRUE; - } - n = ultag_getExtensionsSize(langtag); /* resolve locale keywords and reordering keys */ @@ -1787,6 +1801,11 @@ _appendKeywords(ULanguageTag* langtag, icu::ByteSink& sink, UErrorCode* status) key = ultag_getExtensionKey(langtag, i); type = ultag_getExtensionValue(langtag, i); if (*key == LDMLEXT) { + /* Determine if variants already exists */ + if (ultag_getVariantsSize(langtag)) { + posixVariant = TRUE; + } + _appendLDMLExtensionAsKeywords(type, &kwdFirst, extPool, kwdBuf, &posixVariant, status); if (U_FAILURE(*status)) { break; @@ -2028,7 +2047,10 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode* sta *status = U_MEMORY_ALLOCATION_ERROR; return NULL; } - uprv_memcpy(tagBuf, tag, tagLen); + + if (tagLen > 0) { + uprv_memcpy(tagBuf, tag, tagLen); + } *(tagBuf + tagLen) = 0; /* create a ULanguageTag */ @@ -2692,8 +2714,7 @@ ulocimp_toLanguageTag(const char* localeID, if (U_SUCCESS(tmpStatus)) { if (ultag_isPrivateuseValueSubtags(buf.data(), buf.length())) { /* return private use only tag */ - static const char PREFIX[] = { PRIVATEUSE, SEP }; - sink.Append(PREFIX, sizeof(PREFIX)); + sink.Append("und-x-", 6); sink.Append(buf.data(), buf.length()); done = TRUE; } else if (strict) { diff --git a/thirdparty/icu4c/common/ulocimp.h b/thirdparty/icu4c/common/ulocimp.h index 5691fe9a77..1f796aa213 100644 --- a/thirdparty/icu4c/common/ulocimp.h +++ b/thirdparty/icu4c/common/ulocimp.h @@ -286,6 +286,9 @@ ultag_isUnicodeLocaleType(const char* s, int32_t len); U_CFUNC UBool ultag_isVariantSubtags(const char* s, int32_t len); +U_CAPI const char * U_EXPORT2 +ultag_getTKeyStart(const char *localeID); + U_CFUNC const char* ulocimp_toBcpKey(const char* key); diff --git a/thirdparty/icu4c/common/unicode/bytestream.h b/thirdparty/icu4c/common/unicode/bytestream.h index 044f7a77e7..9735ee0bf8 100644 --- a/thirdparty/icu4c/common/unicode/bytestream.h +++ b/thirdparty/icu4c/common/unicode/bytestream.h @@ -71,7 +71,6 @@ public: */ virtual void Append(const char* bytes, int32_t n) = 0; -#ifndef U_HIDE_DRAFT_API /** * Appends n bytes to this. Same as Append(). * Call AppendU8() with u8"string literals" which are const char * in C++11 @@ -81,7 +80,7 @@ public: * * @param bytes the pointer to the bytes * @param n the number of bytes; must be non-negative - * @draft ICU 67 + * @stable ICU 67 */ inline void AppendU8(const char* bytes, int32_t n) { Append(bytes, n); @@ -97,13 +96,12 @@ public: * * @param bytes the pointer to the bytes * @param n the number of bytes; must be non-negative - * @draft ICU 67 + * @stable ICU 67 */ inline void AppendU8(const char8_t* bytes, int32_t n) { Append(reinterpret_cast<const char*>(bytes), n); } #endif -#endif // U_HIDE_DRAFT_API /** * Returns a writable buffer for appending and writes the buffer's capacity to diff --git a/thirdparty/icu4c/common/unicode/bytestrie.h b/thirdparty/icu4c/common/unicode/bytestrie.h index 85f802df42..271a81d1b4 100644 --- a/thirdparty/icu4c/common/unicode/bytestrie.h +++ b/thirdparty/icu4c/common/unicode/bytestrie.h @@ -30,6 +30,8 @@ #include "unicode/uobject.h" #include "unicode/ustringtrie.h" +class BytesTrieTest; + U_NAMESPACE_BEGIN class ByteSink; @@ -378,6 +380,7 @@ public: private: friend class BytesTrieBuilder; + friend class ::BytesTrieTest; /** * Constructs a BytesTrie reader instance. diff --git a/thirdparty/icu4c/common/unicode/bytestriebuilder.h b/thirdparty/icu4c/common/unicode/bytestriebuilder.h index cae16e48b4..3cff89e443 100644 --- a/thirdparty/icu4c/common/unicode/bytestriebuilder.h +++ b/thirdparty/icu4c/common/unicode/bytestriebuilder.h @@ -30,6 +30,8 @@ #include "unicode/stringpiece.h" #include "unicode/stringtriebuilder.h" +class BytesTrieTest; + U_NAMESPACE_BEGIN class BytesTrieElement; @@ -125,6 +127,8 @@ public: BytesTrieBuilder &clear(); private: + friend class ::BytesTrieTest; + BytesTrieBuilder(const BytesTrieBuilder &other); // no copy constructor BytesTrieBuilder &operator=(const BytesTrieBuilder &other); // no assignment operator @@ -168,6 +172,7 @@ private: virtual int32_t writeValueAndFinal(int32_t i, UBool isFinal); virtual int32_t writeValueAndType(UBool hasValue, int32_t value, int32_t node); virtual int32_t writeDeltaTo(int32_t jumpTarget); + static int32_t internalEncodeDelta(int32_t i, char intBytes[]); CharString *strings; // Pointer not object so we need not #include internal charstr.h. BytesTrieElement *elements; diff --git a/thirdparty/icu4c/common/unicode/docmain.h b/thirdparty/icu4c/common/unicode/docmain.h index edcb5d4e83..e82678c95f 100644 --- a/thirdparty/icu4c/common/unicode/docmain.h +++ b/thirdparty/icu4c/common/unicode/docmain.h @@ -15,7 +15,7 @@ * \file * \brief (Non API- contains Doxygen definitions) * - * This file contains documentation for Doxygen and doesnot have + * This file contains documentation for Doxygen and does not have * any significance with respect to C or C++ API */ @@ -74,7 +74,7 @@ * </tr> * <tr> * <td>Strings and Character Iteration</td> - * <td>ustring.h, utf8.h, utf16.h, UText, UCharIterator</td> + * <td>ustring.h, utf8.h, utf16.h, icu::StringPiece, UText, UCharIterator, icu::ByteSink</td> * <td>icu::UnicodeString, icu::CharacterIterator, icu::Appendable, icu::StringPiece,icu::ByteSink</td> * </tr> * <tr> @@ -128,9 +128,9 @@ * <td>icu::Normalizer2</td> * </tr> * <tr> - * <td>Calendars</td> + * <td>Calendars and Time Zones</td> * <td>ucal.h</td> - * <td>icu::Calendar</td> + * <td>icu::Calendar, icu::TimeZone</td> * </tr> * <tr> * <td>Date and Time Formatting</td> diff --git a/thirdparty/icu4c/common/unicode/icuplug.h b/thirdparty/icu4c/common/unicode/icuplug.h index 52f810da57..205af360d4 100644 --- a/thirdparty/icu4c/common/unicode/icuplug.h +++ b/thirdparty/icu4c/common/unicode/icuplug.h @@ -117,14 +117,13 @@ /* === Basic types === */ #ifndef U_HIDE_INTERNAL_API +struct UPlugData; /** * @{ - * Opaque structure passed to/from a plugin. - * use the APIs to access it. + * Typedef for opaque structure passed to/from a plugin. + * Use the APIs to access it. * @internal ICU 4.4 Technology Preview */ - -struct UPlugData; typedef struct UPlugData UPlugData; /** @} */ diff --git a/thirdparty/icu4c/common/unicode/localematcher.h b/thirdparty/icu4c/common/unicode/localematcher.h index 63a68b0b7f..0cd068ef32 100644 --- a/thirdparty/icu4c/common/unicode/localematcher.h +++ b/thirdparty/icu4c/common/unicode/localematcher.h @@ -91,8 +91,6 @@ enum ULocMatchDemotion { typedef enum ULocMatchDemotion ULocMatchDemotion; #endif -#ifndef U_FORCE_HIDE_DRAFT_API - /** * Builder option for whether to include or ignore one-way (fallback) match data. * The LocaleMatcher uses CLDR languageMatch data which includes fallback (oneway=true) entries. @@ -108,20 +106,20 @@ typedef enum ULocMatchDemotion ULocMatchDemotion; * but not if it is merely a fallback. * * @see LocaleMatcher::Builder#setDirection(ULocMatchDirection) - * @draft ICU 67 + * @stable ICU 67 */ enum ULocMatchDirection { /** * Locale matching includes one-way matches such as Breton→French. (default) * - * @draft ICU 67 + * @stable ICU 67 */ ULOCMATCH_DIRECTION_WITH_ONE_WAY, /** * Locale matching limited to two-way matches including e.g. Danish↔Norwegian * but ignoring one-way matches. * - * @draft ICU 67 + * @stable ICU 67 */ ULOCMATCH_DIRECTION_ONLY_TWO_WAY }; @@ -129,8 +127,6 @@ enum ULocMatchDirection { typedef enum ULocMatchDirection ULocMatchDirection; #endif -#endif // U_FORCE_HIDE_DRAFT_API - struct UHashtable; U_NAMESPACE_BEGIN @@ -463,14 +459,13 @@ public: */ Builder &setDemotionPerDesiredLocale(ULocMatchDemotion demotion); -#ifndef U_HIDE_DRAFT_API /** * Option for whether to include or ignore one-way (fallback) match data. * By default, they are included. * * @param direction the match direction to set. * @return this Builder object - * @draft ICU 67 + * @stable ICU 67 */ Builder &setDirection(ULocMatchDirection direction) { if (U_SUCCESS(errorCode_)) { @@ -478,7 +473,6 @@ public: } return *this; } -#endif // U_HIDE_DRAFT_API #ifndef U_HIDE_DRAFT_API /** @@ -704,7 +698,7 @@ private: LSR *lsrs; int32_t supportedLocalesLength; // These are in preference order: 1. Default locale 2. paradigm locales 3. others. - UHashtable *supportedLsrToIndex; // Map<LSR, Integer> stores index+1 because 0 is "not found" + UHashtable *supportedLsrToIndex; // Map<LSR, Integer> // 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; diff --git a/thirdparty/icu4c/common/unicode/locid.h b/thirdparty/icu4c/common/unicode/locid.h index ba858d702a..81f4685d65 100644 --- a/thirdparty/icu4c/common/unicode/locid.h +++ b/thirdparty/icu4c/common/unicode/locid.h @@ -571,15 +571,13 @@ public: */ void minimizeSubtags(UErrorCode& status); -#ifndef U_HIDE_DRAFT_API /** * Canonicalize the locale ID of this object according to CLDR. * @param status the status code - * @draft ICU 67 + * @stable ICU 67 * @see createCanonical */ void canonicalize(UErrorCode& status); -#endif // U_HIDE_DRAFT_API /** * Gets the list of keywords for the specified locale. diff --git a/thirdparty/icu4c/common/unicode/normalizer2.h b/thirdparty/icu4c/common/unicode/normalizer2.h index 5eb1d95caf..2d355250c2 100644 --- a/thirdparty/icu4c/common/unicode/normalizer2.h +++ b/thirdparty/icu4c/common/unicode/normalizer2.h @@ -225,10 +225,8 @@ public: * Normalizes a UTF-8 string and optionally records how source substrings * relate to changed and unchanged result substrings. * - * Currently implemented completely only for "compose" modes, - * such as for NFC, NFKC, and NFKC_Casefold - * (UNORM2_COMPOSE and UNORM2_COMPOSE_CONTIGUOUS). - * Otherwise currently converts to & from UTF-16 and does not support edits. + * Implemented completely for all built-in modes except for FCD. + * The base class implementation converts to & from UTF-16 and does not support edits. * * @param options Options bit set, usually 0. See U_OMIT_UNCHANGED_TEXT and U_EDITS_NO_RESET. * @param src Source UTF-8 string. @@ -381,11 +379,9 @@ public: * resolves to "yes" or "no" to provide a definitive result, * at the cost of doing more work in those cases. * - * This works for all normalization modes, - * but it is currently optimized for UTF-8 only for "compose" modes, - * such as for NFC, NFKC, and NFKC_Casefold - * (UNORM2_COMPOSE and UNORM2_COMPOSE_CONTIGUOUS). - * For other modes it currently converts to UTF-16 and calls isNormalized(). + * This works for all normalization modes. + * It is optimized for UTF-8 for all built-in modes except for FCD. + * The base class implementation converts to UTF-16 and calls isNormalized(). * * @param s UTF-8 input string * @param errorCode Standard ICU error code. Its input value must @@ -543,10 +539,8 @@ public: * Normalizes a UTF-8 string and optionally records how source substrings * relate to changed and unchanged result substrings. * - * Currently implemented completely only for "compose" modes, - * such as for NFC, NFKC, and NFKC_Casefold - * (UNORM2_COMPOSE and UNORM2_COMPOSE_CONTIGUOUS). - * Otherwise currently converts to & from UTF-16 and does not support edits. + * Implemented completely for most built-in modes except for FCD. + * The base class implementation converts to & from UTF-16 and does not support edits. * * @param options Options bit set, usually 0. See U_OMIT_UNCHANGED_TEXT and U_EDITS_NO_RESET. * @param src Source UTF-8 string. @@ -676,11 +670,9 @@ public: * resolves to "yes" or "no" to provide a definitive result, * at the cost of doing more work in those cases. * - * This works for all normalization modes, - * but it is currently optimized for UTF-8 only for "compose" modes, - * such as for NFC, NFKC, and NFKC_Casefold - * (UNORM2_COMPOSE and UNORM2_COMPOSE_CONTIGUOUS). - * For other modes it currently converts to UTF-16 and calls isNormalized(). + * This works for all normalization modes. + * It is optimized for UTF-8 for all built-in modes except for FCD. + * The base class implementation converts to UTF-16 and calls isNormalized(). * * @param s UTF-8 input string * @param errorCode Standard ICU error code. Its input value must diff --git a/thirdparty/icu4c/common/unicode/platform.h b/thirdparty/icu4c/common/unicode/platform.h index 2bb2f8b318..cb3a833fef 100644 --- a/thirdparty/icu4c/common/unicode/platform.h +++ b/thirdparty/icu4c/common/unicode/platform.h @@ -880,6 +880,6 @@ namespace std { #else # define U_CALLCONV_FPTR #endif -/* @} */ +/** @} */ #endif // _PLATFORM_H diff --git a/thirdparty/icu4c/common/unicode/stringpiece.h b/thirdparty/icu4c/common/unicode/stringpiece.h index 7d7d871e1f..8c96789e73 100644 --- a/thirdparty/icu4c/common/unicode/stringpiece.h +++ b/thirdparty/icu4c/common/unicode/stringpiece.h @@ -75,12 +75,11 @@ class U_COMMON_API StringPiece : public UMemory { * @stable ICU 4.2 */ StringPiece(const char* str); -#ifndef U_HIDE_DRAFT_API #if defined(__cpp_char8_t) || defined(U_IN_DOXYGEN) /** * Constructs from a NUL-terminated const char8_t * pointer. * @param str a NUL-terminated const char8_t * pointer - * @draft ICU 67 + * @stable ICU 67 */ StringPiece(const char8_t* str) : StringPiece(reinterpret_cast<const char*>(str)) {} #endif @@ -88,10 +87,9 @@ class U_COMMON_API StringPiece : public UMemory { * Constructs an empty StringPiece. * Needed for type disambiguation from multiple other overloads. * @param p nullptr - * @draft ICU 67 + * @stable ICU 67 */ StringPiece(std::nullptr_t p) : ptr_(p), length_(0) {} -#endif // U_HIDE_DRAFT_API /** * Constructs from a std::string. @@ -99,17 +97,15 @@ class U_COMMON_API StringPiece : public UMemory { */ StringPiece(const std::string& str) : ptr_(str.data()), length_(static_cast<int32_t>(str.size())) { } -#ifndef U_HIDE_DRAFT_API #if defined(__cpp_lib_char8_t) || defined(U_IN_DOXYGEN) /** * Constructs from a std::u8string. - * @draft ICU 67 + * @stable ICU 67 */ StringPiece(const std::u8string& str) : ptr_(reinterpret_cast<const char*>(str.data())), length_(static_cast<int32_t>(str.size())) { } #endif -#endif // U_HIDE_DRAFT_API /** * Constructs from some other implementation of a string piece class, from any @@ -152,18 +148,16 @@ class U_COMMON_API StringPiece : public UMemory { * @stable ICU 4.2 */ StringPiece(const char* offset, int32_t len) : ptr_(offset), length_(len) { } -#ifndef U_HIDE_DRAFT_API #if defined(__cpp_char8_t) || defined(U_IN_DOXYGEN) /** * Constructs from a const char8_t * pointer and a specified length. * @param str a const char8_t * pointer (need not be terminated) * @param len the length of the string; must be non-negative - * @draft ICU 67 + * @stable ICU 67 */ StringPiece(const char8_t* str, int32_t len) : StringPiece(reinterpret_cast<const char*>(str), len) {} #endif -#endif // U_HIDE_DRAFT_API /** * Substring of another StringPiece. @@ -233,13 +227,12 @@ class U_COMMON_API StringPiece : public UMemory { */ void set(const char* str); -#ifndef U_HIDE_DRAFT_API #if defined(__cpp_char8_t) || defined(U_IN_DOXYGEN) /** * Resets the stringpiece to refer to new data. * @param xdata pointer the new string data. Need not be NUL-terminated. * @param len the length of the new data - * @draft ICU 67 + * @stable ICU 67 */ inline void set(const char8_t* xdata, int32_t len) { set(reinterpret_cast<const char*>(xdata), len); @@ -248,13 +241,12 @@ class U_COMMON_API StringPiece : public UMemory { /** * Resets the stringpiece to refer to new data. * @param str a pointer to a NUL-terminated string. - * @draft ICU 67 + * @stable ICU 67 */ inline void set(const char8_t* str) { set(reinterpret_cast<const char*>(str)); } #endif -#endif // U_HIDE_DRAFT_API /** * Removes the first n string units. @@ -286,13 +278,12 @@ class U_COMMON_API StringPiece : public UMemory { } } -#ifndef U_HIDE_DRAFT_API /** * Searches the StringPiece for the given search string (needle); * @param needle The string for which to search. * @param offset Where to start searching within this string (haystack). * @return The offset of needle in haystack, or -1 if not found. - * @draft ICU 67 + * @stable ICU 67 */ int32_t find(StringPiece needle, int32_t offset); @@ -301,10 +292,9 @@ class U_COMMON_API StringPiece : public UMemory { * similar to std::string::compare(). * @param other The string to compare to. * @return below zero if this < other; above zero if this > other; 0 if this == other. - * @draft ICU 67 + * @stable ICU 67 */ int32_t compare(StringPiece other); -#endif // U_HIDE_DRAFT_API /** * Maximum integer, used as a default value for substring methods. diff --git a/thirdparty/icu4c/common/unicode/ubrk.h b/thirdparty/icu4c/common/unicode/ubrk.h index 37189a8598..1249b0b160 100644 --- a/thirdparty/icu4c/common/unicode/ubrk.h +++ b/thirdparty/icu4c/common/unicode/ubrk.h @@ -296,6 +296,8 @@ ubrk_openBinaryRules(const uint8_t *binaryRules, int32_t rulesLength, const UChar * text, int32_t textLength, UErrorCode * status); +#ifndef U_HIDE_DEPRECATED_API + /** * Thread safe cloning operation * @param bi iterator to be cloned @@ -312,7 +314,7 @@ ubrk_openBinaryRules(const uint8_t *binaryRules, int32_t rulesLength, * @param status to indicate whether the operation went on smoothly or there were errors * An informational status value, U_SAFECLONE_ALLOCATED_ERROR, is used if any allocations were necessary. * @return pointer to the new clone - * @stable ICU 2.0 + * @deprecated ICU 69 Use ubrk_clone() instead. */ U_CAPI UBreakIterator * U_EXPORT2 ubrk_safeClone( @@ -321,6 +323,23 @@ ubrk_safeClone( int32_t *pBufferSize, UErrorCode *status); +#endif /* U_HIDE_DEPRECATED_API */ + +#ifndef U_HIDE_DRAFT_API + +/** + * Thread safe cloning operation. + * @param bi iterator to be cloned + * @param status to indicate whether the operation went on smoothly or there were errors + * @return pointer to the new clone + * @draft ICU 69 + */ +U_CAPI UBreakIterator * U_EXPORT2 +ubrk_clone(const UBreakIterator *bi, + UErrorCode *status); + +#endif // U_HIDE_DRAFT_API + #ifndef U_HIDE_DEPRECATED_API /** diff --git a/thirdparty/icu4c/common/unicode/ucnv.h b/thirdparty/icu4c/common/unicode/ucnv.h index 58f271cfb5..5d784990f2 100644 --- a/thirdparty/icu4c/common/unicode/ucnv.h +++ b/thirdparty/icu4c/common/unicode/ucnv.h @@ -1699,10 +1699,10 @@ ucnv_countAvailable(void); /** * Gets the canonical converter name of the specified converter from a list of - * all available converters contaied in the alias file. All converters + * all available converters contained in the alias file. All converters * in this list can be opened. * - * @param n the index to a converter available on the system (in the range <TT>[0..ucnv_countAvaiable()]</TT>) + * @param n the index to a converter available on the system (in the range <TT>[0..ucnv_countAvailable()]</TT>) * @return a pointer a string (library owned), or <TT>NULL</TT> if the index is out of bounds. * @see ucnv_countAvailable * @stable ICU 2.0 diff --git a/thirdparty/icu4c/common/unicode/ucnvsel.h b/thirdparty/icu4c/common/unicode/ucnvsel.h index 5e0a71cf35..3d7d3327f7 100644 --- a/thirdparty/icu4c/common/unicode/ucnvsel.h +++ b/thirdparty/icu4c/common/unicode/ucnvsel.h @@ -45,11 +45,11 @@ * from the serialized form. */ +struct UConverterSelector; /** * @{ - * The selector data structure + * Typedef for selector data structure. */ -struct UConverterSelector; typedef struct UConverterSelector UConverterSelector; /** @} */ diff --git a/thirdparty/icu4c/common/unicode/unifilt.h b/thirdparty/icu4c/common/unicode/unifilt.h index 420e1a1905..7870b55939 100644 --- a/thirdparty/icu4c/common/unicode/unifilt.h +++ b/thirdparty/icu4c/common/unicode/unifilt.h @@ -40,8 +40,8 @@ U_NAMESPACE_BEGIN * * <code>UnicodeFilter</code> defines a protocol for selecting a * subset of the full range (U+0000 to U+10FFFF) of Unicode characters. - * Currently, filters are used in conjunction with classes like {@link - * Transliterator} to only process selected characters through a + * Currently, filters are used in conjunction with classes like + * {@link Transliterator} to only process selected characters through a * transformation. * * <p>Note: UnicodeFilter currently stubs out two pure virtual methods diff --git a/thirdparty/icu4c/common/unicode/uniset.h b/thirdparty/icu4c/common/unicode/uniset.h index 50b6360f3a..8403c4026c 100644 --- a/thirdparty/icu4c/common/unicode/uniset.h +++ b/thirdparty/icu4c/common/unicode/uniset.h @@ -178,8 +178,6 @@ class RuleCharacterIterator; * Unicode property * </table> * - * <p><b>Warning</b>: you cannot add an empty string ("") to a UnicodeSet.</p> - * * <p><b>Formal syntax</b></p> * * \htmlonly<blockquote>\endhtmlonly @@ -601,7 +599,7 @@ public: /** * Make this object represent the range `start - end`. - * If `end > start` then this object is set to an empty range. + * If `start > end` then this object is set to an empty range. * A frozen set will not be modified. * * @param start first character in the set, inclusive @@ -1077,7 +1075,7 @@ public: /** * Adds the specified range to this set if it is not already * present. If this set already contains the specified range, - * the call leaves this set unchanged. If <code>end > start</code> + * the call leaves this set unchanged. If <code>start > end</code> * then an empty range is added, leaving the set unchanged. * This is equivalent to a boolean logic OR, or a set UNION. * A frozen set will not be modified. @@ -1095,6 +1093,9 @@ public: * present. If this set already contains the specified character, * the call leaves this set unchanged. * A frozen set will not be modified. + * + * @param c the character (code point) + * @return this object, for chaining * @stable ICU 2.0 */ UnicodeSet& add(UChar32 c); @@ -1104,8 +1105,8 @@ public: * present. If this set already contains the multicharacter, * the call leaves this set unchanged. * Thus "ch" => {"ch"} - * <br><b>Warning: you cannot add an empty string ("") to a UnicodeSet.</b> * A frozen set will not be modified. + * * @param s the source string * @return this object, for chaining * @stable ICU 2.4 @@ -1124,8 +1125,8 @@ public: public: /** - * Adds each of the characters in this string to the set. Thus "ch" => {"c", "h"} - * If this set already any particular character, it has no effect on that character. + * Adds each of the characters in this string to the set. Note: "ch" => {"c", "h"} + * If this set already contains any particular character, it has no effect on that character. * A frozen set will not be modified. * @param s the source string * @return this object, for chaining @@ -1135,7 +1136,6 @@ public: /** * Retains EACH of the characters in this string. Note: "ch" == {"c", "h"} - * If this set already any particular character, it has no effect on that character. * A frozen set will not be modified. * @param s the source string * @return this object, for chaining @@ -1145,7 +1145,6 @@ public: /** * Complement EACH of the characters in this string. Note: "ch" == {"c", "h"} - * If this set already any particular character, it has no effect on that character. * A frozen set will not be modified. * @param s the source string * @return this object, for chaining @@ -1155,7 +1154,6 @@ public: /** * Remove EACH of the characters in this string. Note: "ch" == {"c", "h"} - * If this set already any particular character, it has no effect on that character. * A frozen set will not be modified. * @param s the source string * @return this object, for chaining @@ -1165,7 +1163,7 @@ public: /** * Makes a set from a multicharacter string. Thus "ch" => {"ch"} - * <br><b>Warning: you cannot add an empty string ("") to a UnicodeSet.</b> + * * @param s the source string * @return a newly created set containing the given string. * The caller owns the return object and is responsible for deleting it. @@ -1185,15 +1183,13 @@ public: /** * Retain only the elements in this set that are contained in the - * specified range. If <code>end > start</code> then an empty range is + * specified range. If <code>start > end</code> then an empty range is * retained, leaving the set empty. This is equivalent to * a boolean logic AND, or a set INTERSECTION. * A frozen set will not be modified. * - * @param start first character, inclusive, of range to be retained - * to this set. - * @param end last character, inclusive, of range to be retained - * to this set. + * @param start first character, inclusive, of range + * @param end last character, inclusive, of range * @stable ICU 2.0 */ virtual UnicodeSet& retain(UChar32 start, UChar32 end); @@ -1202,14 +1198,31 @@ public: /** * Retain the specified character from this set if it is present. * A frozen set will not be modified. + * + * @param c the character (code point) + * @return this object, for chaining * @stable ICU 2.0 */ UnicodeSet& retain(UChar32 c); +#ifndef U_HIDE_DRAFT_API + /** + * Retains only the specified string from this set if it is present. + * Upon return this set will be empty if it did not contain s, or + * will only contain s if it did contain s. + * A frozen set will not be modified. + * + * @param s the source string + * @return this object, for chaining + * @draft ICU 69 + */ + UnicodeSet& retain(const UnicodeString &s); +#endif // U_HIDE_DRAFT_API + /** * Removes the specified range from this set if it is present. * The set will not contain the specified range once the call - * returns. If <code>end > start</code> then an empty range is + * returns. If <code>start > end</code> then an empty range is * removed, leaving the set unchanged. * A frozen set will not be modified. * @@ -1226,6 +1239,9 @@ public: * The set will not contain the specified range once the call * returns. * A frozen set will not be modified. + * + * @param c the character (code point) + * @return this object, for chaining * @stable ICU 2.0 */ UnicodeSet& remove(UChar32 c); @@ -1253,15 +1269,13 @@ public: /** * Complements the specified range in this set. Any character in * the range will be removed if it is in this set, or will be - * added if it is not in this set. If <code>end > start</code> + * added if it is not in this set. If <code>start > end</code> * then an empty range is complemented, leaving the set unchanged. * This is equivalent to a boolean logic XOR. * A frozen set will not be modified. * - * @param start first character, inclusive, of range to be removed - * from this set. - * @param end last character, inclusive, of range to be removed - * from this set. + * @param start first character, inclusive, of range + * @param end last character, inclusive, of range * @stable ICU 2.0 */ virtual UnicodeSet& complement(UChar32 start, UChar32 end); @@ -1271,16 +1285,18 @@ public: * will be removed if it is in this set, or will be added if it is * not in this set. * A frozen set will not be modified. + * + * @param c the character (code point) + * @return this object, for chaining * @stable ICU 2.0 */ UnicodeSet& complement(UChar32 c); /** * Complement the specified string in this set. - * The set will not contain the specified string once the call - * returns. - * <br><b>Warning: you cannot add an empty string ("") to a UnicodeSet.</b> + * The string will be removed if it is in this set, or will be added if it is not in this set. * A frozen set will not be modified. + * * @param s the string to complement * @return this object, for chaining * @stable ICU 2.4 diff --git a/thirdparty/icu4c/common/unicode/unistr.h b/thirdparty/icu4c/common/unicode/unistr.h index 456389f265..85bd964951 100644 --- a/thirdparty/icu4c/common/unicode/unistr.h +++ b/thirdparty/icu4c/common/unicode/unistr.h @@ -44,9 +44,10 @@ struct UConverter; // unicode/ucnv.h #ifndef USTRING_H /** * \ingroup ustring_ustrlen + * @param s Pointer to sequence of UChars. + * @return Length of sequence. */ -U_CAPI int32_t U_EXPORT2 -u_strlen(const UChar *s); +U_CAPI int32_t U_EXPORT2 u_strlen(const UChar *s); #endif U_NAMESPACE_BEGIN @@ -2766,7 +2767,6 @@ public: * @param options Options bit set, usually 0. See U_TITLECASE_NO_LOWERCASE, * U_TITLECASE_NO_BREAK_ADJUSTMENT, U_TITLECASE_ADJUST_TO_CASED, * U_TITLECASE_WHOLE_STRING, U_TITLECASE_SENTENCES. - * @param options Options bit set, see ucasemap_open(). * @return A reference to this. * @stable ICU 3.8 */ @@ -3614,7 +3614,7 @@ private: // turn a bogus string into an empty one void unBogus(); - // implements assigment operator, copy constructor, and fastCopyFrom() + // implements assignment operator, copy constructor, and fastCopyFrom() UnicodeString ©From(const UnicodeString &src, UBool fastCopy=false); // Copies just the fields without memory management. diff --git a/thirdparty/icu4c/common/unicode/urename.h b/thirdparty/icu4c/common/unicode/urename.h index fe59fdd893..737f4b308e 100644 --- a/thirdparty/icu4c/common/unicode/urename.h +++ b/thirdparty/icu4c/common/unicode/urename.h @@ -482,6 +482,7 @@ #define ubiditransform_open U_ICU_ENTRY_POINT_RENAME(ubiditransform_open) #define ubiditransform_transform U_ICU_ENTRY_POINT_RENAME(ubiditransform_transform) #define ublock_getCode U_ICU_ENTRY_POINT_RENAME(ublock_getCode) +#define ubrk_clone U_ICU_ENTRY_POINT_RENAME(ubrk_clone) #define ubrk_close U_ICU_ENTRY_POINT_RENAME(ubrk_close) #define ubrk_countAvailable U_ICU_ENTRY_POINT_RENAME(ubrk_countAvailable) #define ubrk_current U_ICU_ENTRY_POINT_RENAME(ubrk_current) @@ -534,6 +535,7 @@ #define ucal_getTimeZoneDisplayName U_ICU_ENTRY_POINT_RENAME(ucal_getTimeZoneDisplayName) #define ucal_getTimeZoneID U_ICU_ENTRY_POINT_RENAME(ucal_getTimeZoneID) #define ucal_getTimeZoneIDForWindowsID U_ICU_ENTRY_POINT_RENAME(ucal_getTimeZoneIDForWindowsID) +#define ucal_getTimeZoneOffsetFromLocal U_ICU_ENTRY_POINT_RENAME(ucal_getTimeZoneOffsetFromLocal) #define ucal_getTimeZoneTransitionDate U_ICU_ENTRY_POINT_RENAME(ucal_getTimeZoneTransitionDate) #define ucal_getType U_ICU_ENTRY_POINT_RENAME(ucal_getType) #define ucal_getWeekendTransition U_ICU_ENTRY_POINT_RENAME(ucal_getWeekendTransition) @@ -962,6 +964,7 @@ #define uhash_compareScriptSet U_ICU_ENTRY_POINT_RENAME(uhash_compareScriptSet) #define uhash_compareUChars U_ICU_ENTRY_POINT_RENAME(uhash_compareUChars) #define uhash_compareUnicodeString U_ICU_ENTRY_POINT_RENAME(uhash_compareUnicodeString) +#define uhash_containsKey U_ICU_ENTRY_POINT_RENAME(uhash_containsKey) #define uhash_count U_ICU_ENTRY_POINT_RENAME(uhash_count) #define uhash_deleteHashtable U_ICU_ENTRY_POINT_RENAME(uhash_deleteHashtable) #define uhash_deleteScriptSet U_ICU_ENTRY_POINT_RENAME(uhash_deleteScriptSet) @@ -970,6 +973,7 @@ #define uhash_find U_ICU_ENTRY_POINT_RENAME(uhash_find) #define uhash_get U_ICU_ENTRY_POINT_RENAME(uhash_get) #define uhash_geti U_ICU_ENTRY_POINT_RENAME(uhash_geti) +#define uhash_getiAndFound U_ICU_ENTRY_POINT_RENAME(uhash_getiAndFound) #define uhash_hashCaselessUnicodeString U_ICU_ENTRY_POINT_RENAME(uhash_hashCaselessUnicodeString) #define uhash_hashChars U_ICU_ENTRY_POINT_RENAME(uhash_hashChars) #define uhash_hashIChars U_ICU_ENTRY_POINT_RENAME(uhash_hashIChars) @@ -977,12 +981,15 @@ #define uhash_hashScriptSet U_ICU_ENTRY_POINT_RENAME(uhash_hashScriptSet) #define uhash_hashUChars U_ICU_ENTRY_POINT_RENAME(uhash_hashUChars) #define uhash_hashUnicodeString U_ICU_ENTRY_POINT_RENAME(uhash_hashUnicodeString) +#define uhash_icontainsKey U_ICU_ENTRY_POINT_RENAME(uhash_icontainsKey) #define uhash_iget U_ICU_ENTRY_POINT_RENAME(uhash_iget) #define uhash_igeti U_ICU_ENTRY_POINT_RENAME(uhash_igeti) +#define uhash_igetiAndFound U_ICU_ENTRY_POINT_RENAME(uhash_igetiAndFound) #define uhash_init U_ICU_ENTRY_POINT_RENAME(uhash_init) #define uhash_initSize U_ICU_ENTRY_POINT_RENAME(uhash_initSize) #define uhash_iput U_ICU_ENTRY_POINT_RENAME(uhash_iput) #define uhash_iputi U_ICU_ENTRY_POINT_RENAME(uhash_iputi) +#define uhash_iputiAllowZero U_ICU_ENTRY_POINT_RENAME(uhash_iputiAllowZero) #define uhash_iremove U_ICU_ENTRY_POINT_RENAME(uhash_iremove) #define uhash_iremovei U_ICU_ENTRY_POINT_RENAME(uhash_iremovei) #define uhash_nextElement U_ICU_ENTRY_POINT_RENAME(uhash_nextElement) @@ -990,6 +997,7 @@ #define uhash_openSize U_ICU_ENTRY_POINT_RENAME(uhash_openSize) #define uhash_put U_ICU_ENTRY_POINT_RENAME(uhash_put) #define uhash_puti U_ICU_ENTRY_POINT_RENAME(uhash_puti) +#define uhash_putiAllowZero U_ICU_ENTRY_POINT_RENAME(uhash_putiAllowZero) #define uhash_remove U_ICU_ENTRY_POINT_RENAME(uhash_remove) #define uhash_removeAll U_ICU_ENTRY_POINT_RENAME(uhash_removeAll) #define uhash_removeElement U_ICU_ENTRY_POINT_RENAME(uhash_removeElement) @@ -1150,6 +1158,8 @@ #define ultag_isUnicodeLocaleKey U_ICU_ENTRY_POINT_RENAME(ultag_isUnicodeLocaleKey) #define ultag_isUnicodeLocaleType U_ICU_ENTRY_POINT_RENAME(ultag_isUnicodeLocaleType) #define ultag_isVariantSubtags U_ICU_ENTRY_POINT_RENAME(ultag_isVariantSubtags) +#define umeas_getPrefixBase U_ICU_ENTRY_POINT_RENAME(umeas_getPrefixBase) +#define umeas_getPrefixPower U_ICU_ENTRY_POINT_RENAME(umeas_getPrefixPower) #define umsg_applyPattern U_ICU_ENTRY_POINT_RENAME(umsg_applyPattern) #define umsg_autoQuoteApostrophe U_ICU_ENTRY_POINT_RENAME(umsg_autoQuoteApostrophe) #define umsg_clone U_ICU_ENTRY_POINT_RENAME(umsg_clone) @@ -1672,6 +1682,9 @@ #define uset_compact U_ICU_ENTRY_POINT_RENAME(uset_compact) #define uset_complement U_ICU_ENTRY_POINT_RENAME(uset_complement) #define uset_complementAll U_ICU_ENTRY_POINT_RENAME(uset_complementAll) +#define uset_complementAllCodePoints U_ICU_ENTRY_POINT_RENAME(uset_complementAllCodePoints) +#define uset_complementRange U_ICU_ENTRY_POINT_RENAME(uset_complementRange) +#define uset_complementString U_ICU_ENTRY_POINT_RENAME(uset_complementString) #define uset_contains U_ICU_ENTRY_POINT_RENAME(uset_contains) #define uset_containsAll U_ICU_ENTRY_POINT_RENAME(uset_containsAll) #define uset_containsAllCodePoints U_ICU_ENTRY_POINT_RENAME(uset_containsAllCodePoints) @@ -1695,12 +1708,15 @@ #define uset_openPatternOptions U_ICU_ENTRY_POINT_RENAME(uset_openPatternOptions) #define uset_remove U_ICU_ENTRY_POINT_RENAME(uset_remove) #define uset_removeAll U_ICU_ENTRY_POINT_RENAME(uset_removeAll) +#define uset_removeAllCodePoints U_ICU_ENTRY_POINT_RENAME(uset_removeAllCodePoints) #define uset_removeAllStrings U_ICU_ENTRY_POINT_RENAME(uset_removeAllStrings) #define uset_removeRange U_ICU_ENTRY_POINT_RENAME(uset_removeRange) #define uset_removeString U_ICU_ENTRY_POINT_RENAME(uset_removeString) #define uset_resemblesPattern U_ICU_ENTRY_POINT_RENAME(uset_resemblesPattern) #define uset_retain U_ICU_ENTRY_POINT_RENAME(uset_retain) #define uset_retainAll U_ICU_ENTRY_POINT_RENAME(uset_retainAll) +#define uset_retainAllCodePoints U_ICU_ENTRY_POINT_RENAME(uset_retainAllCodePoints) +#define uset_retainString U_ICU_ENTRY_POINT_RENAME(uset_retainString) #define uset_serialize U_ICU_ENTRY_POINT_RENAME(uset_serialize) #define uset_serializedContains U_ICU_ENTRY_POINT_RENAME(uset_serializedContains) #define uset_set U_ICU_ENTRY_POINT_RENAME(uset_set) diff --git a/thirdparty/icu4c/common/unicode/uset.h b/thirdparty/icu4c/common/unicode/uset.h index 502ea8dc14..1d0daf9d09 100644 --- a/thirdparty/icu4c/common/unicode/uset.h +++ b/thirdparty/icu4c/common/unicode/uset.h @@ -582,8 +582,8 @@ U_CAPI void U_EXPORT2 uset_addString(USet* set, const UChar* str, int32_t strLen); /** - * Adds each of the characters in this string to the set. Thus "ch" => {"c", "h"} - * If this set already any particular character, it has no effect on that character. + * Adds each of the characters in this string to the set. Note: "ch" => {"c", "h"} + * If this set already contains any particular character, it has no effect on that character. * A frozen set will not be modified. * @param set the object to which to add the character * @param str the source string @@ -628,6 +628,20 @@ uset_removeRange(USet* set, UChar32 start, UChar32 end); U_CAPI void U_EXPORT2 uset_removeString(USet* set, const UChar* str, int32_t strLen); +#ifndef U_HIDE_DRAFT_API +/** + * Removes EACH of the characters in this string. Note: "ch" == {"c", "h"} + * A frozen set will not be modified. + * + * @param set the object to be modified + * @param str the string + * @param length the length of the string, or -1 if NUL-terminated + * @draft ICU 69 + */ +U_CAPI void U_EXPORT2 +uset_removeAllCodePoints(USet *set, const UChar *str, int32_t length); +#endif // U_HIDE_DRAFT_API + /** * Removes from this set all of its elements that are contained in the * specified set. This operation effectively modifies this @@ -650,15 +664,41 @@ uset_removeAll(USet* set, const USet* removeSet); * A frozen set will not be modified. * * @param set the object for which to retain only the specified range - * @param start first character, inclusive, of range to be retained - * to this set. - * @param end last character, inclusive, of range to be retained - * to this set. + * @param start first character, inclusive, of range + * @param end last character, inclusive, of range * @stable ICU 3.2 */ U_CAPI void U_EXPORT2 uset_retain(USet* set, UChar32 start, UChar32 end); +#ifndef U_HIDE_DRAFT_API +/** + * Retains only the specified string from this set if it is present. + * Upon return this set will be empty if it did not contain s, or + * will only contain s if it did contain s. + * A frozen set will not be modified. + * + * @param set the object to be modified + * @param str the string + * @param length the length of the string, or -1 if NUL-terminated + * @draft ICU 69 + */ +U_CAPI void U_EXPORT2 +uset_retainString(USet *set, const UChar *str, int32_t length); + +/** + * Retains EACH of the characters in this string. Note: "ch" == {"c", "h"} + * A frozen set will not be modified. + * + * @param set the object to be modified + * @param str the string + * @param length the length of the string, or -1 if NUL-terminated + * @draft ICU 69 + */ +U_CAPI void U_EXPORT2 +uset_retainAllCodePoints(USet *set, const UChar *str, int32_t length); +#endif // U_HIDE_DRAFT_API + /** * Retains only the elements in this set that are contained in the * specified set. In other words, removes from this set all of @@ -696,6 +736,49 @@ uset_compact(USet* set); U_CAPI void U_EXPORT2 uset_complement(USet* set); +#ifndef U_HIDE_DRAFT_API +/** + * Complements the specified range in this set. Any character in + * the range will be removed if it is in this set, or will be + * added if it is not in this set. If <code>start > end</code> + * then an empty range is complemented, leaving the set unchanged. + * This is equivalent to a boolean logic XOR. + * A frozen set will not be modified. + * + * @param set the object to be modified + * @param start first character, inclusive, of range + * @param end last character, inclusive, of range + * @draft ICU 69 + */ +U_CAPI void U_EXPORT2 +uset_complementRange(USet *set, UChar32 start, UChar32 end); + +/** + * Complements the specified string in this set. + * The string will be removed if it is in this set, or will be added if it is not in this set. + * A frozen set will not be modified. + * + * @param set the object to be modified + * @param str the string + * @param length the length of the string, or -1 if NUL-terminated + * @draft ICU 69 + */ +U_CAPI void U_EXPORT2 +uset_complementString(USet *set, const UChar *str, int32_t length); + +/** + * Complements EACH of the characters in this string. Note: "ch" == {"c", "h"} + * A frozen set will not be modified. + * + * @param set the object to be modified + * @param str the string + * @param length the length of the string, or -1 if NUL-terminated + * @draft ICU 69 + */ +U_CAPI void U_EXPORT2 +uset_complementAllCodePoints(USet *set, const UChar *str, int32_t length); +#endif // U_HIDE_DRAFT_API + /** * Complements in this set all elements contained in the specified * set. Any character in the other set will be removed if it is diff --git a/thirdparty/icu4c/common/unicode/ushape.h b/thirdparty/icu4c/common/unicode/ushape.h index fed4869abd..14371edc8f 100644 --- a/thirdparty/icu4c/common/unicode/ushape.h +++ b/thirdparty/icu4c/common/unicode/ushape.h @@ -323,7 +323,7 @@ u_shapeArabic(const UChar *source, int32_t sourceLength, #define U_SHAPE_PRESERVE_PRESENTATION 0x8000 /** Presentation form option: * Replace Arabic Presentation Forms-A and Arabic Presentationo Forms-B with - * their unshaped correspondants in range 0+06xx, before shaping. + * their unshaped correspondents in range 0+06xx, before shaping. * @stable ICU 3.6 */ #define U_SHAPE_PRESERVE_PRESENTATION_NOOP 0 diff --git a/thirdparty/icu4c/common/unicode/utrace.h b/thirdparty/icu4c/common/unicode/utrace.h index 28c313c582..677486f473 100644 --- a/thirdparty/icu4c/common/unicode/utrace.h +++ b/thirdparty/icu4c/common/unicode/utrace.h @@ -173,24 +173,23 @@ typedef enum UTraceFunctionNumber { UTRACE_RES_DATA_LIMIT, #endif // U_HIDE_INTERNAL_API -#ifndef U_HIDE_DRAFT_API /** * The lowest break iterator location. - * @draft ICU 67 + * @stable ICU 67 */ UTRACE_UBRK_START=0x4000, /** * Indicates that a character instance of break iterator was created. * - * @draft ICU 67 + * @stable ICU 67 */ UTRACE_UBRK_CREATE_CHARACTER = UTRACE_UBRK_START, /** * Indicates that a word instance of break iterator was created. * - * @draft ICU 67 + * @stable ICU 67 */ UTRACE_UBRK_CREATE_WORD, @@ -200,21 +199,21 @@ typedef enum UTraceFunctionNumber { * Provides one C-style string to UTraceData: the lb value ("", * "loose", "strict", or "normal"). * - * @draft ICU 67 + * @stable ICU 67 */ UTRACE_UBRK_CREATE_LINE, /** * Indicates that a sentence instance of break iterator was created. * - * @draft ICU 67 + * @stable ICU 67 */ UTRACE_UBRK_CREATE_SENTENCE, /** * Indicates that a title instance of break iterator was created. * - * @draft ICU 67 + * @stable ICU 67 */ UTRACE_UBRK_CREATE_TITLE, @@ -224,12 +223,10 @@ typedef enum UTraceFunctionNumber { * Provides one C-style string to UTraceData: the script code of what * the break engine cover ("Hani", "Khmr", "Laoo", "Mymr", or "Thai"). * - * @draft ICU 67 + * @stable ICU 67 */ UTRACE_UBRK_CREATE_BREAK_ENGINE, -#endif // U_HIDE_DRAFT_API - #ifndef U_HIDE_INTERNAL_API /** * One more than the highest normal break iterator trace location. diff --git a/thirdparty/icu4c/common/unicode/uvernum.h b/thirdparty/icu4c/common/unicode/uvernum.h index a46481a3fe..b09d4943c1 100644 --- a/thirdparty/icu4c/common/unicode/uvernum.h +++ b/thirdparty/icu4c/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 68 +#define U_ICU_VERSION_MAJOR_NUM 69 /** 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 _68 +#define U_ICU_VERSION_SUFFIX _69 /** * \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 "68.2" +#define U_ICU_VERSION "69.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 "68" +#define U_ICU_VERSION_SHORT "69" #ifndef U_HIDE_INTERNAL_API /** Data version in ICU4C. * @internal ICU 4.4 Internal Use Only **/ -#define U_ICU_DATA_VERSION "68.2" +#define U_ICU_DATA_VERSION "69.1" #endif /* U_HIDE_INTERNAL_API */ /*=========================================================================== diff --git a/thirdparty/icu4c/common/uniset.cpp b/thirdparty/icu4c/common/uniset.cpp index b73d612f24..461e5a7197 100644 --- a/thirdparty/icu4c/common/uniset.cpp +++ b/thirdparty/icu4c/common/uniset.cpp @@ -30,24 +30,6 @@ #include "bmpset.h" #include "unisetspan.h" -// Define UChar constants using hex for EBCDIC compatibility -// Used #define to reduce private static exports and memory access time. -#define SET_OPEN ((UChar)0x005B) /*[*/ -#define SET_CLOSE ((UChar)0x005D) /*]*/ -#define HYPHEN ((UChar)0x002D) /*-*/ -#define COMPLEMENT ((UChar)0x005E) /*^*/ -#define COLON ((UChar)0x003A) /*:*/ -#define BACKSLASH ((UChar)0x005C) /*\*/ -#define INTERSECTION ((UChar)0x0026) /*&*/ -#define UPPER_U ((UChar)0x0055) /*U*/ -#define LOWER_U ((UChar)0x0075) /*u*/ -#define OPEN_BRACE ((UChar)123) /*{*/ -#define CLOSE_BRACE ((UChar)125) /*}*/ -#define UPPER_P ((UChar)0x0050) /*P*/ -#define LOWER_P ((UChar)0x0070) /*p*/ -#define UPPER_N ((UChar)78) /*N*/ -#define EQUALS ((UChar)0x003D) /*=*/ - // HIGH_VALUE > all valid values. 110000 for codepoints #define UNICODESET_HIGH 0x0110000 @@ -444,7 +426,6 @@ UBool UnicodeSet::contains(UChar32 start, UChar32 end) const { * @return <tt>true</tt> if this set contains the specified string */ UBool UnicodeSet::contains(const UnicodeString& s) const { - if (s.length() == 0) return FALSE; int32_t cp = getSingleCP(s); if (cp < 0) { return stringsContains(s); @@ -559,11 +540,9 @@ UBool UnicodeSet::matchesIndexValue(uint8_t v) const { if (hasStrings()) { for (i=0; i<strings->size(); ++i) { const UnicodeString& s = *(const UnicodeString*)strings->elementAt(i); - //if (s.length() == 0) { - // // Empty strings match everything - // return TRUE; - //} - // assert(s.length() != 0); // We enforce this elsewhere + if (s.isEmpty()) { + continue; // skip the empty string + } UChar32 c = s.char32At(0); if ((c & 0xFF) == v) { return TRUE; @@ -582,9 +561,6 @@ UMatchDegree UnicodeSet::matches(const Replaceable& text, int32_t limit, UBool incremental) { if (offset == limit) { - // Strings, if any, have length != 0, so we don't worry - // about them here. If we ever allow zero-length strings - // we much check for them here. if (contains(U_ETHER)) { return incremental ? U_PARTIAL_MATCH : U_MATCH; } else { @@ -614,11 +590,9 @@ UMatchDegree UnicodeSet::matches(const Replaceable& text, for (i=0; i<strings->size(); ++i) { const UnicodeString& trial = *(const UnicodeString*)strings->elementAt(i); - - //if (trial.length() == 0) { - // return U_MATCH; // null-string always matches - //} - // assert(trial.length() != 0); // We ensure this elsewhere + if (trial.isEmpty()) { + continue; // skip the empty string + } UChar c = trial.charAt(forward ? 0 : trial.length() - 1); @@ -971,12 +945,12 @@ UnicodeSet& UnicodeSet::add(UChar32 c) { * present. If this set already contains the multicharacter, * the call leaves this set unchanged. * Thus "ch" => {"ch"} - * <br><b>Warning: you cannot add an empty string ("") to a UnicodeSet.</b> + * * @param s the source string * @return the modified set, for chaining */ UnicodeSet& UnicodeSet::add(const UnicodeString& s) { - if (s.length() == 0 || isFrozen() || isBogus()) return *this; + if (isFrozen() || isBogus()) return *this; int32_t cp = getSingleCP(s); if (cp < 0) { if (!stringsContains(s)) { @@ -991,8 +965,7 @@ UnicodeSet& UnicodeSet::add(const UnicodeString& s) { /** * Adds the given string, in order, to 'strings'. The given string - * must have been checked by the caller to not be empty and to not - * already be in 'strings'. + * must have been checked by the caller to not already be in 'strings'. */ void UnicodeSet::_add(const UnicodeString& s) { if (isFrozen() || isBogus()) { @@ -1021,16 +994,13 @@ void UnicodeSet::_add(const UnicodeString& s) { * @param string to test */ int32_t UnicodeSet::getSingleCP(const UnicodeString& s) { - //if (s.length() < 1) { - // throw new IllegalArgumentException("Can't use zero-length strings in UnicodeSet"); - //} - if (s.length() > 2) return -1; - if (s.length() == 1) return s.charAt(0); - - // at this point, len = 2 - UChar32 cp = s.char32At(0); - if (cp > 0xFFFF) { // is surrogate pair - return cp; + int32_t sLength = s.length(); + if (sLength == 1) return s.charAt(0); + if (sLength == 2) { + UChar32 cp = s.char32At(0); + if (cp > 0xFFFF) { // is surrogate pair + return cp; + } } return -1; } @@ -1150,6 +1120,26 @@ UnicodeSet& UnicodeSet::retain(UChar32 c) { return retain(c, c); } +UnicodeSet& UnicodeSet::retain(const UnicodeString &s) { + if (isFrozen() || isBogus()) { return *this; } + UChar32 cp = getSingleCP(s); + if (cp < 0) { + bool isIn = stringsContains(s); + // Check for getRangeCount() first to avoid somewhat-expensive size() + // when there are single code points. + if (isIn && getRangeCount() == 0 && size() == 1) { + return *this; + } + clear(); + if (isIn) { + _add(s); + } + } else { + retain(cp, cp); + } + return *this; +} + /** * Removes the specified range from this set if it is present. * The set will not contain the specified range once the call @@ -1186,7 +1176,7 @@ UnicodeSet& UnicodeSet::remove(UChar32 c) { * @return the modified set, for chaining */ UnicodeSet& UnicodeSet::remove(const UnicodeString& s) { - if (s.length() == 0 || isFrozen() || isBogus()) return *this; + if (isFrozen() || isBogus()) return *this; int32_t cp = getSingleCP(s); if (cp < 0) { if (strings != nullptr && strings->removeElement((void*) &s)) { @@ -1252,12 +1242,12 @@ UnicodeSet& UnicodeSet::complement(void) { * Complement the specified string in this set. * The set will not contain the specified string once the call * returns. - * <br><b>Warning: you cannot add an empty string ("") to a UnicodeSet.</b> + * * @param s the string to complement * @return this object, for chaining */ UnicodeSet& UnicodeSet::complement(const UnicodeString& s) { - if (s.length() == 0 || isFrozen() || isBogus()) return *this; + if (isFrozen() || isBogus()) return *this; int32_t cp = getSingleCP(s); if (cp < 0) { if (stringsContains(s)) { @@ -2001,22 +1991,22 @@ escapeUnprintable) { } // Okay to let ':' pass through switch (c) { - case SET_OPEN: - case SET_CLOSE: - case HYPHEN: - case COMPLEMENT: - case INTERSECTION: - case BACKSLASH: - case OPEN_BRACE: - case CLOSE_BRACE: - case COLON: + case u'[': + case u']': + case u'-': + case u'^': + case u'&': + case u'\\': + case u'{': + case u'}': + case u':': case SymbolTable::SYMBOL_REF: - buf.append(BACKSLASH); + buf.append(u'\\'); break; default: // Escape whitespace if (PatternProps::isWhiteSpace(c)) { - buf.append(BACKSLASH); + buf.append(u'\\'); } break; } @@ -2049,7 +2039,7 @@ UnicodeString& UnicodeSet::_toPattern(UnicodeString& result, backslashCount = 0; } else { result.append(c); - if (c == BACKSLASH) { + if (c == u'\\') { ++backslashCount; } else { backslashCount = 0; @@ -2082,13 +2072,13 @@ UnicodeString& UnicodeSet::toPattern(UnicodeString& result, UnicodeString& UnicodeSet::_generatePattern(UnicodeString& result, UBool escapeUnprintable) const { - result.append(SET_OPEN); + result.append(u'['); // // Check against the predefined categories. We implicitly build // // up ALL category sets the first time toPattern() is called. // for (int8_t cat=0; cat<Unicode::GENERAL_TYPES_COUNT; ++cat) { // if (*this == getCategorySet(cat)) { -// result.append(COLON); +// result.append(u':'); // result.append(CATEGORY_NAMES, cat*2, 2); // return result.append(CATEGORY_CLOSE); // } @@ -2104,7 +2094,7 @@ UnicodeString& UnicodeSet::_generatePattern(UnicodeString& result, getRangeEnd(count-1) == MAX_VALUE) { // Emit the inverse - result.append(COMPLEMENT); + result.append(u'^'); for (int32_t i = 1; i < count; ++i) { UChar32 start = getRangeEnd(i-1)+1; @@ -2112,7 +2102,7 @@ UnicodeString& UnicodeSet::_generatePattern(UnicodeString& result, _appendToPat(result, start, escapeUnprintable); if (start != end) { if ((start+1) != end) { - result.append(HYPHEN); + result.append(u'-'); } _appendToPat(result, end, escapeUnprintable); } @@ -2127,7 +2117,7 @@ UnicodeString& UnicodeSet::_generatePattern(UnicodeString& result, _appendToPat(result, start, escapeUnprintable); if (start != end) { if ((start+1) != end) { - result.append(HYPHEN); + result.append(u'-'); } _appendToPat(result, end, escapeUnprintable); } @@ -2136,14 +2126,14 @@ UnicodeString& UnicodeSet::_generatePattern(UnicodeString& result, if (strings != nullptr) { for (int32_t i = 0; i<strings->size(); ++i) { - result.append(OPEN_BRACE); + result.append(u'{'); _appendToPat(result, *(const UnicodeString*) strings->elementAt(i), escapeUnprintable); - result.append(CLOSE_BRACE); + result.append(u'}'); } } - return result.append(SET_CLOSE); + return result.append(u']'); } /** diff --git a/thirdparty/icu4c/common/uniset_props.cpp b/thirdparty/icu4c/common/uniset_props.cpp index 37277fcb75..8fde5abcdd 100644 --- a/thirdparty/icu4c/common/uniset_props.cpp +++ b/thirdparty/icu4c/common/uniset_props.cpp @@ -47,31 +47,6 @@ U_NAMESPACE_USE -// Define UChar constants using hex for EBCDIC compatibility -// Used #define to reduce private static exports and memory access time. -#define SET_OPEN ((UChar)0x005B) /*[*/ -#define SET_CLOSE ((UChar)0x005D) /*]*/ -#define HYPHEN ((UChar)0x002D) /*-*/ -#define COMPLEMENT ((UChar)0x005E) /*^*/ -#define COLON ((UChar)0x003A) /*:*/ -#define BACKSLASH ((UChar)0x005C) /*\*/ -#define INTERSECTION ((UChar)0x0026) /*&*/ -#define UPPER_U ((UChar)0x0055) /*U*/ -#define LOWER_U ((UChar)0x0075) /*u*/ -#define OPEN_BRACE ((UChar)123) /*{*/ -#define CLOSE_BRACE ((UChar)125) /*}*/ -#define UPPER_P ((UChar)0x0050) /*P*/ -#define LOWER_P ((UChar)0x0070) /*p*/ -#define UPPER_N ((UChar)78) /*N*/ -#define EQUALS ((UChar)0x003D) /*=*/ - -//static const UChar POSIX_OPEN[] = { SET_OPEN,COLON,0 }; // "[:" -static const UChar POSIX_CLOSE[] = { COLON,SET_CLOSE,0 }; // ":]" -//static const UChar PERL_OPEN[] = { BACKSLASH,LOWER_P,0 }; // "\\p" -//static const UChar PERL_CLOSE[] = { CLOSE_BRACE,0 }; // "}" -//static const UChar NAME_OPEN[] = { BACKSLASH,UPPER_N,0 }; // "\\N" -static const UChar HYPHEN_RIGHT_BRACE[] = {HYPHEN,SET_CLOSE,0}; /*-]*/ - // Special property set IDs static const char ANY[] = "ANY"; // [\u0000-\U0010FFFF] static const char ASCII[] = "ASCII"; // [\u0000-\u007F] @@ -81,12 +56,6 @@ static const char ASSIGNED[] = "Assigned"; // [:^Cn:] #define NAME_PROP "na" #define NAME_PROP_LENGTH 2 -/** - * Delimiter string used in patterns to close a category reference: - * ":]". Example: "[:Lu:]". - */ -//static const UChar CATEGORY_CLOSE[] = {COLON, SET_CLOSE, 0x0000}; /* ":]" */ - // Cached sets ------------------------------------------------------------- *** U_CDECL_BEGIN @@ -140,27 +109,27 @@ uniset_getUnicode32Instance(UErrorCode &errorCode) { static inline UBool isPerlOpen(const UnicodeString &pattern, int32_t pos) { UChar c; - return pattern.charAt(pos)==BACKSLASH && ((c=pattern.charAt(pos+1))==LOWER_P || c==UPPER_P); + return pattern.charAt(pos)==u'\\' && ((c=pattern.charAt(pos+1))==u'p' || c==u'P'); } /*static inline UBool isPerlClose(const UnicodeString &pattern, int32_t pos) { - return pattern.charAt(pos)==CLOSE_BRACE; + return pattern.charAt(pos)==u'}'; }*/ static inline UBool isNameOpen(const UnicodeString &pattern, int32_t pos) { - return pattern.charAt(pos)==BACKSLASH && pattern.charAt(pos+1)==UPPER_N; + return pattern.charAt(pos)==u'\\' && pattern.charAt(pos+1)==u'N'; } static inline UBool isPOSIXOpen(const UnicodeString &pattern, int32_t pos) { - return pattern.charAt(pos)==SET_OPEN && pattern.charAt(pos+1)==COLON; + return pattern.charAt(pos)==u'[' && pattern.charAt(pos+1)==u':'; } /*static inline UBool isPOSIXClose(const UnicodeString &pattern, int32_t pos) { - return pattern.charAt(pos)==COLON && pattern.charAt(pos+1)==SET_CLOSE; + return pattern.charAt(pos)==u':' && pattern.charAt(pos+1)==u']'; }*/ // TODO memory debugging provided inside uniset.cpp @@ -326,9 +295,8 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, while (mode != 2 && !chars.atEnd()) { U_ASSERT((lastItem == 0 && op == 0) || - (lastItem == 1 && (op == 0 || op == HYPHEN /*'-'*/)) || - (lastItem == 2 && (op == 0 || op == HYPHEN /*'-'*/ || - op == INTERSECTION /*'&'*/))); + (lastItem == 1 && (op == 0 || op == u'-')) || + (lastItem == 2 && (op == 0 || op == u'-' || op == u'&'))); UChar32 c = 0; UBool literal = FALSE; @@ -356,27 +324,27 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, c = chars.next(opts, literal, ec); if (U_FAILURE(ec)) return; - if (c == 0x5B /*'['*/ && !literal) { + if (c == u'[' && !literal) { if (mode == 1) { chars.setPos(backup); // backup setMode = 1; } else { // Handle opening '[' delimiter mode = 1; - patLocal.append((UChar) 0x5B /*'['*/); + patLocal.append(u'['); chars.getPos(backup); // prepare to backup c = chars.next(opts, literal, ec); if (U_FAILURE(ec)) return; - if (c == 0x5E /*'^'*/ && !literal) { + if (c == u'^' && !literal) { invert = TRUE; - patLocal.append((UChar) 0x5E /*'^'*/); + patLocal.append(u'^'); chars.getPos(backup); // prepare to backup c = chars.next(opts, literal, ec); if (U_FAILURE(ec)) return; } // Fall through to handle special leading '-'; // otherwise restart loop for nested [], \p{}, etc. - if (c == HYPHEN /*'-'*/) { + if (c == u'-') { literal = TRUE; // Fall through to handle literal '-' below } else { @@ -418,7 +386,7 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, op = 0; } - if (op == HYPHEN /*'-'*/ || op == INTERSECTION /*'&'*/) { + if (op == u'-' || op == u'&') { patLocal.append(op); } @@ -454,10 +422,10 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, } switch (op) { - case HYPHEN: /*'-'*/ + case u'-': removeAll(*nested); break; - case INTERSECTION: /*'&'*/ + case u'&': retainAll(*nested); break; case 0: @@ -483,24 +451,24 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, if (!literal) { switch (c) { - case 0x5D /*']'*/: + case u']': if (lastItem == 1) { add(lastChar, lastChar); _appendToPat(patLocal, lastChar, FALSE); } // Treat final trailing '-' as a literal - if (op == HYPHEN /*'-'*/) { + if (op == u'-') { add(op, op); patLocal.append(op); - } else if (op == INTERSECTION /*'&'*/) { + } else if (op == u'&') { // syntaxError(chars, "Trailing '&'"); ec = U_MALFORMED_SET; return; } - patLocal.append((UChar) 0x5D /*']'*/); + patLocal.append(u']'); mode = 2; continue; - case HYPHEN /*'-'*/: + case u'-': if (op == 0) { if (lastItem != 0) { op = (UChar) c; @@ -510,8 +478,8 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, add(c, c); c = chars.next(opts, literal, ec); if (U_FAILURE(ec)) return; - if (c == 0x5D /*']'*/ && !literal) { - patLocal.append(HYPHEN_RIGHT_BRACE, 2); + if (c == u']' && !literal) { + patLocal.append(u"-]", 2); mode = 2; continue; } @@ -520,7 +488,7 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, // syntaxError(chars, "'-' not after char or set"); ec = U_MALFORMED_SET; return; - case INTERSECTION /*'&'*/: + case u'&': if (lastItem == 2 && op == 0) { op = (UChar) c; continue; @@ -528,11 +496,11 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, // syntaxError(chars, "'&' not after set"); ec = U_MALFORMED_SET; return; - case 0x5E /*'^'*/: + case u'^': // syntaxError(chars, "'^' not after '['"); ec = U_MALFORMED_SET; return; - case 0x7B /*'{'*/: + case u'{': if (op != 0) { // syntaxError(chars, "Missing operand after operator"); ec = U_MALFORMED_SET; @@ -549,13 +517,13 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, while (!chars.atEnd()) { c = chars.next(opts, literal, ec); if (U_FAILURE(ec)) return; - if (c == 0x7D /*'}'*/ && !literal) { + if (c == u'}' && !literal) { ok = TRUE; break; } buf.append(c); } - if (buf.length() < 1 || !ok) { + if (!ok) { // syntaxError(chars, "Invalid multicharacter string"); ec = U_MALFORMED_SET; return; @@ -565,9 +533,9 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, // we don't need to drop through to the further // processing add(buf); - patLocal.append((UChar) 0x7B /*'{'*/); + patLocal.append(u'{'); _appendToPat(patLocal, buf, FALSE); - patLocal.append((UChar) 0x7D /*'}'*/); + patLocal.append(u'}'); continue; case SymbolTable::SYMBOL_REF: // symbols nosymbols @@ -580,7 +548,7 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, chars.getPos(backup); c = chars.next(opts, literal, ec); if (U_FAILURE(ec)) return; - UBool anchor = (c == 0x5D /*']'*/ && !literal); + UBool anchor = (c == u']' && !literal); if (symbols == 0 && !anchor) { c = SymbolTable::SYMBOL_REF; chars.setPos(backup); @@ -594,7 +562,7 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, add(U_ETHER); usePat = TRUE; patLocal.append((UChar) SymbolTable::SYMBOL_REF); - patLocal.append((UChar) 0x5D /*']'*/); + patLocal.append(u']'); mode = 2; continue; } @@ -617,7 +585,7 @@ void UnicodeSet::applyPattern(RuleCharacterIterator& chars, lastChar = c; break; case 1: - if (op == HYPHEN /*'-'*/) { + if (op == u'-') { if (lastChar >= c) { // Don't allow redundant (a-a) or empty (b-a) ranges; // these are most likely typos. @@ -1036,11 +1004,11 @@ UBool UnicodeSet::resemblesPropertyPattern(RuleCharacterIterator& chars, RuleCharacterIterator::Pos pos; chars.getPos(pos); UChar32 c = chars.next(iterOpts, literal, ec); - if (c == 0x5B /*'['*/ || c == 0x5C /*'\\'*/) { + if (c == u'[' || c == u'\\') { UChar32 d = chars.next(iterOpts & ~RuleCharacterIterator::SKIP_WHITESPACE, literal, ec); - result = (c == 0x5B /*'['*/) ? (d == 0x3A /*':'*/) : - (d == 0x4E /*'N'*/ || d == 0x70 /*'p'*/ || d == 0x50 /*'P'*/); + result = (c == u'[') ? (d == u':') : + (d == u'N' || d == u'p' || d == u'P'); } chars.setPos(pos); return result && U_SUCCESS(ec); @@ -1071,17 +1039,17 @@ UnicodeSet& UnicodeSet::applyPropertyPattern(const UnicodeString& pattern, posix = TRUE; pos += 2; pos = ICU_Utility::skipWhitespace(pattern, pos); - if (pos < pattern.length() && pattern.charAt(pos) == COMPLEMENT) { + if (pos < pattern.length() && pattern.charAt(pos) == u'^') { ++pos; invert = TRUE; } } else if (isPerlOpen(pattern, pos) || isNameOpen(pattern, pos)) { UChar c = pattern.charAt(pos+1); - invert = (c == UPPER_P); - isName = (c == UPPER_N); + invert = (c == u'P'); + isName = (c == u'N'); pos += 2; pos = ICU_Utility::skipWhitespace(pattern, pos); - if (pos == pattern.length() || pattern.charAt(pos++) != OPEN_BRACE) { + if (pos == pattern.length() || pattern.charAt(pos++) != u'{') { // Syntax error; "\p" or "\P" not followed by "{" FAIL(ec); } @@ -1093,9 +1061,9 @@ UnicodeSet& UnicodeSet::applyPropertyPattern(const UnicodeString& pattern, // Look for the matching close delimiter, either :] or } int32_t close; if (posix) { - close = pattern.indexOf(POSIX_CLOSE, 2, pos); + close = pattern.indexOf(u":]", 2, pos); } else { - close = pattern.indexOf(CLOSE_BRACE, pos); + close = pattern.indexOf(u'}', pos); } if (close < 0) { // Syntax error; close delimiter missing @@ -1105,7 +1073,7 @@ UnicodeSet& UnicodeSet::applyPropertyPattern(const UnicodeString& pattern, // Look for an '=' sign. If this is present, we will parse a // medium \p{gc=Cf} or long \p{GeneralCategory=Format} // pattern. - int32_t equals = pattern.indexOf(EQUALS, pos); + int32_t equals = pattern.indexOf(u'=', pos); UnicodeString propName, valueName; if (equals >= 0 && equals < close && !isName) { // Equals seen; parse medium/long pattern diff --git a/thirdparty/icu4c/common/unisetspan.cpp b/thirdparty/icu4c/common/unisetspan.cpp index 68e44d91ee..fe0d74f5b2 100644 --- a/thirdparty/icu4c/common/unisetspan.cpp +++ b/thirdparty/icu4c/common/unisetspan.cpp @@ -231,6 +231,9 @@ UnicodeSetStringSpan::UnicodeSetStringSpan(const UnicodeSet &set, const UnicodeString &string=*(const UnicodeString *)strings.elementAt(i); const UChar *s16=string.getBuffer(); int32_t length16=string.length(); + if (length16==0) { + continue; // skip the empty string + } UBool thisRelevant; spanLength=spanSet.span(s16, length16, USET_SPAN_CONTAINED); if(spanLength<length16) { // Relevant string. @@ -312,7 +315,7 @@ UnicodeSetStringSpan::UnicodeSetStringSpan(const UnicodeSet &set, const UChar *s16=string.getBuffer(); int32_t length16=string.length(); spanLength=spanSet.span(s16, length16, USET_SPAN_CONTAINED); - if(spanLength<length16) { // Relevant string. + if(spanLength<length16 && length16>0) { // Relevant string. if(which&UTF16) { if(which&CONTAINED) { if(which&FWD) { @@ -362,7 +365,7 @@ UnicodeSetStringSpan::UnicodeSetStringSpan(const UnicodeSet &set, addToSpanNotSet(c); } } - } else { // Irrelevant string. + } else { // Irrelevant string. (Also the empty string.) if(which&UTF8) { if(which&CONTAINED) { // Only necessary for LONGEST_MATCH. uint8_t *s8=utf8+utf8Count; @@ -653,11 +656,12 @@ int32_t UnicodeSetStringSpan::span(const UChar *s, int32_t length, USetSpanCondi for(i=0; i<stringsLength; ++i) { int32_t overlap=spanLengths[i]; if(overlap==ALL_CP_CONTAINED) { - continue; // Irrelevant string. + continue; // Irrelevant string. (Also the empty string.) } const UnicodeString &string=*(const UnicodeString *)strings.elementAt(i); const UChar *s16=string.getBuffer(); int32_t length16=string.length(); + U_ASSERT(length>0); // Try to match this string at pos-overlap..pos. if(overlap>=LONG_SPAN) { @@ -697,6 +701,9 @@ int32_t UnicodeSetStringSpan::span(const UChar *s, int32_t length, USetSpanCondi const UnicodeString &string=*(const UnicodeString *)strings.elementAt(i); const UChar *s16=string.getBuffer(); int32_t length16=string.length(); + if (length16==0) { + continue; // skip the empty string + } // Try to match this string at pos-overlap..pos. if(overlap>=LONG_SPAN) { @@ -817,11 +824,12 @@ int32_t UnicodeSetStringSpan::spanBack(const UChar *s, int32_t length, USetSpanC for(i=0; i<stringsLength; ++i) { int32_t overlap=spanBackLengths[i]; if(overlap==ALL_CP_CONTAINED) { - continue; // Irrelevant string. + continue; // Irrelevant string. (Also the empty string.) } const UnicodeString &string=*(const UnicodeString *)strings.elementAt(i); const UChar *s16=string.getBuffer(); int32_t length16=string.length(); + U_ASSERT(length>0); // Try to match this string at pos-(length16-overlap)..pos-length16. if(overlap>=LONG_SPAN) { @@ -863,6 +871,9 @@ int32_t UnicodeSetStringSpan::spanBack(const UChar *s, int32_t length, USetSpanC const UnicodeString &string=*(const UnicodeString *)strings.elementAt(i); const UChar *s16=string.getBuffer(); int32_t length16=string.length(); + if (length16==0) { + continue; // skip the empty string + } // Try to match this string at pos-(length16-overlap)..pos-length16. if(overlap>=LONG_SPAN) { @@ -1358,11 +1369,12 @@ int32_t UnicodeSetStringSpan::spanNot(const UChar *s, int32_t length) const { // Try to match the strings at pos. for(i=0; i<stringsLength; ++i) { if(spanLengths[i]==ALL_CP_CONTAINED) { - continue; // Irrelevant string. + continue; // Irrelevant string. (Also the empty string.) } const UnicodeString &string=*(const UnicodeString *)strings.elementAt(i); const UChar *s16=string.getBuffer(); int32_t length16=string.length(); + U_ASSERT(length>0); if(length16<=rest && matches16CPB(s, pos, length, s16, length16)) { return pos; // There is a set element at pos. } @@ -1401,11 +1413,12 @@ int32_t UnicodeSetStringSpan::spanNotBack(const UChar *s, int32_t length) const // it is easier and we only need to know whether the string is irrelevant // which is the same in either array. if(spanLengths[i]==ALL_CP_CONTAINED) { - continue; // Irrelevant string. + continue; // Irrelevant string. (Also the empty string.) } const UnicodeString &string=*(const UnicodeString *)strings.elementAt(i); const UChar *s16=string.getBuffer(); int32_t length16=string.length(); + U_ASSERT(length>0); if(length16<=pos && matches16CPB(s, pos-length16, length, s16, length16)) { return pos; // There is a set element at pos. } diff --git a/thirdparty/icu4c/common/uprops.h b/thirdparty/icu4c/common/uprops.h index 8bf929919f..09830bdeb9 100644 --- a/thirdparty/icu4c/common/uprops.h +++ b/thirdparty/icu4c/common/uprops.h @@ -310,55 +310,12 @@ u_isgraphPOSIX(UChar32 c); U_CFUNC UBool u_isprintPOSIX(UChar32 c); -/** Turn a bit index into a bit flag. @internal */ -#define FLAG(n) ((uint32_t)1<<(n)) - -/** Flags for general categories in the order of UCharCategory. @internal */ -#define _Cn FLAG(U_GENERAL_OTHER_TYPES) -#define _Lu FLAG(U_UPPERCASE_LETTER) -#define _Ll FLAG(U_LOWERCASE_LETTER) -#define _Lt FLAG(U_TITLECASE_LETTER) -#define _Lm FLAG(U_MODIFIER_LETTER) -/* #define _Lo FLAG(U_OTHER_LETTER) -- conflicts with MS Visual Studio 9.0 xiosbase */ -#define _Mn FLAG(U_NON_SPACING_MARK) -#define _Me FLAG(U_ENCLOSING_MARK) -#define _Mc FLAG(U_COMBINING_SPACING_MARK) -#define _Nd FLAG(U_DECIMAL_DIGIT_NUMBER) -#define _Nl FLAG(U_LETTER_NUMBER) -#define _No FLAG(U_OTHER_NUMBER) -#define _Zs FLAG(U_SPACE_SEPARATOR) -#define _Zl FLAG(U_LINE_SEPARATOR) -#define _Zp FLAG(U_PARAGRAPH_SEPARATOR) -#define _Cc FLAG(U_CONTROL_CHAR) -#define _Cf FLAG(U_FORMAT_CHAR) -#define _Co FLAG(U_PRIVATE_USE_CHAR) -#define _Cs FLAG(U_SURROGATE) -#define _Pd FLAG(U_DASH_PUNCTUATION) -#define _Ps FLAG(U_START_PUNCTUATION) -/* #define _Pe FLAG(U_END_PUNCTUATION) -- conflicts with MS Visual Studio 9.0 xlocnum */ -/* #define _Pc FLAG(U_CONNECTOR_PUNCTUATION) -- conflicts with MS Visual Studio 9.0 streambuf */ -#define _Po FLAG(U_OTHER_PUNCTUATION) -#define _Sm FLAG(U_MATH_SYMBOL) -#define _Sc FLAG(U_CURRENCY_SYMBOL) -#define _Sk FLAG(U_MODIFIER_SYMBOL) -#define _So FLAG(U_OTHER_SYMBOL) -#define _Pi FLAG(U_INITIAL_PUNCTUATION) -/* #define _Pf FLAG(U_FINAL_PUNCTUATION) -- conflicts with MS Visual Studio 9.0 streambuf */ - /** Some code points. @internal */ enum { TAB =0x0009, LF =0x000a, FF =0x000c, CR =0x000d, - U_A =0x0041, - U_F =0x0046, - U_Z =0x005a, - U_a =0x0061, - U_f =0x0066, - U_z =0x007a, - DEL =0x007f, - NL =0x0085, NBSP =0x00a0, CGJ =0x034f, FIGURESP=0x2007, @@ -367,15 +324,6 @@ enum { ZWJ =0x200d, RLM =0x200f, NNBSP =0x202f, - WJ =0x2060, - INHSWAP =0x206a, - NOMDIG =0x206f, - U_FW_A =0xff21, - U_FW_F =0xff26, - U_FW_Z =0xff3a, - U_FW_a =0xff41, - U_FW_f =0xff46, - U_FW_z =0xff5a, ZWNBSP =0xfeff }; diff --git a/thirdparty/icu4c/common/uresbund.cpp b/thirdparty/icu4c/common/uresbund.cpp index 2ece87897d..5ea4187100 100644 --- a/thirdparty/icu4c/common/uresbund.cpp +++ b/thirdparty/icu4c/common/uresbund.cpp @@ -92,6 +92,15 @@ static UBool chopLocale(char *name) { } /** + * Called to check whether a name without '_' needs to be checked for a parent. + * Some code had assumed that locale IDs with '_' could not have a non-root parent. + * We may want a better way of doing this. + */ +static UBool mayHaveParent(char *name) { + return (name[0] != 0 && uprv_strstr("nb nn",name) != nullptr); +} + +/** * Internal function */ static void entryIncrease(UResourceDataEntry *entry) { @@ -529,8 +538,8 @@ loadParentsExceptRoot(UResourceDataEntry *&t1, char name[], int32_t nameCapacity, UBool usingUSRData, char usrDataPath[], UErrorCode *status) { if (U_FAILURE(*status)) { return FALSE; } - UBool hasChopped = TRUE; - while (hasChopped && t1->fParent == NULL && !t1->fData.noFallback && + UBool checkParent = TRUE; + while (checkParent && t1->fParent == NULL && !t1->fData.noFallback && res_getResource(&t1->fData,"%%ParentIsRoot") == RES_BOGUS) { Resource parentRes = res_getResource(&t1->fData, "%%Parent"); if (parentRes != RES_BOGUS) { // An explicit parent was found. @@ -573,7 +582,7 @@ loadParentsExceptRoot(UResourceDataEntry *&t1, } } t1 = t2; - hasChopped = chopLocale(name); + checkParent = chopLocale(name) || mayHaveParent(name); } return TRUE; } @@ -692,7 +701,7 @@ static UResourceDataEntry *entryOpen(const char* path, const char* localeID, } } } - if (hasChopped && !isRoot) { + if ((hasChopped || mayHaveParent(name)) && !isRoot) { if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) { goto finish; } @@ -716,7 +725,7 @@ static UResourceDataEntry *entryOpen(const char* path, const char* localeID, hasRealData = TRUE; isDefault = TRUE; // TODO: Why not if (usingUSRData) { ... } like in the non-default-locale code path? - if (hasChopped && !isRoot) { + if ((hasChopped || mayHaveParent(name)) && !isRoot) { if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) { goto finish; } @@ -1908,6 +1917,8 @@ ures_getByKeyWithFallback(const UResourceBundle *resB, } else { break; } + } else if (res == RES_BOGUS) { + break; } } while(*myPath); /* Continue until the whole path is consumed */ } @@ -3019,7 +3030,7 @@ ures_getKeywordValues(const char *path, const char *keyword, UErrorCode *status) U_CAPI UBool U_EXPORT2 ures_equal(const UResourceBundle* res1, const UResourceBundle* res2){ if(res1==NULL || res2==NULL){ - return res1==res2; /* pointer comparision */ + return res1==res2; /* pointer comparison */ } if(res1->fKey==NULL|| res2->fKey==NULL){ return (res1->fKey==res2->fKey); diff --git a/thirdparty/icu4c/common/uresdata.cpp b/thirdparty/icu4c/common/uresdata.cpp index ae731e4544..9af081be40 100644 --- a/thirdparty/icu4c/common/uresdata.cpp +++ b/thirdparty/icu4c/common/uresdata.cpp @@ -960,14 +960,6 @@ res_findResource(const ResourceData *pResData, Resource r, char** path, const ch if(URES_IS_TABLE(type)) { *key = pathP; t2 = res_getTableItemByKey(pResData, t1, &indexR, key); - if(t2 == RES_BOGUS) { - /* if we fail to get the resource by key, maybe we got an index */ - indexR = uprv_strtol(pathP, &closeIndex, 10); - if(indexR >= 0 && *closeIndex == 0 && (*pathP != '0' || closeIndex - pathP == 1)) { - /* if we indeed have an index, try to get the item by index */ - t2 = res_getTableItemByIndex(pResData, t1, indexR, key); - } // else t2 is already RES_BOGUS - } } else if(URES_IS_ARRAY(type)) { indexR = uprv_strtol(pathP, &closeIndex, 10); if(indexR >= 0 && *closeIndex == 0) { diff --git a/thirdparty/icu4c/common/uresimp.h b/thirdparty/icu4c/common/uresimp.h index 69d82566fe..f038dedace 100644 --- a/thirdparty/icu4c/common/uresimp.h +++ b/thirdparty/icu4c/common/uresimp.h @@ -270,11 +270,13 @@ ures_getByKeyWithFallback(const UResourceBundle *resB, * function can perform fallback on the sub-resources of the table. * @param resB a resource * @param inKey a key associated with the requested resource + * @param len if not NULL, used to return the length of the string * @param status: fills in the outgoing error code * could be <TT>U_MISSING_RESOURCE_ERROR</TT> if the key is not found * could be a non-failing error * e.g.: <TT>U_USING_FALLBACK_WARNING</TT>,<TT>U_USING_DEFAULT_WARNING </TT> - * @return a pointer to a UResourceBundle struct. If fill in param was NULL, caller must delete it + * @return returns a pointer to a zero-terminated UChar array which lives in a + * memory mapped/DLL file. */ U_CAPI const UChar* U_EXPORT2 ures_getStringByKeyWithFallback(const UResourceBundle *resB, diff --git a/thirdparty/icu4c/common/uset.cpp b/thirdparty/icu4c/common/uset.cpp index eae7981d52..a7e3046dbf 100644 --- a/thirdparty/icu4c/common/uset.cpp +++ b/thirdparty/icu4c/common/uset.cpp @@ -117,6 +117,12 @@ uset_removeString(USet* set, const UChar* str, int32_t strLen) { } U_CAPI void U_EXPORT2 +uset_removeAllCodePoints(USet *set, const UChar *str, int32_t length) { + UnicodeString s(length==-1, str, length); + ((UnicodeSet*) set)->UnicodeSet::removeAll(s); +} + +U_CAPI void U_EXPORT2 uset_removeAll(USet* set, const USet* remove) { ((UnicodeSet*) set)->UnicodeSet::removeAll(*(const UnicodeSet*)remove); } @@ -127,6 +133,18 @@ uset_retain(USet* set, UChar32 start, UChar32 end) { } U_CAPI void U_EXPORT2 +uset_retainString(USet *set, const UChar *str, int32_t length) { + UnicodeString s(length==-1, str, length); + ((UnicodeSet*) set)->UnicodeSet::retain(s); +} + +U_CAPI void U_EXPORT2 +uset_retainAllCodePoints(USet *set, const UChar *str, int32_t length) { + UnicodeString s(length==-1, str, length); + ((UnicodeSet*) set)->UnicodeSet::retainAll(s); +} + +U_CAPI void U_EXPORT2 uset_retainAll(USet* set, const USet* retain) { ((UnicodeSet*) set)->UnicodeSet::retainAll(*(const UnicodeSet*)retain); } @@ -142,6 +160,23 @@ uset_complement(USet* set) { } U_CAPI void U_EXPORT2 +uset_complementRange(USet *set, UChar32 start, UChar32 end) { + ((UnicodeSet*) set)->UnicodeSet::complement(start, end); +} + +U_CAPI void U_EXPORT2 +uset_complementString(USet *set, const UChar *str, int32_t length) { + UnicodeString s(length==-1, str, length); + ((UnicodeSet*) set)->UnicodeSet::complement(s); +} + +U_CAPI void U_EXPORT2 +uset_complementAllCodePoints(USet *set, const UChar *str, int32_t length) { + UnicodeString s(length==-1, str, length); + ((UnicodeSet*) set)->UnicodeSet::complementAll(s); +} + +U_CAPI void U_EXPORT2 uset_complementAll(USet* set, const USet* complement) { ((UnicodeSet*) set)->UnicodeSet::complementAll(*(const UnicodeSet*)complement); } diff --git a/thirdparty/icu4c/common/usprep.cpp b/thirdparty/icu4c/common/usprep.cpp index 8351a77370..874ffc63a8 100644 --- a/thirdparty/icu4c/common/usprep.cpp +++ b/thirdparty/icu4c/common/usprep.cpp @@ -575,7 +575,7 @@ usprep_map( const UStringPrepProfile* profile, } }else if(type==USPREP_DELETE){ - // just consume the codepoint and contine + // just consume the codepoint and continue continue; } //copy the code point into destination diff --git a/thirdparty/icu4c/common/ustr_wcs.cpp b/thirdparty/icu4c/common/ustr_wcs.cpp index e9f278e969..89d0762480 100644 --- a/thirdparty/icu4c/common/ustr_wcs.cpp +++ b/thirdparty/icu4c/common/ustr_wcs.cpp @@ -364,7 +364,7 @@ _strFromWCS( UChar *dest, } /* we have found a null so convert the - * chunk from begining of non-null char to null + * chunk from beginning of non-null char to null */ retVal = uprv_wcstombs(pCSrc,pSrc,remaining); @@ -387,7 +387,7 @@ _strFromWCS( UChar *dest, * null terminate it and convert wchar_ts to chars */ if(nulLen >= _STACK_BUFFER_CAPACITY){ - /* Should rarely occcur */ + /* Should rarely occur */ /* allocate new buffer buffer */ pWStack =(wchar_t*) uprv_malloc(sizeof(wchar_t) * (nulLen + 1)); if(pWStack==NULL){ diff --git a/thirdparty/icu4c/common/utext.cpp b/thirdparty/icu4c/common/utext.cpp index 763b6684fb..d79f8141bb 100644 --- a/thirdparty/icu4c/common/utext.cpp +++ b/thirdparty/icu4c/common/utext.cpp @@ -382,7 +382,7 @@ utext_previous32From(UText *ut, int64_t index) { // UChar32 cPrev; // The character preceding cCurr, which is what we will return. - // Address the chunk containg the position preceding the incoming index + // Address the chunk containing the position preceding the incoming index // A tricky edge case: // We try to test the requested native index against the chunkNativeStart to determine // whether the character preceding the one at the index is in the current chunk. @@ -894,7 +894,7 @@ struct UTF8Buf { // one for a supplementary starting in the last normal position, // and one for an entry for the buffer limit position. uint8_t mapToUChars[UTF8_TEXT_CHUNK_SIZE*3+6]; // Map native offset from bufNativeStart to - // correspoding offset in filled part of buf. + // corresponding offset in filled part of buf. int32_t align; }; @@ -1545,7 +1545,7 @@ utf8TextMapOffsetToNative(const UText *ut) { } // -// Map a native index to the corrsponding chunk offset +// Map a native index to the corresponding chunk offset // static int32_t U_CALLCONV utf8TextMapIndexToUTF16(const UText *ut, int64_t index64) { diff --git a/thirdparty/icu4c/common/util.h b/thirdparty/icu4c/common/util.h index 9c3b76d9ed..b5fac383a2 100644 --- a/thirdparty/icu4c/common/util.h +++ b/thirdparty/icu4c/common/util.h @@ -13,10 +13,10 @@ #ifndef ICU_UTIL_H #define ICU_UTIL_H -#include "unicode/utypes.h" -#include "unicode/uobject.h" +#include "charstr.h" #include "unicode/unistr.h" - +#include "unicode/uobject.h" +#include "unicode/utypes.h" //-------------------------------------------------------------------- // class ICU_Utility // i18n utility functions, scoped into the class ICU_Utility. diff --git a/thirdparty/icu4c/common/utracimp.h b/thirdparty/icu4c/common/utracimp.h index f32fe1db39..945540d25a 100644 --- a/thirdparty/icu4c/common/utracimp.h +++ b/thirdparty/icu4c/common/utracimp.h @@ -193,7 +193,7 @@ UPRV_BLOCK_MACRO_BEGIN { \ * Trace statement for each exit point of a function that has a UTRACE_ENTRY() * statement, and that returns a value. * - * @param val The function's return value, int32_t or comatible type. + * @param val The function's return value, int32_t or compatible type. * * @internal */ diff --git a/thirdparty/icu4c/common/uvector.cpp b/thirdparty/icu4c/common/uvector.cpp index cf19edf646..9c7e74c6d5 100644 --- a/thirdparty/icu4c/common/uvector.cpp +++ b/thirdparty/icu4c/common/uvector.cpp @@ -312,7 +312,7 @@ int32_t UVector::indexOf(UElement key, int32_t startIndex, int8_t hint) const { } else { for (i=startIndex; i<count; ++i) { /* Pointers are not always the same size as ints so to perform - * a valid comparision we need to know whether we are being + * a valid comparison we need to know whether we are being * provided an int or a pointer. */ if (hint & HINT_KEY_POINTER) { if (key.pointer == elements[i].pointer) { @@ -518,7 +518,7 @@ sortiComparator(const void * /*context */, const void *left, const void *right) } /** - * Sort the vector, assuming it constains ints. + * Sort the vector, assuming it contains ints. * (A more general sort would take a comparison function, but it's * not clear whether UVector's UElementComparator or * UComparator from uprv_sortAray would be more appropriate.) diff --git a/thirdparty/icu4c/common/wintz.cpp b/thirdparty/icu4c/common/wintz.cpp index 580cedadb6..ebf31650c2 100644 --- a/thirdparty/icu4c/common/wintz.cpp +++ b/thirdparty/icu4c/common/wintz.cpp @@ -124,10 +124,26 @@ uprv_detectWindowsTimeZone() // No way to support when DST is turned off and the offset in minutes is not a multiple of 60. if (utcOffsetMins % 60 == 0) { char gmtOffsetTz[11] = {}; // "Etc/GMT+dd" is 11-char long with a terminal null. - // Note '-' before 'utcOffsetMin'. The timezone ID's sign convention - // is that a timezone ahead of UTC is Etc/GMT-<offset> and a timezone - // behind UTC is Etc/GMT+<offset>. - int ret = snprintf(gmtOffsetTz, UPRV_LENGTHOF(gmtOffsetTz), "Etc/GMT%+ld", -utcOffsetMins / 60); + // Important note on the sign convention for zones: + // + // From https://en.wikipedia.org/wiki/Tz_database#Area + // "In order to conform with the POSIX style, those zone names beginning with "Etc/GMT" have their sign reversed + // from the standard ISO 8601 convention. In the "Etc" area, zones west of GMT have a positive sign and those + // east have a negative sign in their name (e.g "Etc/GMT-14" is 14 hours ahead of GMT)." + // + // Regarding the POSIX style, from https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html + // "The offset specifies the time value you must add to the local time to get a Coordinated Universal Time value." + // + // However, the Bias value in DYNAMIC_TIME_ZONE_INFORMATION *already* follows the POSIX convention. + // + // From https://docs.microsoft.com/en-us/windows/win32/api/timezoneapi/ns-timezoneapi-dynamic_time_zone_information + // "The bias is the difference, in minutes, between Coordinated Universal Time (UTC) and + // local time. All translations between UTC and local time are based on the following formula: + // UTC = local time + bias" + // + // For example, a time zone that is 3 hours ahead of UTC (UTC+03:00) would have a Bias value of -180, and the + // corresponding time zone ID would be "Etc/GMT-3". (So there is no need to negate utcOffsetMins below.) + int ret = snprintf(gmtOffsetTz, UPRV_LENGTHOF(gmtOffsetTz), "Etc/GMT%+ld", utcOffsetMins / 60); if (ret > 0 && ret < UPRV_LENGTHOF(gmtOffsetTz)) { return uprv_strdup(gmtOffsetTz); } diff --git a/thirdparty/icu4c/icudt68l.dat b/thirdparty/icu4c/icudt69l.dat Binary files differindex 9ecea5d548..3101a49695 100644 --- a/thirdparty/icu4c/icudt68l.dat +++ b/thirdparty/icu4c/icudt69l.dat |