ICU 77.1 77.1
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_NORMALIZATION
12
13#if !UCONFIG_NO_FORMATTING
14
15#if !UCONFIG_NO_MF2
16
17#include "unicode/chariter.h"
19#include "unicode/messageformat2_data_model_names.h"
20
21#ifndef U_HIDE_DEPRECATED_API
22
23#include <map>
24#include <variant>
25
26U_NAMESPACE_BEGIN
27
28class Hashtable;
29class UVector;
30
31namespace message2 {
32
33 class Formatter;
34 class MessageContext;
35 class Selector;
36
37 // Formattable
38 // ----------
39
49 public:
59 virtual const UnicodeString& tag() const = 0;
67 }; // class FormattableObject
68
69 class Formattable;
70} // namespace message2
71
72U_NAMESPACE_END
73
75// Export an explicit template instantiation of the std::variant that is used
76// to represent the message2::Formattable class.
77// (When building DLLs for Windows this is required.)
78// (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
79// for similar examples.)
80#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
81#if defined(U_REAL_MSVC) && defined(_MSVC_STL_VERSION)
82template class U_I18N_API std::_Variant_storage_<false,
83 double,
84 int64_t,
88 std::pair<const icu::message2::Formattable *,int32_t>>;
89#endif
90typedef std::pair<const icu::message2::Formattable*, int32_t> P;
91template class U_I18N_API std::variant<double,
92 int64_t,
96 P>;
97#endif
99
100U_NAMESPACE_BEGIN
101
102namespace message2 {
119 public:
120
128
138 double getDouble(UErrorCode& status) const {
139 if (U_SUCCESS(status)) {
140 if (isDecimal() && getType() == UFMT_DOUBLE) {
141 return (std::get_if<icu::Formattable>(&contents))->getDouble();
142 }
143 if (std::holds_alternative<double>(contents)) {
144 return *(std::get_if<double>(&contents));
145 }
147 }
148 return 0;
149 }
150
160 int32_t getLong(UErrorCode& status) const {
161 if (U_SUCCESS(status)) {
162 if (isDecimal() && getType() == UFMT_LONG) {
163 return std::get_if<icu::Formattable>(&contents)->getLong();
164 }
165 if (std::holds_alternative<int64_t>(contents)) {
166 return static_cast<int32_t>(*(std::get_if<int64_t>(&contents)));
167 }
169 }
170 return 0;
171 }
172
183 int64_t getInt64Value(UErrorCode& status) const {
184 if (U_SUCCESS(status)) {
185 if (isDecimal() && getType() == UFMT_INT64) {
186 return std::get_if<icu::Formattable>(&contents)->getInt64();
187 }
188 if (std::holds_alternative<int64_t>(contents)) {
189 return *(std::get_if<int64_t>(&contents));
190 }
192 }
193 return 0;
194 }
195
210 int64_t getInt64(UErrorCode& status) const;
220 const UnicodeString& getString(UErrorCode& status) const {
221 if (U_SUCCESS(status)) {
222 if (std::holds_alternative<UnicodeString>(contents)) {
223 return *std::get_if<UnicodeString>(&contents);
224 }
226 }
227 return bogusString;
228 }
229
239 UDate getDate(UErrorCode& status) const {
240 if (U_SUCCESS(status)) {
241 if (isDate()) {
242 return *std::get_if<double>(&contents);
243 }
245 }
246 return 0;
247 }
248
256 UBool isNumeric() const { return (getType() == UFMT_DOUBLE || getType() == UFMT_LONG || getType() == UFMT_INT64); }
257
268 const Formattable* getArray(int32_t& count, UErrorCode& status) const;
269
280 const FormattableObject* getObject(UErrorCode& status) const {
281 if (U_SUCCESS(status)) {
282 // Can't return a reference since FormattableObject
283 // is an abstract class
284 if (getType() == UFMT_OBJECT) {
285 return *std::get_if<const FormattableObject*>(&contents);
286 // TODO: should assert that if type is object, object is non-null
287 }
289 }
290 return nullptr;
291 }
292
300 friend inline void swap(Formattable& f1, Formattable& f2) noexcept {
301 using std::swap;
302
303 swap(f1.contents, f2.contents);
304 swap(f1.holdsDate, f2.holdsDate);
305 }
306
327 Formattable() : contents(0.0) {}
336 Formattable(const UnicodeString& s) : contents(s) {}
345 Formattable(double d) : contents(d) {}
354 Formattable(int64_t i) : contents(i) {}
363 Formattable f;
364 f.contents = d;
365 f.holdsDate = true;
366 return f;
367 }
368
382 static Formattable forDecimal(std::string_view number, UErrorCode& status);
392 Formattable(const Formattable* arr, int32_t len) : contents(std::pair(arr, len)) {}
401 Formattable(const FormattableObject* obj) : contents(obj) {}
408 virtual ~Formattable();
421 private:
422
423 std::variant<double,
424 int64_t,
426 icu::Formattable, // represents a Decimal
427 const FormattableObject*,
428 std::pair<const Formattable*, int32_t>> contents;
429 bool holdsDate = false; // otherwise, we get type errors about UDate being a duplicate type
430 UnicodeString bogusString; // :((((
431
432 UBool isDecimal() const {
433 return std::holds_alternative<icu::Formattable>(contents);
434 }
435 UBool isDate() const {
436 return std::holds_alternative<double>(contents) && holdsDate;
437 }
438 }; // class Formattable
439
453#ifndef U_IN_DOXYGEN
454class U_I18N_API ResolvedFunctionOption : public UObject {
455 private:
456
457 /* const */ UnicodeString name;
458 /* const */ Formattable value;
459
460 public:
461 const UnicodeString& getName() const { return name; }
462 const Formattable& getValue() const { return value; }
463 ResolvedFunctionOption(const UnicodeString& n, const Formattable& f) : name(n), value(f) {}
464 ResolvedFunctionOption() {}
465 ResolvedFunctionOption(ResolvedFunctionOption&&);
466 ResolvedFunctionOption& operator=(ResolvedFunctionOption&& other) noexcept {
467 name = std::move(other.name);
468 value = std::move(other.value);
469 return *this;
470 }
471 virtual ~ResolvedFunctionOption();
472}; // class ResolvedFunctionOption
473#endif
474
482using FunctionOptionsMap = std::map<UnicodeString, message2::Formattable>;
483
491 public:
505 FunctionOptionsMap getOptions() const {
506 int32_t len;
507 const ResolvedFunctionOption* resolvedOptions = getResolvedFunctionOptions(len);
508 FunctionOptionsMap result;
509 for (int32_t i = 0; i < len; i++) {
510 const ResolvedFunctionOption& opt = resolvedOptions[i];
511 result[opt.getName()] = opt.getValue();
512 }
513 return result;
514 }
515
522 FunctionOptions() { options = nullptr; }
552 FunctionOptions& operator=(const FunctionOptions&) = delete;
553 private:
554 friend class InternalValue;
555 friend class MessageFormatter;
556 friend class StandardFunctions;
557
558 explicit FunctionOptions(UVector&&, UErrorCode&);
559
560 const ResolvedFunctionOption* getResolvedFunctionOptions(int32_t& len) const;
561 UBool getFunctionOption(const UnicodeString&, Formattable&) const;
562 // Returns empty string if option doesn't exist
563 UnicodeString getStringFunctionOption(const UnicodeString&) const;
564 int32_t optionsCount() const { return functionOptionsLen; }
565
566 // Named options passed to functions
567 // This is not a Hashtable in order to make it possible for code in a public header file
568 // to construct a std::map from it, on-the-fly. Otherwise, it would be impossible to put
569 // that code in the header because it would have to call internal Hashtable methods.
570 ResolvedFunctionOption* options;
571 int32_t functionOptionsLen = 0;
572
573 // Returns a new FunctionOptions
574 FunctionOptions mergeOptions(FunctionOptions&& other, UErrorCode&);
575}; // class FunctionOptions
576
588 public:
607 FormattedValue() : type(kString) {}
616 bool isString() const { return type == kString; }
625 bool isNumber() const { return type == kNumber; }
633 const UnicodeString& getString() const { return stringOutput; }
641 const number::FormattedNumber& getNumber() const { return numberOutput; }
657 FormattedValue(FormattedValue&& other) { *this = std::move(other); }
665 private:
666 enum Type {
667 kString,
668 kNumber
669 };
670 Type type;
671 UnicodeString stringOutput;
672 number::FormattedNumber numberOutput;
673 }; // class FormattedValue
674
688 public:
699 explicit FormattedPlaceholder(const UnicodeString& s) : fallback(s), type(kFallback) {}
712 : fallback(input.fallback), source(input.source),
713 formatted(std::move(output)), previousOptions(FunctionOptions()), type(kEvaluated) {}
714
727 : fallback(input.fallback), source(input.source),
728 formatted(std::move(output)), previousOptions(std::move(opts)), type(kEvaluated) {}
729
739 : fallback(fb), source(input), type(kUnevaluated) {}
740
747 FormattedPlaceholder() : type(kNull) {}
767 bool isFallback() const { return type == kFallback; }
777 bool isNullOperand() const { return type == kNull; }
787 bool isEvaluated() const { return (type == kEvaluated); }
796 bool canFormat() const { return !(isFallback() || isNullOperand()); }
804 const UnicodeString& getFallback() const { return fallback; }
813 const FunctionOptions& options() const { return previousOptions; }
814
821 const FormattedValue& output() const { return formatted; }
837 FormattedPlaceholder(FormattedPlaceholder&& other) { *this = std::move(other); }
854 UErrorCode& status) const;
855
856 private:
857 friend class MessageFormatter;
858
859 enum Type {
860 kFallback, // Represents the result of formatting that encountered an error
861 kNull, // Represents the absence of both an output and an input (not necessarily an error)
862 kUnevaluated, // `source` should be valid, but there's no result yet
863 kEvaluated, // `formatted` exists
864 };
865 UnicodeString fallback;
866 Formattable source;
867 FormattedValue formatted;
868 FunctionOptions previousOptions; // Ignored unless type is kEvaluated
869 Type type;
870 }; // class FormattedPlaceholder
871
883 public:
891 if (U_SUCCESS(status)) {
892 status = U_UNSUPPORTED_ERROR;
893 }
894 }
895
901 int32_t length(UErrorCode& status) const {
902 if (U_SUCCESS(status)) {
903 status = U_UNSUPPORTED_ERROR;
904 }
905 return -1;
906 }
907
913 char16_t charAt(int32_t index, UErrorCode& status) const {
914 (void) index;
915 if (U_SUCCESS(status)) {
916 status = U_UNSUPPORTED_ERROR;
917 }
918 return 0;
919 }
920
926 StringPiece subSequence(int32_t start, int32_t end, UErrorCode& status) const {
927 (void) start;
928 (void) end;
929 if (U_SUCCESS(status)) {
930 status = U_UNSUPPORTED_ERROR;
931 }
932 return "";
933 }
934
940 UnicodeString toString(UErrorCode& status) const override {
941 if (U_SUCCESS(status)) {
942 status = U_UNSUPPORTED_ERROR;
943 }
944 return {};
945 }
946
952 UnicodeString toTempString(UErrorCode& status) const override {
953 if (U_SUCCESS(status)) {
954 status = U_UNSUPPORTED_ERROR;
955 }
956 return {};
957 }
958
964 Appendable& appendTo(Appendable& appendable, UErrorCode& status) const override {
965 if (U_SUCCESS(status)) {
966 status = U_UNSUPPORTED_ERROR;
967 }
968 return appendable;
969 }
970
976 UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const override {
977 (void) cfpos;
978 if (U_SUCCESS(status)) {
979 status = U_UNSUPPORTED_ERROR;
980 }
981 return false;
982 }
983
990 if (U_SUCCESS(status)) {
991 status = U_UNSUPPORTED_ERROR;
992 }
993 return nullptr;
994 }
995
1002 }; // class FormattedMessage
1003
1004} // namespace message2
1005
1006U_NAMESPACE_END
1007
1008#endif // U_HIDE_DEPRECATED_API
1009
1010#endif /* #if !UCONFIG_NO_MF2 */
1011
1012#endif /* #if !UCONFIG_NO_FORMATTING */
1013
1014#endif /* #if !UCONFIG_NO_NORMALIZATION */
1015
1016#endif /* U_SHOW_CPLUSPLUS_API */
1017
1018#endif // MESSAGEFORMAT2_FORMATTABLE_H
1019
1020// eof
C++ API: Character Iterator.
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.
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.
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.
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:743
#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