ICU 78.1  78.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 #include "unicode/smpdtfmt.h"
21 
22 #ifndef U_HIDE_DEPRECATED_API
23 
24 #include <map>
25 #include <variant>
26 
27 U_NAMESPACE_BEGIN
28 
29 class Hashtable;
30 class UVector;
31 
32 namespace message2 {
33 
34  class Formatter;
35  class MessageContext;
36  class Selector;
37 
38  // Formattable
39  // ----------
40 
50  public:
60  virtual const UnicodeString& tag() const = 0;
67  virtual ~FormattableObject();
68  }; // class FormattableObject
69 
96  };
97 
114  public:
115 
123 
133  U_I18N_API double getDouble(UErrorCode& status) const {
134  if (U_SUCCESS(status)) {
135  if (isDecimal() && getType() == UFMT_DOUBLE) {
136  return (std::get_if<icu::Formattable>(&contents))->getDouble();
137  }
138  if (std::holds_alternative<double>(contents)) {
139  return *(std::get_if<double>(&contents));
140  }
141  status = U_ILLEGAL_ARGUMENT_ERROR;
142  }
143  return 0;
144  }
145 
155  U_I18N_API int32_t getLong(UErrorCode& status) const {
156  if (U_SUCCESS(status)) {
157  if (isDecimal() && getType() == UFMT_LONG) {
158  return std::get_if<icu::Formattable>(&contents)->getLong();
159  }
160  if (std::holds_alternative<int64_t>(contents)) {
161  return static_cast<int32_t>(*(std::get_if<int64_t>(&contents)));
162  }
163  status = U_ILLEGAL_ARGUMENT_ERROR;
164  }
165  return 0;
166  }
167 
178  U_I18N_API int64_t getInt64Value(UErrorCode& status) const {
179  if (U_SUCCESS(status)) {
180  if (isDecimal() && getType() == UFMT_INT64) {
181  return std::get_if<icu::Formattable>(&contents)->getInt64();
182  }
183  if (std::holds_alternative<int64_t>(contents)) {
184  return *(std::get_if<int64_t>(&contents));
185  }
186  status = U_ILLEGAL_ARGUMENT_ERROR;
187  }
188  return 0;
189  }
190 
205  U_I18N_API int64_t getInt64(UErrorCode& status) const;
216  if (U_SUCCESS(status)) {
217  if (std::holds_alternative<UnicodeString>(contents)) {
218  return *std::get_if<UnicodeString>(&contents);
219  }
220  status = U_ILLEGAL_ARGUMENT_ERROR;
221  }
222  return bogusString;
223  }
224 
236  U_I18N_API const DateInfo* getDate(UErrorCode& status) const {
237  if (U_SUCCESS(status)) {
238  if (isDate()) {
239  return std::get_if<DateInfo>(&contents);
240  }
241  status = U_ILLEGAL_ARGUMENT_ERROR;
242  }
243  return nullptr;
244  }
245 
253  U_I18N_API UBool isNumeric() const { return (getType() == UFMT_DOUBLE || getType() == UFMT_LONG || getType() == UFMT_INT64); }
254 
265  U_I18N_API const Formattable* getArray(int32_t& count, UErrorCode& status) const;
266 
278  if (U_SUCCESS(status)) {
279  // Can't return a reference since FormattableObject
280  // is an abstract class
281  if (getType() == UFMT_OBJECT) {
282  return *std::get_if<const FormattableObject*>(&contents);
283  // TODO: should assert that if type is object, object is non-null
284  }
285  status = U_ILLEGAL_ARGUMENT_ERROR;
286  }
287  return nullptr;
288  }
297  U_I18N_API friend inline void swap(Formattable& f1, Formattable& f2) noexcept {
298  using std::swap;
299 
300  swap(f1.contents, f2.contents);
301  }
323  U_I18N_API Formattable() : contents(0.0) {}
332  U_I18N_API Formattable(const UnicodeString& s) : contents(s) {}
341  U_I18N_API Formattable(double d) : contents(d) {}
350  U_I18N_API Formattable(int64_t i) : contents(i) {}
360  U_I18N_API Formattable(DateInfo&& d) : contents(std::move(d)) {}
375  U_I18N_API static Formattable forDecimal(std::string_view number, UErrorCode& status);
385  U_I18N_API Formattable(const Formattable* arr, int32_t len) : contents(std::pair(arr, len)) {}
394  U_I18N_API Formattable(const FormattableObject* obj) : contents(obj) {}
414  private:
415 
416  std::variant<double,
417  int64_t,
419  icu::Formattable, // represents a Decimal
420  DateInfo,
421  const FormattableObject*,
422  std::pair<const Formattable*, int32_t>> contents;
423  UnicodeString bogusString; // :((((
424 
425  UBool isDecimal() const {
426  return std::holds_alternative<icu::Formattable>(contents);
427  }
428  UBool isDate() const {
429  return std::holds_alternative<DateInfo>(contents);
430  }
431  }; // class Formattable
432 
446 #ifndef U_IN_DOXYGEN
447 class U_I18N_API_CLASS ResolvedFunctionOption : public UObject {
448  private:
449 
450  /* const */ UnicodeString name;
451  /* const */ Formattable value;
452  // True iff this option was represented in the syntax by a literal value.
453  // This is necessary in order to implement the spec for the `select` option
454  // of `:number` and `:integer`.
455  /* const */ bool sourceIsLiteral;
456 
457  public:
458  U_I18N_API const UnicodeString& getName() const { return name; }
459  U_I18N_API const Formattable& getValue() const { return value; }
460  U_I18N_API bool isLiteral() const { return sourceIsLiteral; }
461  U_I18N_API ResolvedFunctionOption(const UnicodeString& n, const Formattable& f, bool s)
462  : name(n), value(f), sourceIsLiteral(s) {}
463  U_I18N_API ResolvedFunctionOption() {}
464  U_I18N_API ResolvedFunctionOption(ResolvedFunctionOption&&);
465  U_I18N_API ResolvedFunctionOption& operator=(ResolvedFunctionOption&& other) noexcept {
466  name = std::move(other.name);
467  value = std::move(other.value);
468  sourceIsLiteral = other.sourceIsLiteral;
469  return *this;
470  }
471  U_I18N_API virtual ~ResolvedFunctionOption();
472 }; // class ResolvedFunctionOption
473 #endif
474 
482 using 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  }
522  FunctionOptions() { options = nullptr; }
529  virtual ~FunctionOptions();
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(std::u16string_view, Formattable&) const;
562  UBool wasSetFromLiteral(const UnicodeString&) const;
563  // Returns empty string if option doesn't exist
564  UnicodeString getStringFunctionOption(std::u16string_view) const;
565  int32_t optionsCount() const { return functionOptionsLen; }
566 
567  // Named options passed to functions
568  // This is not a Hashtable in order to make it possible for code in a public header file
569  // to construct a std::map from it, on-the-fly. Otherwise, it would be impossible to put
570  // that code in the header because it would have to call internal Hashtable methods.
571  ResolvedFunctionOption* options;
572  int32_t functionOptionsLen = 0;
573 
578  FunctionOptions mergeOptions(FunctionOptions&& other, UErrorCode&);
579 }; // class FunctionOptions
580 
592  public:
598  explicit FormattedValue(const UnicodeString&);
611  FormattedValue() : type(kString) {}
620  bool isString() const { return type == kString; }
629  bool isNumber() const { return type == kNumber; }
637  const UnicodeString& getString() const { return stringOutput; }
645  const number::FormattedNumber& getNumber() const { return numberOutput; }
661  FormattedValue(FormattedValue&& other) { *this = std::move(other); }
668  virtual ~FormattedValue();
669  private:
670  enum Type {
671  kString,
672  kNumber
673  };
674  Type type;
675  UnicodeString stringOutput;
676  number::FormattedNumber numberOutput;
677  }; // class FormattedValue
678 
692  public:
703  U_I18N_API explicit FormattedPlaceholder(const UnicodeString& s) : fallback(s), type(kFallback) {}
716  : fallback(input.fallback), source(input.source),
717  formatted(std::move(output)), previousOptions(FunctionOptions()), type(kEvaluated) {}
731  : fallback(input.fallback), source(input.source),
732  formatted(std::move(output)), previousOptions(std::move(opts)), type(kEvaluated) {}
743  : fallback(fb), source(input), type(kUnevaluated) {}
751  U_I18N_API FormattedPlaceholder() : type(kNull) {}
771  U_I18N_API bool isFallback() const { return type == kFallback; }
781  U_I18N_API bool isNullOperand() const { return type == kNull; }
791  U_I18N_API bool isEvaluated() const { return (type == kEvaluated); }
800  U_I18N_API bool canFormat() const { return !(isFallback() || isNullOperand()); }
808  U_I18N_API const UnicodeString& getFallback() const { return fallback; }
817  U_I18N_API const FunctionOptions& options() const { return previousOptions; }
824  U_I18N_API const FormattedValue& output() const { return formatted; }
840  U_I18N_API FormattedPlaceholder(FormattedPlaceholder&& other) { *this = std::move(other); }
857  UErrorCode& status) const;
858 
859  private:
860  friend class MessageFormatter;
861 
862  enum Type {
863  kFallback, // Represents the result of formatting that encountered an error
864  kNull, // Represents the absence of both an output and an input (not necessarily an error)
865  kUnevaluated, // `source` should be valid, but there's no result yet
866  kEvaluated, // `formatted` exists
867  };
868  UnicodeString fallback;
869  Formattable source;
870  FormattedValue formatted;
871  FunctionOptions previousOptions; // Ignored unless type is kEvaluated
872  Type type;
873  }; // class FormattedPlaceholder
874 
886  public:
894  if (U_SUCCESS(status)) {
895  status = U_UNSUPPORTED_ERROR;
896  }
897  }
904  int32_t length(UErrorCode& status) const {
905  if (U_SUCCESS(status)) {
906  status = U_UNSUPPORTED_ERROR;
907  }
908  return -1;
909  }
916  char16_t charAt(int32_t index, UErrorCode& status) const {
917  (void) index;
918  if (U_SUCCESS(status)) {
919  status = U_UNSUPPORTED_ERROR;
920  }
921  return 0;
922  }
929  StringPiece subSequence(int32_t start, int32_t end, UErrorCode& status) const {
930  (void) start;
931  (void) end;
932  if (U_SUCCESS(status)) {
933  status = U_UNSUPPORTED_ERROR;
934  }
935  return "";
936  }
943  UnicodeString toString(UErrorCode& status) const override {
944  if (U_SUCCESS(status)) {
945  status = U_UNSUPPORTED_ERROR;
946  }
947  return {};
948  }
955  UnicodeString toTempString(UErrorCode& status) const override {
956  if (U_SUCCESS(status)) {
957  status = U_UNSUPPORTED_ERROR;
958  }
959  return {};
960  }
967  Appendable& appendTo(Appendable& appendable, UErrorCode& status) const override {
968  if (U_SUCCESS(status)) {
969  status = U_UNSUPPORTED_ERROR;
970  }
971  return appendable;
972  }
979  UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const override {
980  (void) cfpos;
981  if (U_SUCCESS(status)) {
982  status = U_UNSUPPORTED_ERROR;
983  }
984  return false;
985  }
993  if (U_SUCCESS(status)) {
994  status = U_UNSUPPORTED_ERROR;
995  }
996  return nullptr;
997  }
1005  }; // class FormattedMessage
1006 
1007 } // namespace message2
1008 
1009 U_NAMESPACE_END
1010 
1011 #endif // U_HIDE_DEPRECATED_API
1012 
1013 #endif /* #if !UCONFIG_NO_MF2 */
1014 
1015 #endif /* #if !UCONFIG_NO_FORMATTING */
1016 
1017 #endif /* #if !UCONFIG_NO_NORMALIZATION */
1018 
1019 #endif /* U_SHOW_CPLUSPLUS_API */
1020 
1021 #endif // MESSAGEFORMAT2_FORMATTABLE_H
1022 
1023 // 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.
A Locale object represents a specific geographical, political, or cultural region.
Definition: locid.h:198
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:222
UnicodeString is a string class that stores Unicode characters directly and provides similar function...
Definition: unistr.h:303
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...
U_I18N_API friend void swap(Formattable &f1, Formattable &f2) noexcept
Non-member swap function.
U_I18N_API Formattable(const UnicodeString &s)
String constructor.
U_I18N_API Formattable & operator=(Formattable) noexcept
Assignment operator.
U_I18N_API int64_t getInt64(UErrorCode &status) const
Gets the int64 value of this object.
U_I18N_API int32_t getLong(UErrorCode &status) const
Gets the long value of this object.
U_I18N_API icu::Formattable asICUFormattable(UErrorCode &status) const
Converts the Formattable object to an ICU Formattable object.
U_I18N_API UBool isNumeric() const
Returns true if the data type of this Formattable object is kDouble.
U_I18N_API const Formattable * getArray(int32_t &count, UErrorCode &status) const
Gets the array value and count of this object.
U_I18N_API Formattable(const FormattableObject *obj)
Object constructor.
U_I18N_API Formattable(double d)
Double constructor.
static U_I18N_API 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.
U_I18N_API Formattable()
Default constructor.
U_I18N_API const DateInfo * getDate(UErrorCode &status) const
Gets the struct representing the date value of this object.
U_I18N_API Formattable(const Formattable *arr, int32_t len)
Array constructor.
U_I18N_API double getDouble(UErrorCode &status) const
Gets the double value of this object.
U_I18N_API UFormattableType getType() const
Gets the data type of this Formattable object.
U_I18N_API Formattable(int64_t i)
Int64 constructor.
U_I18N_API int64_t getInt64Value(UErrorCode &status) const
Gets the int64 value of this object.
U_I18N_API Formattable(DateInfo &&d)
Date constructor.
U_I18N_API Formattable(const Formattable &)
Copy constructor.
virtual U_I18N_API ~Formattable()
Destructor.
U_I18N_API const FormattableObject * getObject(UErrorCode &status) const
Returns a pointer to the FormattableObject contained within this formattable, or if this object does ...
U_I18N_API const UnicodeString & getString(UErrorCode &status) const
Gets the string 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.
CharacterIterator * toCharacterIterator(UErrorCode &status)
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.
Appendable & appendTo(Appendable &appendable, UErrorCode &status) const override
Not yet implemented.
virtual ~FormattedMessage()
Destructor.
char16_t charAt(int32_t index, UErrorCode &status) const
Not yet implemented.
A FormattablePlaceholder encapsulates an input value (a message2::Formattable) together with an optio...
U_I18N_API FormattedPlaceholder(const FormattedPlaceholder &input, FunctionOptions &&opts, FormattedValue &&output)
Constructor for fully formatted placeholders with options.
U_I18N_API FormattedPlaceholder(const UnicodeString &s)
Fallback constructor.
U_I18N_API UnicodeString formatToString(const Locale &locale, UErrorCode &status) const
Formats this as a string, using defaults.
U_I18N_API const message2::Formattable & asFormattable() const
Returns the source Formattable value for this placeholder.
U_I18N_API bool isFallback() const
Returns true iff this is a fallback placeholder.
U_I18N_API FormattedPlaceholder & operator=(FormattedPlaceholder &&) noexcept
Move assignment operator: The source FormattedPlaceholder will be left in a valid but undefined state...
U_I18N_API bool isEvaluated() const
Returns true iff this has formatting output.
U_I18N_API FormattedPlaceholder(const Formattable &input, const UnicodeString &fb)
Constructor for unformatted placeholders.
U_I18N_API const FunctionOptions & options() const
Returns the options of this placeholder.
U_I18N_API FormattedPlaceholder(const FormattedPlaceholder &input, FormattedValue &&output)
Constructor for fully formatted placeholders.
U_I18N_API const UnicodeString & getFallback() const
Gets the fallback value of this placeholder, to be used in its place if an error occurs while formatt...
U_I18N_API const FormattedValue & output() const
Returns the formatted output of this placeholder.
U_I18N_API bool canFormat() const
Returns true iff this represents a valid argument to the formatter.
U_I18N_API bool isNullOperand() const
Returns true iff this is a null placeholder.
U_I18N_API FormattedPlaceholder()
Default constructor.
A FormattedValue represents the result of formatting a message2::Formattable.
const UnicodeString & getString() const
Gets the string contents of this value.
virtual ~FormattedValue()
Destructor.
FormattedValue(number::FormattedNumber &&)
Formatted number constructor.
const number::FormattedNumber & getNumber() const
Gets the number contents of this value.
bool isNumber() const
Returns true iff this is a formatted number.
FormattedValue(const UnicodeString &)
Formatted string constructor.
FormattedValue & operator=(FormattedValue &&) noexcept
Move assignment operator: The source FormattedValue will be left in a valid but undefined state.
bool isString() const
Returns true iff this is a formatted string.
Structure encapsulating named options passed to a custom selector or formatter.
virtual ~FunctionOptions()
Destructor.
FunctionOptions & operator=(FunctionOptions &&) noexcept
Move assignment operator: The source FunctionOptions will be left in a valid but undefined state.
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.
C++ API: Format and parse dates in a language-independent manner.
The DateInfo struct represents all the information needed to format a date with a time zone.
UnicodeString zoneId
IANA time zone name; "UTC" if UTC; empty string if value is floating The time zone is required in ord...
UFormattableType
Enum designating the type of a UFormattable instance.
Definition: uformattable.h:48
@ UFMT_LONG
ufmt_getLong() will return without conversion.
Definition: uformattable.h:51
@ UFMT_OBJECT
ufmt_getObject() will return without conversion.
Definition: uformattable.h:55
@ UFMT_DOUBLE
ufmt_getDouble() will return without conversion.
Definition: uformattable.h:50
@ UFMT_INT64
ufmt_getInt64() will return without conversion.
Definition: uformattable.h:54
int8_t UBool
The ICU boolean type, a signed-byte integer.
Definition: umachine.h:269
Basic definitions for ICU, for both C and C++ APIs.
UErrorCode
Standard ICU4C error code type, a substitute for exceptions.
Definition: utypes.h:509
@ U_ILLEGAL_ARGUMENT_ERROR
Start of codes indicating failure.
Definition: utypes.h:546
@ U_UNSUPPORTED_ERROR
Requested operation not supported in current context.
Definition: utypes.h:561
#define U_SUCCESS(x)
Does the error code indicate success?
Definition: utypes.h:822
#define U_I18N_API_CLASS
Set to export library symbols from inside the i18n library, and to import them from outside,...
Definition: utypes.h:457
#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