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