зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1737814 - Part 1: Add a AutoFormatResult class. r=platform-i18n-reviewers,anba,gregtatum
This AutoFormatResult class could be shared later by ListFormat. Differential Revision: https://phabricator.services.mozilla.com/D129561
This commit is contained in:
Родитель
cf3a438f13
Коммит
24dcdf0726
|
@ -2,8 +2,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "unicode/udateintervalformat.h"
|
||||
|
||||
#include "DateTimeFormatUtils.h"
|
||||
#include "ScopedICUObject.h"
|
||||
|
||||
|
@ -72,63 +70,15 @@ DateIntervalFormat::~DateIntervalFormat() {
|
|||
udtitvfmt_close(mDateIntervalFormat.GetMut());
|
||||
}
|
||||
|
||||
AutoFormattedDateInterval::AutoFormattedDateInterval() {
|
||||
mFormatted = udtitvfmt_openResult(&mError);
|
||||
if (U_FAILURE(mError)) {
|
||||
mFormatted = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const UFormattedValue* AutoFormattedDateInterval::Value() const {
|
||||
if (!IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
const UFormattedValue* value = udtitvfmt_resultAsValue(mFormatted, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
Result<Span<const char16_t>, ICUError> AutoFormattedDateInterval::ToSpan()
|
||||
const {
|
||||
if (!IsValid()) {
|
||||
return Err(GetError());
|
||||
}
|
||||
|
||||
const UFormattedValue* value = Value();
|
||||
if (!value) {
|
||||
return Err(ICUError::InternalError);
|
||||
}
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t strLength;
|
||||
const char16_t* str = ufmtval_getString(value, &strLength, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
return Err(ToICUError(status));
|
||||
}
|
||||
|
||||
return Span{str, AssertedCast<size_t>(strLength)};
|
||||
}
|
||||
|
||||
AutoFormattedDateInterval::~AutoFormattedDateInterval() {
|
||||
if (mFormatted) {
|
||||
udtitvfmt_closeResult(mFormatted);
|
||||
}
|
||||
}
|
||||
|
||||
ICUResult DateIntervalFormat::TryFormatCalendar(
|
||||
const Calendar& aStart, const Calendar& aEnd,
|
||||
AutoFormattedDateInterval& aFormatted, bool* aPracticallyEqual) const {
|
||||
MOZ_ASSERT(aFormatted.IsValid());
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
udtitvfmt_formatCalendarToResult(
|
||||
mDateIntervalFormat.GetConst(), aStart.GetUCalendar(),
|
||||
aEnd.GetUCalendar(), aFormatted.GetUFormattedDateInterval(), &status);
|
||||
udtitvfmt_formatCalendarToResult(mDateIntervalFormat.GetConst(),
|
||||
aStart.GetUCalendar(), aEnd.GetUCalendar(),
|
||||
aFormatted.GetFormatted(), &status);
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
return Err(ToICUError(status));
|
||||
|
@ -145,7 +95,7 @@ ICUResult DateIntervalFormat::TryFormatDateTime(
|
|||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
udtitvfmt_formatToResult(mDateIntervalFormat.GetConst(), aStart, aEnd,
|
||||
aFormatted.GetUFormattedDateInterval(), &status);
|
||||
aFormatted.GetFormatted(), &status);
|
||||
if (U_FAILURE(status)) {
|
||||
return Err(ToICUError(status));
|
||||
}
|
||||
|
|
|
@ -11,16 +11,16 @@
|
|||
#include "mozilla/Span.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#include "unicode/udateintervalformat.h"
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
struct UDateIntervalFormat;
|
||||
struct UFormattedDateInterval;
|
||||
struct UFormattedValue;
|
||||
|
||||
namespace mozilla::intl {
|
||||
class AutoFormattedDateInterval;
|
||||
class Calendar;
|
||||
|
||||
using AutoFormattedDateInterval =
|
||||
AutoFormattedResult<UFormattedDateInterval, udtitvfmt_openResult,
|
||||
udtitvfmt_resultAsValue, udtitvfmt_closeResult>;
|
||||
|
||||
/**
|
||||
* This component is a Mozilla-focused API for the date range formatting
|
||||
* provided by ICU. This DateIntervalFormat class helps to format the range
|
||||
|
@ -101,59 +101,6 @@ class DateIntervalFormat final {
|
|||
ICUPointer<UDateIntervalFormat> mDateIntervalFormat =
|
||||
ICUPointer<UDateIntervalFormat>(nullptr);
|
||||
};
|
||||
|
||||
/**
|
||||
* A RAII class to hold the formatted value of DateIntervalFormat.
|
||||
*
|
||||
* The caller will need to create this AutoFormattedDateInterval on the stack,
|
||||
* and call IsValid() method to check if the native object
|
||||
* (UFormattedDateInterval) has been created properly, and then passes this
|
||||
* object to the methods of DateIntervalFormat.
|
||||
* The result of the DateIntervalFormat's method will be stored in this object,
|
||||
* the caller can use ToSpan() method to get the formatted string, or pass it
|
||||
* to DateIntervalFormat::TryFormattedToParts to get the DateTimePart vector.
|
||||
*
|
||||
* The formatted value will be released once this class is destructed.
|
||||
*/
|
||||
class MOZ_RAII AutoFormattedDateInterval {
|
||||
public:
|
||||
AutoFormattedDateInterval();
|
||||
~AutoFormattedDateInterval();
|
||||
|
||||
AutoFormattedDateInterval(const AutoFormattedDateInterval& other) = delete;
|
||||
AutoFormattedDateInterval& operator=(const AutoFormattedDateInterval& other) =
|
||||
delete;
|
||||
|
||||
AutoFormattedDateInterval(AutoFormattedDateInterval&& other) = delete;
|
||||
AutoFormattedDateInterval& operator=(AutoFormattedDateInterval&& other) =
|
||||
delete;
|
||||
|
||||
/**
|
||||
* Check if the native UFormattedDateInterval was created successfully.
|
||||
*/
|
||||
bool IsValid() const { return !!mFormatted; }
|
||||
|
||||
/**
|
||||
* Get error code if IsValid() returns false.
|
||||
*/
|
||||
ICUError GetError() const { return ToICUError(mError); }
|
||||
|
||||
/**
|
||||
* Get the formatted result.
|
||||
*/
|
||||
Result<Span<const char16_t>, ICUError> ToSpan() const;
|
||||
|
||||
private:
|
||||
friend class DateIntervalFormat;
|
||||
UFormattedDateInterval* GetUFormattedDateInterval() const {
|
||||
return mFormatted;
|
||||
}
|
||||
|
||||
const UFormattedValue* Value() const;
|
||||
|
||||
UFormattedDateInterval* mFormatted = nullptr;
|
||||
UErrorCode mError = U_ZERO_ERROR;
|
||||
};
|
||||
} // namespace mozilla::intl
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/intl/ICU4CGlue.h"
|
||||
#include "unicode/uformattedvalue.h"
|
||||
|
||||
namespace mozilla::intl {
|
||||
|
||||
|
@ -21,4 +22,17 @@ ICUResult ToICUResult(UErrorCode status) {
|
|||
return Err(ToICUError(status));
|
||||
}
|
||||
|
||||
// static
|
||||
Result<Span<const char16_t>, ICUError> FormattedResult::ToSpanImpl(
|
||||
const UFormattedValue* value) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t strLength;
|
||||
const char16_t* str = ufmtval_getString(value, &strLength, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
return Err(ToICUError(status));
|
||||
}
|
||||
|
||||
return Span{str, AssertedCast<size_t>(strLength)};
|
||||
}
|
||||
|
||||
} // namespace mozilla::intl
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <stdint.h>
|
||||
#include <string_view>
|
||||
|
||||
struct UFormattedValue;
|
||||
namespace mozilla::intl {
|
||||
|
||||
static inline const char* IcuLocale(const char* aLocale) {
|
||||
|
@ -544,6 +545,109 @@ class AvailableLocalesEnumeration final {
|
|||
Iterator end() const { return Iterator(mLocalesCount); }
|
||||
};
|
||||
|
||||
/**
|
||||
* A helper class to wrap calling ICU function in cpp file so we don't have to
|
||||
* include the ICU header here.
|
||||
*/
|
||||
class FormattedResult {
|
||||
protected:
|
||||
static Result<Span<const char16_t>, ICUError> ToSpanImpl(
|
||||
const UFormattedValue* value);
|
||||
};
|
||||
|
||||
/**
|
||||
* A RAII class to hold the formatted value of format result.
|
||||
*
|
||||
* The caller will need to create this AutoFormattedResult on the stack, with
|
||||
* the following parameters:
|
||||
* 1. Native ICU type.
|
||||
* 2. An ICU function which opens the result.
|
||||
* 3. An ICU function which can get the result as UFormattedValue.
|
||||
* 4. An ICU function which closes the result.
|
||||
*
|
||||
* After the object is created, caller needs to call IsValid() method to check
|
||||
* if the native object has been created properly, and then passes this
|
||||
* object to other format interfaces.
|
||||
* The format result will be stored in this object, the caller can use ToSpan()
|
||||
* method to get the formatted string.
|
||||
*
|
||||
* The methods GetFormatted() and Value() are private methods since they expose
|
||||
* native ICU types. If the caller wants to call these methods, the caller needs
|
||||
* to register itself as a friend class in AutoFormattedResult.
|
||||
*
|
||||
* The formatted value and the native ICU object will be released once this
|
||||
* class is destructed.
|
||||
*/
|
||||
template <typename T, T*(Open)(UErrorCode*),
|
||||
const UFormattedValue*(GetValue)(const T*, UErrorCode*),
|
||||
void(Close)(T*)>
|
||||
class MOZ_RAII AutoFormattedResult : FormattedResult {
|
||||
public:
|
||||
AutoFormattedResult() {
|
||||
mFormatted = Open(&mError);
|
||||
if (U_FAILURE(mError)) {
|
||||
mFormatted = nullptr;
|
||||
}
|
||||
}
|
||||
~AutoFormattedResult() {
|
||||
if (mFormatted) {
|
||||
Close(mFormatted);
|
||||
}
|
||||
}
|
||||
|
||||
AutoFormattedResult(const AutoFormattedResult& other) = delete;
|
||||
AutoFormattedResult& operator=(const AutoFormattedResult& other) = delete;
|
||||
|
||||
AutoFormattedResult(AutoFormattedResult&& other) = delete;
|
||||
AutoFormattedResult& operator=(AutoFormattedResult&& other) = delete;
|
||||
|
||||
/**
|
||||
* Check if the native UFormattedDateInterval was created successfully.
|
||||
*/
|
||||
bool IsValid() const { return !!mFormatted; }
|
||||
|
||||
/**
|
||||
* Get error code if IsValid() returns false.
|
||||
*/
|
||||
ICUError GetError() const { return ToICUError(mError); }
|
||||
|
||||
/**
|
||||
* Get the formatted result.
|
||||
*/
|
||||
Result<Span<const char16_t>, ICUError> ToSpan() const {
|
||||
if (!IsValid()) {
|
||||
return Err(GetError());
|
||||
}
|
||||
|
||||
const UFormattedValue* value = Value();
|
||||
if (!value) {
|
||||
return Err(ICUError::InternalError);
|
||||
}
|
||||
|
||||
return ToSpanImpl(value);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class DateIntervalFormat;
|
||||
T* GetFormatted() const { return mFormatted; }
|
||||
|
||||
const UFormattedValue* Value() const {
|
||||
if (!IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
const UFormattedValue* value = GetValue(mFormatted, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
T* mFormatted = nullptr;
|
||||
UErrorCode mError = U_ZERO_ERROR;
|
||||
};
|
||||
} // namespace mozilla::intl
|
||||
|
||||
#endif /* intl_components_ICUUtils_h */
|
||||
|
|
Загрузка…
Ссылка в новой задаче