1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-10 10:01:13 +09:00

LibLocale: Move definition of Range structure to dedicated header

We were redefining a Range type in a few formatters. Move it to its own
header to avoid ODR violations (and give it a more descriptive name).
This commit is contained in:
Timothy Flynn 2024-06-19 12:46:45 -04:00 committed by Tim Flynn
parent 8a509a8023
commit ad10705615
Notes: sideshowbarker 2024-07-17 06:38:11 +09:00
4 changed files with 56 additions and 60 deletions

View file

@ -15,6 +15,7 @@
#include <LibLocale/ICU.h>
#include <LibLocale/Locale.h>
#include <LibLocale/NumberFormat.h>
#include <LibLocale/PartitionRange.h>
#include <stdlib.h>
#include <unicode/calendar.h>
@ -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<icu::SimpleDateFormat> formatter)
@ -765,8 +756,8 @@ public:
i32 previous_end_index = 0;
Vector<Partition> result;
Optional<Range> start_range;
Optional<Range> end_range;
Optional<PartitionRange> start_range;
Optional<PartitionRange> 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());
}

View file

@ -12,6 +12,7 @@
#include <LibLocale/ICU.h>
#include <LibLocale/Locale.h>
#include <LibLocale/NumberFormat.h>
#include <LibLocale/PartitionRange.h>
#include <math.h>
#include <unicode/numberformatter.h>
@ -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<double>()) {
@ -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<Range>& partitions)
static void flatten_partitions(Vector<PartitionRange>& partitions)
{
if (partitions.size() <= 1)
return;
quick_sort(partitions);
auto subtract_range = [&](auto const& first, auto const& second) -> Vector<Range> {
auto subtract_range = [&](auto const& first, auto const& second) -> Vector<PartitionRange> {
if (second.start > first.end || first.start > second.end)
return { first };
Vector<Range> result;
Vector<PartitionRange> 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<Range> ranges;
ranges.empend(LITERAL_FIELD, 0, formatted_number.length());
Vector<PartitionRange> ranges;
ranges.empend(PartitionRange::LITERAL_FIELD, 0, formatted_number.length());
icu::ConstrainedFieldPosition position;
Optional<Range> start_range;
Optional<Range> end_range;
Optional<PartitionRange> start_range;
Optional<PartitionRange> end_range;
while (static_cast<bool>(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());
}

View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Types.h>
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 };
};
}

View file

@ -9,6 +9,7 @@
#include <LibLocale/ICU.h>
#include <LibLocale/Locale.h>
#include <LibLocale/NumberFormat.h>
#include <LibLocale/PartitionRange.h>
#include <LibLocale/RelativeTimeFormat.h>
#include <unicode/decimfmt.h>
@ -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<icu::RelativeDateTimeFormatter> formatter)
@ -178,7 +169,7 @@ public:
return {};
Vector<Partition> result;
Vector<Range> separators;
Vector<PartitionRange> 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;
}