Skip to content

Commit

Permalink
Bring back FunctionFactory
Browse files Browse the repository at this point in the history
  • Loading branch information
catamorphism committed Oct 7, 2024
1 parent 037b027 commit f82c921
Show file tree
Hide file tree
Showing 9 changed files with 357 additions and 74 deletions.
3 changes: 2 additions & 1 deletion icu4c/source/i18n/messageformat2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,14 @@ FunctionOptions MessageFormatter::resolveOptions(const Environment& env,
}

// Look up the function name
Function* function = lookupFunction(functionName, status);
FunctionFactory* functionFactory = lookupFunctionFactory(functionName, status);
if (U_FAILURE(status)) {
// Function is unknown -- set error and use the fallback value
status = U_ZERO_ERROR;
context.getErrors().setUnknownFunction(functionName, status);
return InternalValue::fallback(fallbackStr);
}
LocalPointer<Function> function(functionFactory->createFunction(locale, status));
// Value is not a fallback, so we can safely call takeValue()
LocalPointer<FunctionValue> functionArg(rand.takeValue(status));
U_ASSERT(U_SUCCESS(status));
Expand Down
36 changes: 21 additions & 15 deletions icu4c/source/i18n/messageformat2_formatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,18 +122,23 @@ namespace message2 {
// Set up the standard function registry
MFFunctionRegistry::Builder standardFunctionsBuilder(success);

Function* dateTime = StandardFunctions::DateTime::dateTime(locale, success);
Function* date = StandardFunctions::DateTime::date(locale, success);
Function* time = StandardFunctions::DateTime::time(locale, success);
standardFunctionsBuilder.adoptFunction(FunctionName(UnicodeString("datetime")), dateTime, success)
.adoptFunction(FunctionName(UnicodeString("date")), date, success)
.adoptFunction(FunctionName(UnicodeString("time")), time, success)
.adoptFunction(FunctionName(UnicodeString("number")),
StandardFunctions::Number::number(locale, success), success)
.adoptFunction(FunctionName(UnicodeString("integer")),
StandardFunctions::Number::integer(locale, success), success)
.adoptFunction(FunctionName(UnicodeString("string")),
StandardFunctions::String::string(locale, success), success);
LocalPointer<FunctionFactory> dateTime(StandardFunctions::DateTimeFactory::dateTime(success));
LocalPointer<FunctionFactory> date(StandardFunctions::DateTimeFactory::date(success));
LocalPointer<FunctionFactory> time(StandardFunctions::DateTimeFactory::time(success));
LocalPointer<FunctionFactory> number(StandardFunctions::NumberFactory::number(success));
LocalPointer<FunctionFactory> integer(StandardFunctions::NumberFactory::integer(success));
LocalPointer<FunctionFactory> string(StandardFunctions::StringFactory::string(success));
CHECK_ERROR(success);
standardFunctionsBuilder.adoptFunctionFactory(FunctionName(UnicodeString("datetime")),
dateTime.orphan(), success)
.adoptFunctionFactory(FunctionName(UnicodeString("date")), date.orphan(), success)
.adoptFunctionFactory(FunctionName(UnicodeString("time")), time.orphan(), success)
.adoptFunctionFactory(FunctionName(UnicodeString("number")),
number.orphan(), success)
.adoptFunctionFactory(FunctionName(UnicodeString("integer")),
integer.orphan(), success)
.adoptFunctionFactory(FunctionName(UnicodeString("string")),
string.orphan(), success);
CHECK_ERROR(success);
standardMFFunctionRegistry = standardFunctionsBuilder.build();
CHECK_ERROR(success);
Expand Down Expand Up @@ -220,16 +225,17 @@ namespace message2 {
return standardMFFunctionRegistry.hasFunction(functionName);
}

Function* MessageFormatter::lookupFunction(const FunctionName& functionName,
UErrorCode& status) const {
FunctionFactory*
MessageFormatter::lookupFunctionFactory(const FunctionName& functionName,
UErrorCode& status) const {
NULL_ON_ERROR(status);

if (isBuiltInFunction(functionName)) {
return standardMFFunctionRegistry.getFunction(functionName);
}
if (hasCustomMFFunctionRegistry()) {
const MFFunctionRegistry& customMFFunctionRegistry = getCustomMFFunctionRegistry();
Function* function = customMFFunctionRegistry.getFunction(functionName);
FunctionFactory* function = customMFFunctionRegistry.getFunction(functionName);
if (function != nullptr) {
return function;
}
Expand Down
147 changes: 121 additions & 26 deletions icu4c/source/i18n/messageformat2_function_registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace message2 {

// Function registry implementation

FunctionFactory::~FunctionFactory() {}
Function::~Function() {}
FunctionValue::~FunctionValue() {}

Expand All @@ -50,9 +51,10 @@ MFFunctionRegistry MFFunctionRegistry::Builder::build() {
return result;
}

MFFunctionRegistry::Builder& MFFunctionRegistry::Builder::adoptFunction(const FunctionName& functionName,
Function* function,
UErrorCode& errorCode) {
MFFunctionRegistry::Builder&
MFFunctionRegistry::Builder::adoptFunctionFactory(const FunctionName& functionName,
FunctionFactory* function,
UErrorCode& errorCode) {
if (U_SUCCESS(errorCode)) {
U_ASSERT(functions != nullptr);
functions->put(functionName, function, errorCode);
Expand Down Expand Up @@ -98,9 +100,9 @@ MFFunctionRegistry::Builder::~Builder() {

// Returns non-owned pointer. Returns pointer rather than reference because it can fail.
// Returns non-const because Function is mutable.
Function* MFFunctionRegistry::getFunction(const FunctionName& functionName) const {
FunctionFactory* MFFunctionRegistry::getFunction(const FunctionName& functionName) const {
U_ASSERT(functions != nullptr);
return static_cast<Function*>(functions->get(functionName));
return static_cast<FunctionFactory*>(functions->get(functionName));
}

UBool MFFunctionRegistry::getDefaultFormatterNameByType(const UnicodeString& type, FunctionName& name) const {
Expand Down Expand Up @@ -225,6 +227,40 @@ MFFunctionRegistry::~MFFunctionRegistry() {

// --------- Number

/* static */ StandardFunctions::NumberFactory*
StandardFunctions::NumberFactory::integer(UErrorCode& success) {
return NumberFactory::create(true, success);
}

/* static */ StandardFunctions::NumberFactory*
StandardFunctions::NumberFactory::number(UErrorCode& success) {
return NumberFactory::create(false, success);
}

/* static */ StandardFunctions::NumberFactory*
StandardFunctions::NumberFactory::create(bool isInteger,
UErrorCode& success) {
NULL_ON_ERROR(success);

LocalPointer<NumberFactory> result(new NumberFactory(isInteger));
if (!result.isValid()) {
success = U_MEMORY_ALLOCATION_ERROR;
return nullptr;
}
return result.orphan();
}

Function*
StandardFunctions::NumberFactory::createFunction(const Locale& locale, UErrorCode& errorCode) {
NULL_ON_ERROR(errorCode);

Number* result = new Number(locale, isInteger);
if (result == nullptr) {
errorCode = U_MEMORY_ALLOCATION_ERROR;
}
return result;
}

/* static */ StandardFunctions::Number*
StandardFunctions::Number::integer(const Locale& loc, UErrorCode& success) {
return create(loc, true, success);
Expand Down Expand Up @@ -582,6 +618,7 @@ UnicodeString StandardFunctions::NumberValue::formatToString(UErrorCode& errorCo
return formattedNumber.toString(errorCode);
}

StandardFunctions::NumberFactory::~NumberFactory() {}
StandardFunctions::Number::~Number() {}
StandardFunctions::NumberValue::~NumberValue() {}

Expand Down Expand Up @@ -699,23 +736,49 @@ static UnicodeString defaultForOption(const UnicodeString& optionName) {
}
*/

/* static */ StandardFunctions::DateTime*
StandardFunctions::DateTime::date(const Locale& loc, UErrorCode& success) {
return DateTime::create(loc, DateTimeType::kDate, success);
/* static */ StandardFunctions::DateTimeFactory*
StandardFunctions::DateTimeFactory::date(UErrorCode& success) {
return DateTimeFactory::create(DateTimeType::kDate, success);
}

/* static */ StandardFunctions::DateTime*
StandardFunctions::DateTime::time(const Locale& loc, UErrorCode& success) {
return DateTime::create(loc, DateTimeType::kTime, success);
/* static */ StandardFunctions::DateTimeFactory*
StandardFunctions::DateTimeFactory::time(UErrorCode& success) {
return DateTimeFactory::create(DateTimeType::kTime, success);
}

/* static */ StandardFunctions::DateTime*
StandardFunctions::DateTime::dateTime(const Locale& loc, UErrorCode& success) {
return DateTime::create(loc, DateTimeType::kDateTime, success);
/* static */ StandardFunctions::DateTimeFactory*
StandardFunctions::DateTimeFactory::dateTime(UErrorCode& success) {
return DateTimeFactory::create(DateTimeType::kDateTime, success);
}

/* static */ StandardFunctions::DateTimeFactory*
StandardFunctions::DateTimeFactory::create(DateTimeFactory::DateTimeType type,
UErrorCode& success) {
NULL_ON_ERROR(success);

LocalPointer<DateTimeFactory> result(new DateTimeFactory(type));
if (!result.isValid()) {
success = U_MEMORY_ALLOCATION_ERROR;
return nullptr;
}
return result.orphan();
}

Function*
StandardFunctions::DateTimeFactory::createFunction(const Locale& locale, UErrorCode& errorCode) {
NULL_ON_ERROR(errorCode);

DateTime* result = new DateTime(locale, type);
if (result == nullptr) {
errorCode = U_MEMORY_ALLOCATION_ERROR;
}
return result;
}

/* static */ StandardFunctions::DateTime*
StandardFunctions::DateTime::create(const Locale& loc, DateTimeType type, UErrorCode& success) {
StandardFunctions::DateTime::create(const Locale& loc,
DateTimeFactory::DateTimeType type,
UErrorCode& success) {
NULL_ON_ERROR(success);

LocalPointer<DateTime> result(new DateTime(loc, type));
Expand All @@ -728,7 +791,12 @@ StandardFunctions::DateTime::create(const Locale& loc, DateTimeType type, UError

FunctionValue*
StandardFunctions::DateTime::call(FunctionValue& val, FunctionOptions&& opts, UErrorCode& errorCode) {
auto result = new DateTimeValue(type, locale, val, std::move(opts), errorCode);
NULL_ON_ERROR(errorCode);

auto result = new DateTimeValue(locale, type, val, std::move(opts), errorCode);
if (result == nullptr) {
errorCode = U_MEMORY_ALLOCATION_ERROR;
}
return result;
}

Expand Down Expand Up @@ -761,8 +829,8 @@ UnicodeString StandardFunctions::DateTimeValue::formatToString(UErrorCode& statu
return formattedDate;
}

StandardFunctions::DateTimeValue::DateTimeValue(DateTime::DateTimeType type,
const Locale& locale,
StandardFunctions::DateTimeValue::DateTimeValue(const Locale& locale,
DateTimeFactory::DateTimeType type,
FunctionValue& val,
FunctionOptions&& options,
UErrorCode& errorCode) {
Expand Down Expand Up @@ -795,21 +863,23 @@ StandardFunctions::DateTimeValue::DateTimeValue(DateTime::DateTimeType type,
bool hasTimeStyleOption = dateStyleOption.length() > 0;
bool noOptions = opts.optionsCount() == 0;

bool useStyle = (type == DateTime::DateTimeType::kDateTime
using DateTimeType = DateTimeFactory::DateTimeType;

bool useStyle = (type == DateTimeType::kDateTime
&& (hasDateStyleOption || hasTimeStyleOption
|| noOptions))
|| (type != DateTime::DateTimeType::kDateTime);
|| (type != DateTimeType::kDateTime);

bool useDate = type == DateTime::DateTimeType::kDate
|| (type == DateTime::DateTimeType::kDateTime
bool useDate = type == DateTimeType::kDate
|| (type == DateTimeType::kDateTime
&& hasDateStyleOption);
bool useTime = type == DateTime::DateTimeType::kTime
|| (type == DateTime::DateTimeType::kDateTime
bool useTime = type == DateTimeType::kTime
|| (type == DateTimeType::kDateTime
&& hasTimeStyleOption);

if (useStyle) {
// Extract style options
if (type == DateTime::DateTimeType::kDateTime) {
if (type == DateTimeType::kDateTime) {
// Note that the options-getting has to be repeated across the three cases,
// since `:datetime` uses "dateStyle"/"timeStyle" and `:date` and `:time`
// use "style"
Expand All @@ -823,7 +893,7 @@ StandardFunctions::DateTimeValue::DateTimeValue(DateTime::DateTimeType type,
} else {
df.adoptInstead(DateFormat::createDateTimeInstance(dateStyle, timeStyle, locale));
}
} else if (type == DateTime::DateTimeType::kDate) {
} else if (type == DateTimeType::kDate) {
dateStyle = stringToStyle(opts.getStringFunctionOption(styleName), errorCode);
df.adoptInstead(DateFormat::createDateInstance(dateStyle, locale));
} else {
Expand Down Expand Up @@ -1010,11 +1080,24 @@ StandardFunctions::DateTimeValue::DateTimeValue(DateTime::DateTimeType type,
formattedDate = result;
}

StandardFunctions::DateTimeFactory::~DateTimeFactory() {}
StandardFunctions::DateTime::~DateTime() {}
StandardFunctions::DateTimeValue::~DateTimeValue() {}

// --------- String

/* static */ StandardFunctions::StringFactory*
StandardFunctions::StringFactory::string(UErrorCode& success) {
NULL_ON_ERROR(success);

LocalPointer<StringFactory> result(new StringFactory());
if (!result.isValid()) {
success = U_MEMORY_ALLOCATION_ERROR;
return nullptr;
}
return result.orphan();
}

/* static */ StandardFunctions::String*
StandardFunctions::String::string(const Locale& loc, UErrorCode& success) {
NULL_ON_ERROR(success);
Expand All @@ -1027,6 +1110,17 @@ StandardFunctions::String::string(const Locale& loc, UErrorCode& success) {
return result.orphan();
}

Function*
StandardFunctions::StringFactory::createFunction(const Locale& locale, UErrorCode& errorCode) {
NULL_ON_ERROR(errorCode);

String* result = new String(locale);
if (result == nullptr) {
errorCode = U_MEMORY_ALLOCATION_ERROR;
}
return result;
}

extern UnicodeString formattableToString(const Locale&, const Formattable&, UErrorCode&);

FunctionValue*
Expand Down Expand Up @@ -1075,6 +1169,7 @@ void StandardFunctions::StringValue::selectKeys(const UnicodeString* keys,
}
}

StandardFunctions::StringFactory::~StringFactory() {}
StandardFunctions::String::~String() {}
StandardFunctions::StringValue::~StringValue() {}

Expand Down
Loading

0 comments on commit f82c921

Please sign in to comment.