• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"
16 #include "unicode/numberformatter.h"
17 #include "unicode/messageformat2_data_model_names.h"
18 
19 #ifndef U_HIDE_DEPRECATED_API
20 
21 #include <map>
22 #include <variant>
23 
24 U_NAMESPACE_BEGIN
25 
26 class Hashtable;
27 class UVector;
28 
29 namespace message2 {
30 
31     class Formatter;
32     class MessageContext;
33     class Selector;
34 
35     // Formattable
36     // ----------
37 
38     /**
39      * `FormattableObject` is an abstract class that can be implemented in order to define
40      * an arbitrary class that can be passed to a custom formatter or selector function.
41      * To be passed in such a way, it must be wrapped in a `Formattable` object.
42      *
43      * @internal ICU 75 technology preview
44      * @deprecated This API is for technology preview only.
45      */
46     class U_I18N_API FormattableObject : public UObject {
47     public:
48         /**
49          * Returns an arbitrary string representing the type of this object.
50          * It's up to the implementor of this class, as well as the implementors
51          * of any custom functions that rely on particular values of this tag
52          * corresponding to particular classes that the object contents can be
53          * downcast to, to ensure that the type tags are used soundly.
54          * @internal ICU 75 technology preview
55          * @deprecated This API is for technology preview only.
56          */
57         virtual const UnicodeString& tag() const = 0;
58         /**
59          * Destructor.
60          *
61          * @internal ICU 75 technology preview
62          * @deprecated This API is for technology preview only.
63          */
64         virtual ~FormattableObject();
65     }; // class FormattableObject
66 
67     class Formattable;
68 } // namespace message2
69 
70 U_NAMESPACE_END
71 
72 /// @cond DOXYGEN_IGNORE
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)
80 template class U_I18N_API std::_Variant_storage_<false,
81   double,
82   int64_t,
83   icu::UnicodeString,
84   icu::Formattable,
85   const icu::message2::FormattableObject *,
86   std::pair<const icu::message2::Formattable *,int32_t>>;
87 #endif
88 typedef std::pair<const icu::message2::Formattable*, int32_t> P;
89 template class U_I18N_API std::variant<double,
90 				       int64_t,
91 				       icu::UnicodeString,
92 				       icu::Formattable,
93 				       const icu::message2::FormattableObject*,
94                                        P>;
95 #endif
96 /// @endcond
97 
98 U_NAMESPACE_BEGIN
99 
100 namespace message2 {
101     /**
102      * The `Formattable` class represents a typed value that can be formatted,
103      * originating either from a message argument or a literal in the code.
104      * ICU's Formattable class is not used in MessageFormat 2 because it's unsafe to copy an
105      * icu::Formattable value that contains an object. (See ICU-20275).
106      *
107      * `Formattable` is immutable (not deeply immutable) and
108      * is movable and copyable.
109      * (Copying does not do a deep copy when the wrapped value is an array or
110      * object. Likewise, while a pointer to a wrapped array or object is `const`,
111      * the referents of the pointers may be mutated by other code.)
112      *
113      * @internal ICU 75 technology preview
114      * @deprecated This API is for technology preview only.
115      */
116     class U_I18N_API Formattable : public UObject {
117     public:
118 
119         /**
120          * Gets the data type of this Formattable object.
121          * @return    the data type of this Formattable object.
122          * @internal ICU 75 technology preview
123          * @deprecated This API is for technology preview only.
124          */
125         UFormattableType getType() const;
126 
127         /**
128          * Gets the double value of this object. If this object is not of type
129          * UFMT_DOUBLE, then the result is undefined and the error code is set.
130          *
131          * @param status Input/output error code.
132          * @return    the double value of this object.
133          * @internal ICU 75 technology preview
134          * @deprecated This API is for technology preview only.
135          */
getDouble(UErrorCode & status)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                 }
144                 status = U_ILLEGAL_ARGUMENT_ERROR;
145             }
146             return 0;
147         }
148 
149         /**
150          * Gets the long value of this object. If this object is not of type
151          * UFMT_LONG then the result is undefined and the error code is set.
152          *
153          * @param status Input/output error code.
154          * @return    the long value of this object.
155          * @internal ICU 75 technology preview
156          * @deprecated This API is for technology preview only.
157          */
getLong(UErrorCode & status)158         int32_t getLong(UErrorCode& status) const {
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                 }
166                 status = U_ILLEGAL_ARGUMENT_ERROR;
167             }
168             return 0;
169         }
170 
171         /**
172          * Gets the int64 value of this object. If this object is not of type
173          * kInt64 then the result is undefined and the error code is set.
174          * If conversion to int64 is desired, call getInt64()
175          *
176          * @param status Input/output error code.
177          * @return    the int64 value of this object.
178          * @internal ICU 75 technology preview
179          * @deprecated This API is for technology preview only.
180          */
getInt64Value(UErrorCode & status)181         int64_t getInt64Value(UErrorCode& status) const {
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                 }
189                 status = U_ILLEGAL_ARGUMENT_ERROR;
190             }
191             return 0;
192         }
193 
194         /**
195          * Gets the int64 value of this object. If this object is of a numeric
196          * type and the magnitude is too large to fit in an int64, then
197          * the maximum or minimum int64 value, as appropriate, is returned
198          * and the status is set to U_INVALID_FORMAT_ERROR.  If the
199          * magnitude fits in an int64, then a casting conversion is
200          * performed, with truncation of any fractional part. If this object is
201          * not a numeric type, then 0 is returned and
202          * the status is set to U_INVALID_FORMAT_ERROR.
203          * @param status the error code
204          * @return    the int64 value of this object.
205          * @internal ICU 75 technology preview
206          * @deprecated This API is for technology preview only.
207          */
208         int64_t         getInt64(UErrorCode& status) const;
209         /**
210          * Gets the string value of this object. If this object is not of type
211          * kString then the result is undefined and the error code is set.
212          *
213          * @param status Input/output error code.
214          * @return          A reference to the string value of this object.
215          * @internal ICU 75 technology preview
216          * @deprecated This API is for technology preview only.
217          */
getString(UErrorCode & status)218         const UnicodeString& getString(UErrorCode& status) const {
219             if (U_SUCCESS(status)) {
220                 if (std::holds_alternative<UnicodeString>(contents)) {
221                     return *std::get_if<UnicodeString>(&contents);
222                 }
223                 status = U_ILLEGAL_ARGUMENT_ERROR;
224             }
225             return bogusString;
226         }
227 
228         /**
229          * Gets the Date value of this object. If this object is not of type
230          * kDate then the result is undefined and the error code is set.
231          *
232          * @param status Input/output error code.
233          * @return    the Date value of this object.
234          * @internal ICU 75 technology preview
235          * @deprecated This API is for technology preview only.
236          */
getDate(UErrorCode & status)237         UDate getDate(UErrorCode& status) const {
238             if (U_SUCCESS(status)) {
239                 if (isDate()) {
240                     return *std::get_if<double>(&contents);
241                 }
242                 status = U_ILLEGAL_ARGUMENT_ERROR;
243             }
244             return 0;
245         }
246 
247         /**
248          * Returns true if the data type of this Formattable object
249          * is kDouble
250          * @return true if this is a pure numeric object
251          * @internal ICU 75 technology preview
252          * @deprecated This API is for technology preview only.
253          */
isNumeric()254         UBool isNumeric() const { return (getType() == UFMT_DOUBLE || getType() == UFMT_LONG || getType() == UFMT_INT64); }
255 
256         /**
257          * Gets the array value and count of this object. If this object
258          * is not of type kArray then the result is undefined and the error code is set.
259          *
260          * @param count    fill-in with the count of this object.
261          * @param status Input/output error code.
262          * @return         the array value of this object.
263          * @internal ICU 75 technology preview
264          * @deprecated This API is for technology preview only.
265          */
266         const Formattable* getArray(int32_t& count, UErrorCode& status) const;
267 
268         /**
269          * Returns a pointer to the FormattableObject contained within this
270          * formattable, or if this object does not contain a FormattableObject,
271          * returns nullptr and sets the error code.
272          *
273          * @param status Input/output error code.
274          * @return a FormattableObject pointer, or nullptr
275          * @internal ICU 75 technology preview
276          * @deprecated This API is for technology preview only.
277          */
getObject(UErrorCode & status)278         const FormattableObject* getObject(UErrorCode& status) const {
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                 }
286                 status = U_ILLEGAL_ARGUMENT_ERROR;
287             }
288             return nullptr;
289         }
290         /**
291          * Non-member swap function.
292          * @param f1 will get f2's contents
293          * @param f2 will get f1's contents
294          *
295          * @internal ICU 75 technology preview
296          * @deprecated This API is for technology preview only.
297          */
swap(Formattable & f1,Formattable & f2)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         }
304         /**
305          * Copy constructor.
306          *
307          * @internal ICU 75 technology preview
308          * @deprecated This API is for technology preview only.
309          */
310         Formattable(const Formattable&);
311         /**
312          * Assignment operator
313          *
314          * @internal ICU 75 technology preview
315          * @deprecated This API is for technology preview only.
316          */
317         Formattable& operator=(Formattable) noexcept;
318         /**
319          * Default constructor. Leaves the Formattable in a
320          * valid but undefined state.
321          *
322          * @internal ICU 75 technology preview
323          * @deprecated This API is for technology preview only.
324          */
Formattable()325         Formattable() : contents(0.0) {}
326         /**
327          * String constructor.
328          *
329          * @param s A string to wrap as a Formattable.
330          *
331          * @internal ICU 75 technology preview
332          * @deprecated This API is for technology preview only.
333          */
Formattable(const UnicodeString & s)334         Formattable(const UnicodeString& s) : contents(s) {}
335         /**
336          * Double constructor.
337          *
338          * @param d A double value to wrap as a Formattable.
339          *
340          * @internal ICU 75 technology preview
341          * @deprecated This API is for technology preview only.
342          */
Formattable(double d)343         Formattable(double d) : contents(d) {}
344         /**
345          * Int64 constructor.
346          *
347          * @param i An int64 value to wrap as a Formattable.
348          *
349          * @internal ICU 75 technology preview
350          * @deprecated This API is for technology preview only.
351          */
Formattable(int64_t i)352         Formattable(int64_t i) : contents(i) {}
353         /**
354          * Date factory method.
355          *
356          * @param d A UDate value to wrap as a Formattable.
357          * @internal ICU 75 technology preview
358          * @deprecated This API is for technology preview only.
359          */
forDate(UDate d)360         static Formattable forDate(UDate d) {
361             Formattable f;
362             f.contents = d;
363             f.holdsDate = true;
364             return f;
365         }
366         /**
367          * Creates a Formattable object of an appropriate numeric type from a
368          * a decimal number in string form.  The Formattable will retain the
369          * full precision of the input in decimal format, even when it exceeds
370          * what can be represented by a double or int64_t.
371          *
372          * @param number  the unformatted (not localized) string representation
373          *                     of the Decimal number.
374          * @param status  the error code.  Possible errors include U_INVALID_FORMAT_ERROR
375          *                if the format of the string does not conform to that of a
376          *                decimal number.
377          * @internal ICU 75 technology preview
378          * @deprecated This API is for technology preview only.
379          */
380         static Formattable forDecimal(std::string_view number, UErrorCode& status);
381         /**
382          * Array constructor.
383          *
384          * @param arr An array of Formattables, which is adopted.
385          * @param len The length of the array.
386          *
387          * @internal ICU 75 technology preview
388          * @deprecated This API is for technology preview only.
389          */
Formattable(const Formattable * arr,int32_t len)390         Formattable(const Formattable* arr, int32_t len) : contents(std::pair(arr, len)) {}
391         /**
392          * Object constructor.
393          *
394          * @param obj A FormattableObject (not adopted).
395          *
396          * @internal ICU 75 technology preview
397          * @deprecated This API is for technology preview only.
398          */
Formattable(const FormattableObject * obj)399         Formattable(const FormattableObject* obj) : contents(obj) {}
400         /**
401          * Destructor.
402          *
403          * @internal ICU 75 technology preview
404          * @deprecated This API is for technology preview only.
405          */
406         virtual ~Formattable();
407         /**
408          * Converts the Formattable object to an ICU Formattable object.
409          * If this has type UFMT_OBJECT or kArray, then `status` is set to
410          * U_ILLEGAL_ARGUMENT_ERROR.
411          *
412          * @param status Input/output error code.
413          * @return An icu::Formattable value with the same value as this.
414          *
415          * @internal ICU 75 technology preview
416          * @deprecated This API is for technology preview only.
417          */
418         icu::Formattable asICUFormattable(UErrorCode& status) const;
419     private:
420 
421         std::variant<double,
422                      int64_t,
423                      UnicodeString,
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 
isDecimal()430         UBool isDecimal() const {
431             return std::holds_alternative<icu::Formattable>(contents);
432         }
isDate()433         UBool isDate() const {
434             return std::holds_alternative<double>(contents) && holdsDate;
435         }
436     }; // class Formattable
437 
438 /**
439  * Internal use only, but has to be included here as part of the implementation
440  * of the header-only `FunctionOptions::getOptions()` method
441  *
442  *  A `ResolvedFunctionOption` represents the result of evaluating
443  * a single named function option. It pairs the given name with the `Formattable`
444  * value resulting from evaluating the option's value.
445  *
446  * `ResolvedFunctionOption` is immutable and is not copyable or movable.
447  *
448  * @internal ICU 75 technology preview
449  * @deprecated This API is for technology preview only.
450  */
451 #ifndef U_IN_DOXYGEN
452 class U_I18N_API ResolvedFunctionOption : public UObject {
453   private:
454 
455     /* const */ UnicodeString name;
456     /* const */ Formattable value;
457 
458   public:
getName()459       const UnicodeString& getName() const { return name; }
getValue()460       const Formattable& getValue() const { return value; }
ResolvedFunctionOption(const UnicodeString & n,const Formattable & f)461       ResolvedFunctionOption(const UnicodeString& n, const Formattable& f) : name(n), value(f) {}
ResolvedFunctionOption()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 
473 /**
474  * Mapping from option names to `message2::Formattable` objects, obtained
475  * by calling `getOptions()` on a `FunctionOptions` object.
476  *
477  * @internal ICU 75 technology preview
478  * @deprecated This API is for technology preview only.
479  */
480 using FunctionOptionsMap = std::map<UnicodeString, message2::Formattable>;
481 
482 /**
483  * Structure encapsulating named options passed to a custom selector or formatter.
484  *
485  * @internal ICU 75 technology preview
486  * @deprecated This API is for technology preview only.
487  */
488 class U_I18N_API FunctionOptions : public UObject {
489  public:
490     /**
491      * Returns a map of all name-value pairs provided as options to this function.
492      * The syntactic order of options is not guaranteed to
493      * be preserved.
494      *
495      * This class is immutable and movable but not copyable.
496      *
497      * @return           A map from strings to `message2::Formattable` objects representing
498      *                   the results of resolving each option value.
499      *
500      * @internal ICU 75 technology preview
501      * @deprecated This API is for technology preview only.
502      */
getOptions()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++) {
508             const ResolvedFunctionOption& opt = resolvedOptions[i];
509             result[opt.getName()] = opt.getValue();
510         }
511         return result;
512     }
513     /**
514      * Default constructor.
515      * Returns an empty mapping.
516      *
517      * @internal ICU 75 technology preview
518      * @deprecated This API is for technology preview only.
519      */
FunctionOptions()520     FunctionOptions() { options = nullptr; }
521     /**
522      * Destructor.
523      *
524      * @internal ICU 75 technology preview
525      * @deprecated This API is for technology preview only.
526      */
527     virtual ~FunctionOptions();
528     /**
529      * Move assignment operator:
530      * The source FunctionOptions will be left in a valid but undefined state.
531      *
532      * @internal ICU 75 technology preview
533      * @deprecated This API is for technology preview only.
534      */
535     FunctionOptions& operator=(FunctionOptions&&) noexcept;
536     /**
537      * Move constructor:
538      * The source FunctionOptions will be left in a valid but undefined state.
539      *
540      * @internal ICU 75 technology preview
541      * @deprecated This API is for technology preview only.
542      */
543     FunctionOptions(FunctionOptions&&);
544     /**
545      * Copy constructor.
546      *
547      * @internal ICU 75 technology preview
548      * @deprecated This API is for technology preview only.
549      */
550     FunctionOptions& operator=(const FunctionOptions&) = delete;
551  private:
552     friend class MessageFormatter;
553     friend class StandardFunctions;
554 
555     explicit FunctionOptions(UVector&&, UErrorCode&);
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;
optionsCount()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 
576     /**
577      * A `FormattedValue` represents the result of formatting a `message2::Formattable`.
578      * It contains either a string or a formatted number. (More types could be added
579      * in the future.)
580      *
581      * `FormattedValue` is immutable and movable. It is not copyable.
582      *
583      * @internal ICU 75 technology preview
584      * @deprecated This API is for technology preview only.
585      */
586     class U_I18N_API FormattedValue : public UObject {
587     public:
588         /**
589          * Formatted string constructor.
590          * @internal ICU 75 technology preview
591          * @deprecated This API is for technology preview only.
592          */
593         explicit FormattedValue(const UnicodeString&);
594         /**
595          * Formatted number constructor.
596          * @internal ICU 75 technology preview
597          * @deprecated This API is for technology preview only.
598          */
599         explicit FormattedValue(number::FormattedNumber&&);
600         /**
601          * Default constructor. Leaves the FormattedValue in
602          * a valid but undefined state.
603          * @internal ICU 75 technology preview
604          * @deprecated This API is for technology preview only.
605          */
FormattedValue()606         FormattedValue() : type(kString) {}
607         /**
608          * Returns true iff this is a formatted string.
609          *
610          * @return True if and only if this value is a formatted string.
611          *
612          * @internal ICU 75 technology preview
613          * @deprecated This API is for technology preview only.
614          */
isString()615         bool isString() const { return type == kString; }
616         /**
617          * Returns true iff this is a formatted number.
618          *
619          * @return True if and only if this value is a formatted number.
620          *
621          * @internal ICU 75 technology preview
622          * @deprecated This API is for technology preview only.
623          */
isNumber()624         bool isNumber() const { return type == kNumber; }
625         /**
626          * Gets the string contents of this value. If !isString(), then
627          * the result is undefined.
628          * @return          A reference to a formatted string.
629          * @internal ICU 75 technology preview
630          * @deprecated This API is for technology preview only.
631          */
getString()632         const UnicodeString& getString() const { return stringOutput; }
633         /**
634          * Gets the number contents of this value. If !isNumber(), then
635          * the result is undefined.
636          * @return          A reference to a formatted number.
637          * @internal ICU 75 technology preview
638          * @deprecated This API is for technology preview only.
639          */
getNumber()640         const number::FormattedNumber& getNumber() const { return numberOutput; }
641         /**
642          * Move assignment operator:
643          * The source FormattedValue will be left in a valid but undefined state.
644          *
645          * @internal ICU 75 technology preview
646          * @deprecated This API is for technology preview only.
647          */
648         FormattedValue& operator=(FormattedValue&&) noexcept;
649         /**
650          * Move constructor:
651          * The source FormattedValue will be left in a valid but undefined state.
652          *
653          * @internal ICU 75 technology preview
654          * @deprecated This API is for technology preview only.
655          */
FormattedValue(FormattedValue && other)656         FormattedValue(FormattedValue&& other) { *this = std::move(other); }
657         /**
658          * Destructor.
659          *
660          * @internal ICU 75 technology preview
661          * @deprecated This API is for technology preview only.
662          */
663         virtual ~FormattedValue();
664     private:
665         enum Type {
666             kString,
667             kNumber
668         };
669         Type type;
670         UnicodeString stringOutput;
671         number::FormattedNumber numberOutput;
672     }; // class FormattedValue
673 
674     /**
675      * A `FormattablePlaceholder` encapsulates an input value (a `message2::Formattable`)
676      * together with an optional output value (a `message2::FormattedValue`).
677      *  More information, such as source line/column numbers, could be added to the class
678      * in the future.
679      *
680      * `FormattablePlaceholder` is immutable (not deeply immutable) and movable.
681      * It is not copyable.
682      *
683      * @internal ICU 75 technology preview
684      * @deprecated This API is for technology preview only.
685      */
686     class U_I18N_API FormattedPlaceholder : public UObject {
687     public:
688         /**
689          * Fallback constructor. Constructs a value that represents a formatting error,
690          * without recording an input `Formattable` as the source.
691          *
692          * @param s An error string. (See the MessageFormat specification for details
693          *        on fallback strings.)
694          *
695          * @internal ICU 75 technology preview
696          * @deprecated This API is for technology preview only.
697          */
FormattedPlaceholder(const UnicodeString & s)698         explicit FormattedPlaceholder(const UnicodeString& s) : fallback(s), type(kFallback) {}
699         /**
700          * Constructor for fully formatted placeholders.
701          *
702          * @param input A `FormattedPlaceholder` containing the fallback string and source
703          *        `Formattable` used to construct the formatted value.
704          * @param output A `FormattedValue` representing the formatted output of `input`.
705          *        Passed by move.
706          *
707          * @internal ICU 75 technology preview
708          * @deprecated This API is for technology preview only.
709          */
FormattedPlaceholder(const FormattedPlaceholder & input,FormattedValue && output)710         FormattedPlaceholder(const FormattedPlaceholder& input, FormattedValue&& output)
711             : fallback(input.fallback), source(input.source),
712             formatted(std::move(output)), previousOptions(FunctionOptions()), type(kEvaluated) {}
713         /**
714          * Constructor for fully formatted placeholders with options.
715          *
716          * @param input A `FormattedPlaceholder` containing the fallback string and source
717          *        `Formattable` used to construct the formatted value.
718          * @param opts Function options that were used to construct `output`. May be the empty map.
719          * @param output A `FormattedValue` representing the formatted output of `input`.
720          *        Passed by move.
721          *
722          * @internal ICU 75 technology preview
723          * @deprecated This API is for technology preview only.
724          */
FormattedPlaceholder(const FormattedPlaceholder & input,FunctionOptions && opts,FormattedValue && output)725         FormattedPlaceholder(const FormattedPlaceholder& input, FunctionOptions&& opts, FormattedValue&& output)
726             : fallback(input.fallback), source(input.source),
727             formatted(std::move(output)), previousOptions(std::move(opts)), type(kEvaluated) {}
728         /**
729          * Constructor for unformatted placeholders.
730          *
731          * @param input A `Formattable` object.
732          * @param fb Fallback string to use if an error occurs while formatting the input.
733          *
734          * @internal ICU 75 technology preview
735          * @deprecated This API is for technology preview only.
736          */
FormattedPlaceholder(const Formattable & input,const UnicodeString & fb)737         FormattedPlaceholder(const Formattable& input, const UnicodeString& fb)
738             : fallback(fb), source(input), type(kUnevaluated) {}
739         /**
740          * Default constructor. Leaves the FormattedPlaceholder in a
741          * valid but undefined state.
742          *
743          * @internal ICU 75 technology preview
744          * @deprecated This API is for technology preview only.
745          */
FormattedPlaceholder()746         FormattedPlaceholder() : type(kNull) {}
747         /**
748          * Returns the source `Formattable` value for this placeholder.
749          * The result is undefined if this is a null operand.
750          *
751          * @return A message2::Formattable value.
752          *
753          * @internal ICU 75 technology preview
754          * @deprecated This API is for technology preview only.
755          */
756         const message2::Formattable& asFormattable() const;
757         /**
758          * Returns true iff this is a fallback placeholder.
759          *
760          * @return True if and only if this placeholder was constructed from a fallback string,
761          *         with no `Formattable` source or formatting output.
762          *
763          * @internal ICU 75 technology preview
764          * @deprecated This API is for technology preview only.
765          */
isFallback()766         bool isFallback() const { return type == kFallback; }
767         /**
768          * Returns true iff this is a null placeholder.
769          *
770          * @return True if and only if this placeholder represents the absent argument to a formatter
771          *         that was invoked without an argument.
772          *
773          * @internal ICU 75 technology preview
774          * @deprecated This API is for technology preview only.
775          */
isNullOperand()776         bool isNullOperand() const { return type == kNull; }
777         /**
778          * Returns true iff this has formatting output.
779          *
780          * @return True if and only if this was constructed from both an input `Formattable` and
781          *         output `FormattedValue`.
782          *
783          * @internal ICU 75 technology preview
784          * @deprecated This API is for technology preview only.
785          */
isEvaluated()786         bool isEvaluated() const { return (type == kEvaluated); }
787         /**
788          * Returns true iff this represents a valid argument to the formatter.
789          *
790          * @return True if and only if this is neither the null argument nor a fallback placeholder.
791          *
792          * @internal ICU 75 technology preview
793          * @deprecated This API is for technology preview only.
794          */
canFormat()795         bool canFormat() const { return !(isFallback() || isNullOperand()); }
796         /**
797          * Gets the fallback value of this placeholder, to be used in its place if an error occurs while
798          * formatting it.
799          * @return          A reference to this placeholder's fallback string.
800          * @internal ICU 75 technology preview
801          * @deprecated This API is for technology preview only.
802          */
getFallback()803         const UnicodeString& getFallback() const { return fallback; }
804         /**
805          * Returns the options of this placeholder. The result is the empty map if !isEvaluated().
806          * @return A reference to an option map, capturing the options that were used
807          *         in producing the output of this `FormattedPlaceholder`
808          *         (or empty if there is no output)
809          * @internal ICU 75 technology preview
810          * @deprecated This API is for technology preview only.
811          */
options()812         const FunctionOptions& options() const { return previousOptions; }
813 
814         /**
815          * Returns the formatted output of this placeholder. The result is undefined if !isEvaluated().
816          * @return          A fully formatted `FormattedPlaceholder`.
817          * @internal ICU 75 technology preview
818          * @deprecated This API is for technology preview only.
819          */
output()820         const FormattedValue& output() const { return formatted; }
821         /**
822          * Move assignment operator:
823          * The source FormattedPlaceholder will be left in a valid but undefined state.
824          *
825          * @internal ICU 75 technology preview
826          * @deprecated This API is for technology preview only.
827          */
828         FormattedPlaceholder& operator=(FormattedPlaceholder&&) noexcept;
829         /**
830          * Move constructor:
831          * The source FormattedPlaceholder will be left in a valid but undefined state.
832          *
833          * @internal ICU 75 technology preview
834          * @deprecated This API is for technology preview only.
835          */
FormattedPlaceholder(FormattedPlaceholder && other)836         FormattedPlaceholder(FormattedPlaceholder&& other) { *this = std::move(other); }
837         /**
838          * Formats this as a string, using defaults.  If this is
839          * either the null operand or is a fallback value, the return value is the result of formatting the
840          * fallback value (which is the default fallback string if this is the null operand).
841          * If there is no formatted output and the input is object- or array-typed,
842          * then the argument is treated as a fallback value, since there is no default formatter
843          * for objects or arrays.
844          *
845          * @param locale The locale to use for formatting numbers or dates
846          * @param status Input/output error code
847          * @return The result of formatting this placeholder.
848          *
849          * @internal ICU 75 technology preview
850          * @deprecated This API is for technology preview only.
851          */
852         UnicodeString formatToString(const Locale& locale,
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 
871     /**
872      * Not yet implemented: The result of a message formatting operation. Based on
873      * ICU4J's FormattedMessage.java.
874      *
875      * The class will contain information allowing the result to be viewed as a string,
876      * iterator, etc. (TBD)
877      *
878      * @internal ICU 75 technology preview
879      * @deprecated This API is for technology preview only.
880      */
881     class U_I18N_API FormattedMessage : public icu::FormattedValue {
882     public:
883         /**
884          * Not yet implemented.
885          *
886          * @internal ICU 75 technology preview
887          * @deprecated This API is for ICU internal use only.
888          */
FormattedMessage(UErrorCode & status)889         FormattedMessage(UErrorCode& status) {
890             if (U_SUCCESS(status)) {
891                 status = U_UNSUPPORTED_ERROR;
892             }
893         }
894         /**
895          * Not yet implemented.
896          *
897          * @internal ICU 75 technology preview
898          * @deprecated This API is for ICU internal use only.
899          */
length(UErrorCode & status)900         int32_t length(UErrorCode& status) const {
901             if (U_SUCCESS(status)) {
902                 status = U_UNSUPPORTED_ERROR;
903             }
904             return -1;
905         }
906         /**
907          * Not yet implemented.
908          *
909          * @internal ICU 75 technology preview
910          * @deprecated This API is for ICU internal use only.
911          */
charAt(int32_t index,UErrorCode & status)912         char16_t charAt(int32_t index, UErrorCode& status) const {
913             (void) index;
914             if (U_SUCCESS(status)) {
915                 status = U_UNSUPPORTED_ERROR;
916             }
917             return 0;
918         }
919         /**
920          * Not yet implemented.
921          *
922          * @internal ICU 75 technology preview
923          * @deprecated This API is for ICU internal use only.
924          */
subSequence(int32_t start,int32_t end,UErrorCode & status)925         StringPiece subSequence(int32_t start, int32_t end, UErrorCode& status) const {
926             (void) start;
927             (void) end;
928             if (U_SUCCESS(status)) {
929                 status = U_UNSUPPORTED_ERROR;
930             }
931             return "";
932         }
933         /**
934          * Not yet implemented.
935          *
936          * @internal ICU 75 technology preview
937          * @deprecated This API is for ICU internal use only.
938          */
toString(UErrorCode & status)939         UnicodeString toString(UErrorCode& status) const override {
940             if (U_SUCCESS(status)) {
941                 status = U_UNSUPPORTED_ERROR;
942             }
943             return {};
944         }
945         /**
946          * Not yet implemented.
947          *
948          * @internal ICU 75 technology preview
949          * @deprecated This API is for ICU internal use only.
950          */
toTempString(UErrorCode & status)951         UnicodeString toTempString(UErrorCode& status) const override {
952             if (U_SUCCESS(status)) {
953                 status = U_UNSUPPORTED_ERROR;
954             }
955             return {};
956         }
957         /**
958          * Not yet implemented.
959          *
960          * @internal ICU 75 technology preview
961          * @deprecated This API is for ICU internal use only.
962          */
appendTo(Appendable & appendable,UErrorCode & status)963         Appendable& appendTo(Appendable& appendable, UErrorCode& status) const override {
964             if (U_SUCCESS(status)) {
965                 status = U_UNSUPPORTED_ERROR;
966             }
967             return appendable;
968         }
969         /**
970          * Not yet implemented.
971          *
972          * @internal ICU 75 technology preview
973          * @deprecated This API is for ICU internal use only.
974          */
nextPosition(ConstrainedFieldPosition & cfpos,UErrorCode & status)975         UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const override {
976             (void) cfpos;
977             if (U_SUCCESS(status)) {
978                 status = U_UNSUPPORTED_ERROR;
979             }
980             return false;
981         }
982         /**
983          * Not yet implemented.
984          *
985          * @internal ICU 75 technology preview
986          * @deprecated This API is for ICU internal use only.
987          */
toCharacterIterator(UErrorCode & status)988         CharacterIterator* toCharacterIterator(UErrorCode& status) {
989             if (U_SUCCESS(status)) {
990                 status = U_UNSUPPORTED_ERROR;
991             }
992             return nullptr;
993         }
994         /**
995          * Destructor.
996          *
997          * @internal ICU 75 technology preview
998          * @deprecated This API is for ICU internal use only.
999          */
1000         virtual ~FormattedMessage();
1001     }; // class FormattedMessage
1002 
1003 } // namespace message2
1004 
1005 U_NAMESPACE_END
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
1018