ICU 76.1 76.1
Loading...
Searching...
No Matches
messageformat2_formattable.h
1// © 2024 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3
4#include "unicode/utypes.h"
5
6#ifndef MESSAGEFORMAT2_FORMATTABLE_H
7#define MESSAGEFORMAT2_FORMATTABLE_H
8
9#if U_SHOW_CPLUSPLUS_API
10
11#if !UCONFIG_NO_FORMATTING
12
13#if !UCONFIG_NO_MF2
14
15#include "unicode/chariter.h"
17#include "unicode/messageformat2_data_model_names.h"
18
19#ifndef U_HIDE_DEPRECATED_API
20
21#include <map>
22#include <variant>
23
24U_NAMESPACE_BEGIN
25
26class Hashtable;
27class UVector;
28
29namespace message2 {
30
31 class Formatter;
32 class MessageContext;
33 class Selector;
34
35 // Formattable
36 // ----------
37
47 public:
57 virtual const UnicodeString& tag() const = 0;
65 }; // class FormattableObject
66
67 class Formattable;
68} // namespace message2
69
71
73// Export an explicit template instantiation of the std::variant that is used
74// to represent the message2::Formattable class.
75// (When building DLLs for Windows this is required.)
76// (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
77// for similar examples.)
78#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
79#if defined(U_REAL_MSVC) && defined(_MSVC_STL_VERSION)
80template class U_I18N_API std::_Variant_storage_<false,
81 double,
82 int64_t,
86 std::pair<const icu::message2::Formattable *,int32_t>>;
87#endif
88typedef std::pair<const icu::message2::Formattable*, int32_t> P;
89template class U_I18N_API std::variant<double,
90 int64_t,
94 P>;
95#endif
97
99
100namespace message2 {
117 public:
118
126
136 double getDouble(UErrorCode& status) const {
137 if (U_SUCCESS(status)) {
138 if (isDecimal() && getType() == UFMT_DOUBLE) {
139 return (std::get_if<icu::Formattable>(&contents))->getDouble();
140 }
141 if (std::holds_alternative<double>(contents)) {
142 return *(std::get_if<double>(&contents));
143 }
145 }
146 return 0;
147 }
148
159 if (U_SUCCESS(status)) {
160 if (isDecimal() && getType() == UFMT_LONG) {
161 return std::get_if<icu::Formattable>(&contents)->getLong();
162 }
163 if (std::holds_alternative<int64_t>(contents)) {
164 return static_cast<int32_t>(*(std::get_if<int64_t>(&contents)));
165 }
167 }
168 return 0;
169 }
170
182 if (U_SUCCESS(status)) {
183 if (isDecimal() && getType() == UFMT_INT64) {
184 return std::get_if<icu::Formattable>(&contents)->getInt64();
185 }
186 if (std::holds_alternative<int64_t>(contents)) {
187 return *(std::get_if<int64_t>(&contents));
188 }
190 }
191 return 0;
192 }
193
219 if (U_SUCCESS(status)) {
220 if (std::holds_alternative<UnicodeString>(contents)) {
221 return *std::get_if<UnicodeString>(&contents);
222 }
224 }
225 return bogusString;
226 }
227
238 if (U_SUCCESS(status)) {
239 if (isDate()) {
240 return *std::get_if<double>(&contents);
241 }
243 }
244 return 0;
245 }
246
254 UBool isNumeric() const { return (getType() == UFMT_DOUBLE || getType() == UFMT_LONG || getType() == UFMT_INT64); }
255
267
279 if (U_SUCCESS(status)) {
280 // Can't return a reference since FormattableObject
281 // is an abstract class
282 if (getType() == UFMT_OBJECT) {
283 return *std::get_if<const FormattableObject*>(&contents);
284 // TODO: should assert that if type is object, object is non-null
285 }
287 }
288 return nullptr;
289 }
298 friend inline void swap(Formattable& f1, Formattable& f2) noexcept {
299 using std::swap;
300
301 swap(f1.contents, f2.contents);
302 swap(f1.holdsDate, f2.holdsDate);
303 }
325 Formattable() : contents(0.0) {}
334 Formattable(const UnicodeString& s) : contents(s) {}
343 Formattable(double d) : contents(d) {}
352 Formattable(int64_t i) : contents(i) {}
362 f.contents = d;
363 f.holdsDate = true;
364 return f;
365 }
380 static Formattable forDecimal(std::string_view number, UErrorCode& status);
390 Formattable(const Formattable* arr, int32_t len) : contents(std::pair(arr, len)) {}
399 Formattable(const FormattableObject* obj) : contents(obj) {}
406 virtual ~Formattable();
419 private:
420
421 std::variant<double,
422 int64_t,
424 icu::Formattable, // represents a Decimal
425 const FormattableObject*,
426 std::pair<const Formattable*, int32_t>> contents;
427 bool holdsDate = false; // otherwise, we get type errors about UDate being a duplicate type
428 UnicodeString bogusString; // :((((
429
430 UBool isDecimal() const {
431 return std::holds_alternative<icu::Formattable>(contents);
432 }
433 UBool isDate() const {
434 return std::holds_alternative<double>(contents) && holdsDate;
435 }
436 }; // class Formattable
437
451#ifndef U_IN_DOXYGEN
452class U_I18N_API ResolvedFunctionOption : public UObject {
453 private:
454
455 /* const */ UnicodeString name;
456 /* const */ Formattable value;
457
458 public:
459 const UnicodeString& getName() const { return name; }
460 const Formattable& getValue() const { return value; }
461 ResolvedFunctionOption(const UnicodeString& n, const Formattable& f) : name(n), value(f) {}
462 ResolvedFunctionOption() {}
463 ResolvedFunctionOption(ResolvedFunctionOption&&);
464 ResolvedFunctionOption& operator=(ResolvedFunctionOption&& other) noexcept {
465 name = std::move(other.name);
466 value = std::move(other.value);
467 return *this;
468 }
469 virtual ~ResolvedFunctionOption();
470}; // class ResolvedFunctionOption
471#endif
472
480using FunctionOptionsMap = std::map<UnicodeString, message2::Formattable>;
481
489 public:
503 FunctionOptionsMap getOptions() const {
504 int32_t len;
505 const ResolvedFunctionOption* resolvedOptions = getResolvedFunctionOptions(len);
506 FunctionOptionsMap result;
507 for (int32_t i = 0; i < len; i++) {
509 result[opt.getName()] = opt.getValue();
510 }
511 return result;
512 }
520 FunctionOptions() { options = nullptr; }
551 private:
553 friend class StandardFunctions;
554
556
557 const ResolvedFunctionOption* getResolvedFunctionOptions(int32_t& len) const;
558 UBool getFunctionOption(const UnicodeString&, Formattable&) const;
559 // Returns empty string if option doesn't exist
560 UnicodeString getStringFunctionOption(const UnicodeString&) const;
561 int32_t optionsCount() const { return functionOptionsLen; }
562
563 // Named options passed to functions
564 // This is not a Hashtable in order to make it possible for code in a public header file
565 // to construct a std::map from it, on-the-fly. Otherwise, it would be impossible to put
566 // that code in the header because it would have to call internal Hashtable methods.
567 ResolvedFunctionOption* options;
568 int32_t functionOptionsLen = 0;
569}; // class FunctionOptions
570
571
572 // TODO doc comments
573 // Encapsulates either a formatted string or formatted number;
574 // more output types could be added in the future.
575
587 public:
606 FormattedValue() : type(kString) {}
615 bool isString() const { return type == kString; }
624 bool isNumber() const { return type == kNumber; }
632 const UnicodeString& getString() const { return stringOutput; }
640 const number::FormattedNumber& getNumber() const { return numberOutput; }
656 FormattedValue(FormattedValue&& other) { *this = std::move(other); }
664 private:
665 enum Type {
666 kString,
667 kNumber
668 };
669 Type type;
670 UnicodeString stringOutput;
671 number::FormattedNumber numberOutput;
672 }; // class FormattedValue
673
687 public:
698 explicit FormattedPlaceholder(const UnicodeString& s) : fallback(s), type(kFallback) {}
711 : fallback(input.fallback), source(input.source),
712 formatted(std::move(output)), previousOptions(FunctionOptions()), type(kEvaluated) {}
726 : fallback(input.fallback), source(input.source),
727 formatted(std::move(output)), previousOptions(std::move(opts)), type(kEvaluated) {}
738 : fallback(fb), source(input), type(kUnevaluated) {}
746 FormattedPlaceholder() : type(kNull) {}
766 bool isFallback() const { return type == kFallback; }
776 bool isNullOperand() const { return type == kNull; }
786 bool isEvaluated() const { return (type == kEvaluated); }
795 bool canFormat() const { return !(isFallback() || isNullOperand()); }
803 const UnicodeString& getFallback() const { return fallback; }
812 const FunctionOptions& options() const { return previousOptions; }
813
820 const FormattedValue& output() const { return formatted; }
853 UErrorCode& status) const;
854
855 private:
856 friend class MessageFormatter;
857
858 enum Type {
859 kFallback, // Represents the result of formatting that encountered an error
860 kNull, // Represents the absence of both an output and an input (not necessarily an error)
861 kUnevaluated, // `source` should be valid, but there's no result yet
862 kEvaluated, // `formatted` exists
863 };
864 UnicodeString fallback;
865 Formattable source;
866 FormattedValue formatted;
867 FunctionOptions previousOptions; // Ignored unless type is kEvaluated
868 Type type;
869 }; // class FormattedPlaceholder
870
882 public:
901 if (U_SUCCESS(status)) {
903 }
904 return -1;
905 }
912 char16_t charAt(int32_t index, UErrorCode& status) const {
913 (void) index;
914 if (U_SUCCESS(status)) {
916 }
917 return 0;
918 }
926 (void) start;
927 (void) end;
928 if (U_SUCCESS(status)) {
930 }
931 return "";
932 }
940 if (U_SUCCESS(status)) {
942 }
943 return {};
944 }
952 if (U_SUCCESS(status)) {
954 }
955 return {};
956 }
964 if (U_SUCCESS(status)) {
966 }
967 return appendable;
968 }
976 (void) cfpos;
977 if (U_SUCCESS(status)) {
979 }
980 return false;
981 }
989 if (U_SUCCESS(status)) {
991 }
992 return nullptr;
993 }
1001 }; // class FormattedMessage
1002
1003} // namespace message2
1004
1006
1007#endif // U_HIDE_DEPRECATED_API
1008
1009#endif /* #if !UCONFIG_NO_MF2 */
1010
1011#endif /* #if !UCONFIG_NO_FORMATTING */
1012
1013#endif /* U_SHOW_CPLUSPLUS_API */
1014
1015#endif // MESSAGEFORMAT2_FORMATTABLE_H
1016
1017// eof
C++ API: Character Iterator.
Base class for objects to which Unicode characters and strings can be appended.
Definition appendable.h:54
Abstract class that defines an API for iteration on text objects.
Definition chariter.h:361
Represents a span of a string containing a given field.
Formattable objects can be passed to the Format class or its subclasses for formatting.
Definition fmtable.h:63
An abstract formatted value: a string with associated field attributes.
"Smart pointer" base class; do not use directly: use LocalPointer etc.
A Locale object represents a specific geographical, political, or cultural region.
Definition locid.h:195
A string-like object that points to a sized piece of memory.
Definition stringpiece.h:61
UObject is the common ICU "boilerplate" class.
Definition uobject.h:223
UnicodeString is a string class that stores Unicode characters directly and provides similar function...
Definition unistr.h:296
FormattableObject is an abstract class that can be implemented in order to define an arbitrary class ...
virtual ~FormattableObject()
Destructor.
virtual const UnicodeString & tag() const =0
Returns an arbitrary string representing the type of this object.
The Formattable class represents a typed value that can be formatted, originating either from a messa...
Formattable(const FormattableObject *obj)
Object constructor.
Formattable(const UnicodeString &s)
String constructor.
Formattable(const Formattable *arr, int32_t len)
Array constructor.
Formattable(int64_t i)
Int64 constructor.
static Formattable forDecimal(std::string_view number, UErrorCode &status)
Creates a Formattable object of an appropriate numeric type from a a decimal number in string form.
const FormattableObject * getObject(UErrorCode &status) const
Returns a pointer to the FormattableObject contained within this formattable, or if this object does ...
double getDouble(UErrorCode &status) const
Gets the double value of this object.
icu::Formattable asICUFormattable(UErrorCode &status) const
Converts the Formattable object to an ICU Formattable object.
virtual ~Formattable()
Destructor.
int64_t getInt64(UErrorCode &status) const
Gets the int64 value of this object.
const UnicodeString & getString(UErrorCode &status) const
Gets the string value of this object.
Formattable & operator=(Formattable) noexcept
Assignment operator.
int32_t getLong(UErrorCode &status) const
Gets the long value of this object.
const Formattable * getArray(int32_t &count, UErrorCode &status) const
Gets the array value and count of this object.
int64_t getInt64Value(UErrorCode &status) const
Gets the int64 value of this object.
UBool isNumeric() const
Returns true if the data type of this Formattable object is kDouble.
static Formattable forDate(UDate d)
Date factory method.
Formattable(double d)
Double constructor.
friend void swap(Formattable &f1, Formattable &f2) noexcept
Non-member swap function.
Formattable(const Formattable &)
Copy constructor.
UFormattableType getType() const
Gets the data type of this Formattable object.
UDate getDate(UErrorCode &status) const
Gets the Date value of this object.
Not yet implemented: The result of a message formatting operation.
UBool nextPosition(ConstrainedFieldPosition &cfpos, UErrorCode &status) const override
Not yet implemented.
StringPiece subSequence(int32_t start, int32_t end, UErrorCode &status) const
Not yet implemented.
int32_t length(UErrorCode &status) const
Not yet implemented.
UnicodeString toTempString(UErrorCode &status) const override
Not yet implemented.
FormattedMessage(UErrorCode &status)
Not yet implemented.
UnicodeString toString(UErrorCode &status) const override
Not yet implemented.
virtual ~FormattedMessage()
Destructor.
CharacterIterator * toCharacterIterator(UErrorCode &status)
Not yet implemented.
char16_t charAt(int32_t index, UErrorCode &status) const
Not yet implemented.
Appendable & appendTo(Appendable &appendable, UErrorCode &status) const override
Not yet implemented.
A FormattablePlaceholder encapsulates an input value (a message2::Formattable) together with an optio...
FormattedPlaceholder(const UnicodeString &s)
Fallback constructor.
const message2::Formattable & asFormattable() const
Returns the source Formattable value for this placeholder.
UnicodeString formatToString(const Locale &locale, UErrorCode &status) const
Formats this as a string, using defaults.
FormattedPlaceholder & operator=(FormattedPlaceholder &&) noexcept
Move assignment operator: The source FormattedPlaceholder will be left in a valid but undefined state...
bool isEvaluated() const
Returns true iff this has formatting output.
bool isNullOperand() const
Returns true iff this is a null placeholder.
const UnicodeString & getFallback() const
Gets the fallback value of this placeholder, to be used in its place if an error occurs while formatt...
FormattedPlaceholder(const FormattedPlaceholder &input, FormattedValue &&output)
Constructor for fully formatted placeholders.
bool isFallback() const
Returns true iff this is a fallback placeholder.
const FunctionOptions & options() const
Returns the options of this placeholder.
FormattedPlaceholder(const Formattable &input, const UnicodeString &fb)
Constructor for unformatted placeholders.
const FormattedValue & output() const
Returns the formatted output of this placeholder.
bool canFormat() const
Returns true iff this represents a valid argument to the formatter.
FormattedPlaceholder(const FormattedPlaceholder &input, FunctionOptions &&opts, FormattedValue &&output)
Constructor for fully formatted placeholders with options.
A FormattedValue represents the result of formatting a message2::Formattable.
FormattedValue & operator=(FormattedValue &&) noexcept
Move assignment operator: The source FormattedValue will be left in a valid but undefined state.
virtual ~FormattedValue()
Destructor.
FormattedValue(number::FormattedNumber &&)
Formatted number constructor.
bool isNumber() const
Returns true iff this is a formatted number.
FormattedValue(const UnicodeString &)
Formatted string constructor.
const number::FormattedNumber & getNumber() const
Gets the number contents of this value.
const UnicodeString & getString() const
Gets the string contents of this value.
bool isString() const
Returns true iff this is a formatted string.
Structure encapsulating named options passed to a custom selector or formatter.
FunctionOptions & operator=(FunctionOptions &&) noexcept
Move assignment operator: The source FunctionOptions will be left in a valid but undefined state.
virtual ~FunctionOptions()
Destructor.
FunctionOptionsMap getOptions() const
Returns a map of all name-value pairs provided as options to this function.
The result of a number formatting operation.
C++ API: All-in-one formatter for localized numbers, currencies, and units.
UFormattableType
Enum designating the type of a UFormattable instance.
@ UFMT_LONG
ufmt_getLong() will return without conversion.
@ UFMT_OBJECT
ufmt_getObject() will return without conversion.
@ UFMT_DOUBLE
ufmt_getDouble() will return without conversion.
@ UFMT_INT64
ufmt_getInt64() will return without conversion.
int8_t UBool
The ICU boolean type, a signed-byte integer.
Definition umachine.h:247
Basic definitions for ICU, for both C and C++ APIs.
UErrorCode
Standard ICU4C error code type, a substitute for exceptions.
Definition utypes.h:430
@ U_ILLEGAL_ARGUMENT_ERROR
Start of codes indicating failure.
Definition utypes.h:467
@ U_UNSUPPORTED_ERROR
Requested operation not supported in current context.
Definition utypes.h:482
#define U_SUCCESS(x)
Does the error code indicate success?
Definition utypes.h:742
#define U_I18N_API
Set to export library symbols from inside the i18n library, and to import them from outside.
Definition utypes.h:316
double UDate
Date and Time data type.
Definition utypes.h:218