diff --git a/Userland/Libraries/LibLocale/DateTimeFormat.cpp b/Userland/Libraries/LibLocale/DateTimeFormat.cpp index 8ce4f0d7ba1..f8a3cd77e6d 100644 --- a/Userland/Libraries/LibLocale/DateTimeFormat.cpp +++ b/Userland/Libraries/LibLocale/DateTimeFormat.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -659,16 +660,6 @@ static bool is_formatted_range_actually_a_range(icu::FormattedDateInterval const return has_range; } -struct Range { - constexpr bool contains(i32 position) const - { - return start <= position && position < end; - } - - i32 start { 0 }; - i32 end { 0 }; -}; - class DateTimeFormatImpl : public DateTimeFormat { public: DateTimeFormatImpl(icu::Locale& locale, icu::UnicodeString const& pattern, StringView time_zone_identifier, NonnullOwnPtr formatter) @@ -765,8 +756,8 @@ public: i32 previous_end_index = 0; Vector result; - Optional start_range; - Optional end_range; + Optional start_range; + Optional end_range; auto create_partition = [&](i32 field, i32 begin, i32 end) { Partition partition; @@ -789,7 +780,7 @@ public: if (position.getCategory() == UFIELD_CATEGORY_DATE_INTERVAL_SPAN) { auto& range = position.getField() == 0 ? start_range : end_range; - range = Range { position.getStart(), position.getLimit() }; + range = PartitionRange { position.getField(), position.getStart(), position.getLimit() }; } else if (position.getCategory() == UFIELD_CATEGORY_DATE) { create_partition(position.getField(), position.getStart(), position.getLimit()); } diff --git a/Userland/Libraries/LibLocale/NumberFormat.cpp b/Userland/Libraries/LibLocale/NumberFormat.cpp index 57e14ecf63f..a6098f25435 100644 --- a/Userland/Libraries/LibLocale/NumberFormat.cpp +++ b/Userland/Libraries/LibLocale/NumberFormat.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -491,14 +492,10 @@ static void apply_rounding_options(icu::number::LocalizedNumberFormatter& format formatter = formatter.roundingMode(icu_rounding_mode(rounding_options.mode)); } -// ICU does not contain a field enumeration for "literal" partitions. Define a custom field so that we may provide a -// type for those partitions. -static constexpr i32 LITERAL_FIELD = -1; - static constexpr StringView icu_number_format_field_to_string(i32 field, NumberFormat::Value const& value, bool is_unit) { switch (field) { - case LITERAL_FIELD: + case PartitionRange::LITERAL_FIELD: return "literal"sv; case UNUM_INTEGER_FIELD: if (auto const* number = value.get_pointer()) { @@ -541,26 +538,6 @@ static constexpr StringView icu_number_format_field_to_string(i32 field, NumberF VERIFY_NOT_REACHED(); } -struct Range { - constexpr bool contains(i32 position) const - { - return start <= position && position < end; - } - - constexpr bool operator<(Range const& other) const - { - if (start < other.start) - return true; - if (start == other.start) - return end > other.end; - return false; - } - - i32 field { LITERAL_FIELD }; - i32 start { 0 }; - i32 end { 0 }; -}; - // ICU will give us overlapping partitions, e.g. for the formatted result "1,234", we will get the following parts: // // part="," type=group start=1 end=2 @@ -571,18 +548,18 @@ struct Range { // part="1" type=integer start=0 end=1 // part="," type=group start=1 end=2 // part="234" type=integer start=2 end=5 -static void flatten_partitions(Vector& partitions) +static void flatten_partitions(Vector& partitions) { if (partitions.size() <= 1) return; quick_sort(partitions); - auto subtract_range = [&](auto const& first, auto const& second) -> Vector { + auto subtract_range = [&](auto const& first, auto const& second) -> Vector { if (second.start > first.end || first.start > second.end) return { first }; - Vector result; + Vector result; if (second.start > first.start) result.empend(first.field, first.start, second.start); @@ -827,17 +804,17 @@ private: if (icu_failure(status)) return {}; - Vector ranges; - ranges.empend(LITERAL_FIELD, 0, formatted_number.length()); + Vector ranges; + ranges.empend(PartitionRange::LITERAL_FIELD, 0, formatted_number.length()); icu::ConstrainedFieldPosition position; - Optional start_range; - Optional end_range; + Optional start_range; + Optional end_range; while (static_cast(formatted->nextPosition(position, status)) && icu_success(status)) { if (position.getCategory() == UFIELD_CATEGORY_NUMBER_RANGE_SPAN) { auto& range = position.getField() == 0 ? start_range : end_range; - range = Range { position.getField(), position.getStart(), position.getLimit() }; + range = PartitionRange { position.getField(), position.getStart(), position.getLimit() }; } else { ranges.empend(position.getField(), position.getStart(), position.getLimit()); } diff --git a/Userland/Libraries/LibLocale/PartitionRange.h b/Userland/Libraries/LibLocale/PartitionRange.h new file mode 100644 index 00000000000..a231e0f65a8 --- /dev/null +++ b/Userland/Libraries/LibLocale/PartitionRange.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Locale { + +struct PartitionRange { + // ICU does not contain a field enumeration for "literal" partitions. Define a custom field so that we may provide + // a type for those partitions. + static constexpr i32 LITERAL_FIELD = -1; + + constexpr bool contains(i32 position) const + { + return start <= position && position < end; + } + + constexpr bool operator<(PartitionRange const& other) const + { + if (start < other.start) + return true; + if (start == other.start) + return end > other.end; + return false; + } + + i32 field { LITERAL_FIELD }; + i32 start { 0 }; + i32 end { 0 }; +}; + +} diff --git a/Userland/Libraries/LibLocale/RelativeTimeFormat.cpp b/Userland/Libraries/LibLocale/RelativeTimeFormat.cpp index 9fe0a5eb9e9..549842e11ba 100644 --- a/Userland/Libraries/LibLocale/RelativeTimeFormat.cpp +++ b/Userland/Libraries/LibLocale/RelativeTimeFormat.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -117,14 +118,10 @@ static constexpr UDateRelativeDateTimeFormatterStyle icu_relative_date_time_styl VERIFY_NOT_REACHED(); } -// ICU does not contain a field enumeration for "literal" partitions. Define a custom field so that we may provide a -// type for those partitions. -static constexpr i32 LITERAL_FIELD = -1; - static constexpr StringView icu_relative_time_format_field_to_string(i32 field) { switch (field) { - case LITERAL_FIELD: + case PartitionRange::LITERAL_FIELD: return "literal"sv; case UNUM_INTEGER_FIELD: return "integer"sv; @@ -138,12 +135,6 @@ static constexpr StringView icu_relative_time_format_field_to_string(i32 field) VERIFY_NOT_REACHED(); } -struct Range { - i32 field { 0 }; - i32 start { 0 }; - i32 end { 0 }; -}; - class RelativeTimeFormatImpl : public RelativeTimeFormat { public: explicit RelativeTimeFormatImpl(NonnullOwnPtr formatter) @@ -178,7 +169,7 @@ public: return {}; Vector result; - Vector separators; + Vector separators; auto create_partition = [&](i32 field, i32 begin, i32 end, bool is_unit) { Partition partition; @@ -201,7 +192,7 @@ public: } if (previous_end_index < position.getStart()) - create_partition(LITERAL_FIELD, previous_end_index, position.getStart(), false); + create_partition(PartitionRange::LITERAL_FIELD, previous_end_index, position.getStart(), false); auto start = position.getStart(); @@ -223,7 +214,7 @@ public: } if (previous_end_index < formatted_time.length()) - create_partition(LITERAL_FIELD, previous_end_index, formatted_time.length(), false); + create_partition(PartitionRange::LITERAL_FIELD, previous_end_index, formatted_time.length(), false); return result; }