ICU 77.1  77.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
26 U_NAMESPACE_BEGIN
27 
28 class Hashtable;
29 class UVector;
30 
31 namespace 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;
66  virtual ~FormattableObject();
67  }; // class FormattableObject
68 
69  class Formattable;
70 } // namespace message2
71 
72 U_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)
82 template class U_I18N_API std::_Variant_storage_<false,
83  double,
84  int64_t,
88  std::pair<const icu::message2::Formattable *,int32_t>>;
89 #endif
90 typedef std::pair<const icu::message2::Formattable*, int32_t> P;
91 template class U_I18N_API std::variant<double,
92  int64_t,
96  P>;
97 #endif
98 
100 U_NAMESPACE_BEGIN
101 
102 namespace message2 {
118  class U_I18N_API Formattable : public UObject {
119  public:
120 
127  UFormattableType getType() const;
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  }
146  status = U_ILLEGAL_ARGUMENT_ERROR;
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  }
168  status = U_ILLEGAL_ARGUMENT_ERROR;
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  }
191  status = U_ILLEGAL_ARGUMENT_ERROR;
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  }
225  status = U_ILLEGAL_ARGUMENT_ERROR;
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  }
244  status = U_ILLEGAL_ARGUMENT_ERROR;
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  }
288  status = U_ILLEGAL_ARGUMENT_ERROR;
289  }
290  return nullptr;
291  }
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  }
312  Formattable(const Formattable&);
319  Formattable& operator=(Formattable) noexcept;
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  }
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();
420  icu::Formattable asICUFormattable(UErrorCode& status) const;
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
454 class 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 
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();
537  FunctionOptions& operator=(FunctionOptions&&) noexcept;
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:
594  explicit FormattedValue(const UnicodeString&);
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; }
649  FormattedValue& operator=(FormattedValue&&) noexcept;
657  FormattedValue(FormattedValue&& other) { *this = std::move(other); }
664  virtual ~FormattedValue();
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) {}
727  : fallback(input.fallback), source(input.source),
728  formatted(std::move(output)), previousOptions(std::move(opts)), type(kEvaluated) {}
739  : fallback(fb), source(input), type(kUnevaluated) {}
747  FormattedPlaceholder() : type(kNull) {}
757  const message2::Formattable& asFormattable() const;
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; }
829  FormattedPlaceholder& operator=(FormattedPlaceholder&&) noexcept;
837  FormattedPlaceholder(FormattedPlaceholder&& other) { *this = std::move(other); }
853  UnicodeString formatToString(const Locale& locale,
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  }
901  int32_t length(UErrorCode& status) const {
902  if (U_SUCCESS(status)) {
903  status = U_UNSUPPORTED_ERROR;
904  }
905  return -1;
906  }
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  }
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  }
940  UnicodeString toString(UErrorCode& status) const override {
941  if (U_SUCCESS(status)) {
942  status = U_UNSUPPORTED_ERROR;
943  }
944  return {};
945  }
952  UnicodeString toTempString(UErrorCode& status) const override {
953  if (U_SUCCESS(status)) {
954  status = U_UNSUPPORTED_ERROR;
955  }
956  return {};
957  }
964  Appendable& appendTo(Appendable& appendable, UErrorCode& status) const override {
965  if (U_SUCCESS(status)) {
966  status = U_UNSUPPORTED_ERROR;
967  }
968  return appendable;
969  }
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  }
990  if (U_SUCCESS(status)) {
991  status = U_UNSUPPORTED_ERROR;
992  }
993  return nullptr;
994  }
1001  virtual ~FormattedMessage();
1002  }; // class FormattedMessage
1003 
1004 } // namespace message2
1005 
1006 U_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
const FunctionOptions & options() const
Returns the options of this placeholder.
int64_t getInt64Value(UErrorCode &status) const
Gets the int64 value of this object.
FormattedMessage(UErrorCode &status)
Not yet implemented.
const UnicodeString & getString(UErrorCode &status) const
Gets the string value of this object.
#define U_SUCCESS(x)
Does the error code indicate success?
Definition: utypes.h:743
A FormattedValue represents the result of formatting a message2::Formattable.
Formattable(const Formattable *arr, int32_t len)
Array constructor.
double UDate
Date and Time data type.
Definition: utypes.h:218
bool isEvaluated() const
Returns true iff this has formatting output.
FormattableObject is an abstract class that can be implemented in order to define an arbitrary class ...
Formattable(const FormattableObject *obj)
Object constructor.
An abstract formatted value: a string with associated field attributes.
UFormattableType
Enum designating the type of a UFormattable instance.
Definition: uformattable.h:48
FormattedPlaceholder(const Formattable &input, const UnicodeString &fb)
Constructor for unformatted placeholders.
int32_t length(UErrorCode &status) const
Not yet implemented.
UnicodeString toString(UErrorCode &status) const override
Not yet implemented.
#define U_I18N_API
Set to export library symbols from inside the i18n library, and to import them from outside...
Definition: utypes.h:316
UDate getDate(UErrorCode &status) const
Gets the Date value of this object.
CharacterIterator * toCharacterIterator(UErrorCode &status)
Not yet implemented.
Formattable(double d)
Double constructor.
const number::FormattedNumber & getNumber() const
Gets the number contents of this value.
Requested operation not supported in current context.
Definition: utypes.h:482
Abstract class that defines an API for iteration on text objects.
Definition: chariter.h:361
UnicodeString toTempString(UErrorCode &status) const override
Not yet implemented.
Start of codes indicating failure.
Definition: utypes.h:467
Appendable & appendTo(Appendable &appendable, UErrorCode &status) const override
Not yet implemented.
bool isString() const
Returns true iff this is a formatted string.
ufmt_getInt64() will return without conversion.
Definition: uformattable.h:54
ufmt_getObject() will return without conversion.
Definition: uformattable.h:55
double getDouble(UErrorCode &status) const
Gets the double value of this object.
FormattedPlaceholder(const FormattedPlaceholder &input, FormattedValue &&output)
Constructor for fully formatted placeholders.
UBool isNumeric() const
Returns true if the data type of this Formattable object is kDouble.
ufmt_getLong() will return without conversion.
Definition: uformattable.h:51
FunctionOptionsMap getOptions() const
Returns a map of all name-value pairs provided as options to this function.
bool isNumber() const
Returns true iff this is a formatted number.
const UnicodeString & getString() const
Gets the string contents of this value.
const FormattableObject * getObject(UErrorCode &status) const
Returns a pointer to the FormattableObject contained within this formattable, or if this object does ...
Formattable(int64_t i)
Int64 constructor.
Represents a span of a string containing a given field.
char16_t charAt(int32_t index, UErrorCode &status) const
Not yet implemented.
static Formattable forDate(UDate d)
Date factory method.
FormattedPlaceholder(const UnicodeString &s)
Fallback constructor.
UErrorCode
Standard ICU4C error code type, a substitute for exceptions.
Definition: utypes.h:430
FormattedPlaceholder(const FormattedPlaceholder &input, FunctionOptions &&opts, FormattedValue &&output)
Constructor for fully formatted placeholders with options.
Not yet implemented: The result of a message formatting operation.
friend void swap(Formattable &f1, Formattable &f2) noexcept
Non-member swap function.
The Formattable class represents a typed value that can be formatted, originating either from a messa...
Structure encapsulating named options passed to a custom selector or formatter.
bool isNullOperand() const
Returns true iff this is a null placeholder.
StringPiece subSequence(int32_t start, int32_t end, UErrorCode &status) const
Not yet implemented.
int32_t getLong(UErrorCode &status) const
Gets the long value of this object.
A FormattablePlaceholder encapsulates an input value (a message2::Formattable) together with an optio...
Basic definitions for ICU, for both C and C++ APIs.
Formattable(const UnicodeString &s)
String constructor.
bool isFallback() const
Returns true iff this is a fallback placeholder.
UBool nextPosition(ConstrainedFieldPosition &cfpos, UErrorCode &status) const override
Not yet implemented.
UnicodeString is a string class that stores Unicode characters directly and provides similar function...
Definition: unistr.h:295
C++ API: Character Iterator.
Formattable objects can be passed to the Format class or its subclasses for formatting.
Definition: fmtable.h:63
The result of a number formatting operation.
A string-like object that points to a sized piece of memory.
Definition: stringpiece.h:61
UObject is the common ICU &quot;boilerplate&quot; class.
Definition: uobject.h:223
C++ API: All-in-one formatter for localized numbers, currencies, and units.
const FormattedValue & output() const
Returns the formatted output of this placeholder.
ufmt_getDouble() will return without conversion.
Definition: uformattable.h:50
const UnicodeString & getFallback() const
Gets the fallback value of this placeholder, to be used in its place if an error occurs while formatt...
int8_t UBool
The ICU boolean type, a signed-byte integer.
Definition: umachine.h:247
bool canFormat() const
Returns true iff this represents a valid argument to the formatter.
Base class for objects to which Unicode characters and strings can be appended.
Definition: appendable.h:54
A Locale object represents a specific geographical, political, or cultural region.
Definition: locid.h:195