jpayne@69: // © 2016 and later: Unicode, Inc. and others. jpayne@69: // License & terms of use: http://www.unicode.org/copyright.html jpayne@69: /* jpayne@69: ****************************************************************************** jpayne@69: * Copyright (C) 2014-2016, International Business Machines jpayne@69: * Corporation and others. All Rights Reserved. jpayne@69: ****************************************************************************** jpayne@69: * simpleformatter.h jpayne@69: */ jpayne@69: jpayne@69: #ifndef __SIMPLEFORMATTER_H__ jpayne@69: #define __SIMPLEFORMATTER_H__ jpayne@69: jpayne@69: /** jpayne@69: * \file jpayne@69: * \brief C++ API: Simple formatter, minimal subset of MessageFormat. jpayne@69: */ jpayne@69: jpayne@69: #include "unicode/utypes.h" jpayne@69: jpayne@69: #if U_SHOW_CPLUSPLUS_API jpayne@69: jpayne@69: #include "unicode/unistr.h" jpayne@69: jpayne@69: U_NAMESPACE_BEGIN jpayne@69: jpayne@69: // Forward declaration: jpayne@69: namespace number { jpayne@69: namespace impl { jpayne@69: class SimpleModifier; jpayne@69: } jpayne@69: } jpayne@69: jpayne@69: /** jpayne@69: * Formats simple patterns like "{1} was born in {0}". jpayne@69: * Minimal subset of MessageFormat; fast, simple, minimal dependencies. jpayne@69: * Supports only numbered arguments with no type nor style parameters, jpayne@69: * and formats only string values. jpayne@69: * Quoting via ASCII apostrophe compatible with ICU MessageFormat default behavior. jpayne@69: * jpayne@69: * Factory methods set error codes for syntax errors jpayne@69: * and for too few or too many arguments/placeholders. jpayne@69: * jpayne@69: * SimpleFormatter objects are thread-safe except for assignment and applying new patterns. jpayne@69: * jpayne@69: * Example: jpayne@69: *
jpayne@69:  * UErrorCode errorCode = U_ZERO_ERROR;
jpayne@69:  * SimpleFormatter fmt("{1} '{born}' in {0}", errorCode);
jpayne@69:  * UnicodeString result;
jpayne@69:  *
jpayne@69:  * // Output: "paul {born} in england"
jpayne@69:  * fmt.format("england", "paul", result, errorCode);
jpayne@69:  * 
jpayne@69: * jpayne@69: * This class is not intended for public subclassing. jpayne@69: * jpayne@69: * @see MessageFormat jpayne@69: * @see UMessagePatternApostropheMode jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: class U_COMMON_API SimpleFormatter U_FINAL : public UMemory { jpayne@69: public: jpayne@69: /** jpayne@69: * Default constructor. jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: SimpleFormatter() : compiledPattern((char16_t)0) {} jpayne@69: jpayne@69: /** jpayne@69: * Constructs a formatter from the pattern string. jpayne@69: * jpayne@69: * @param pattern The pattern string. jpayne@69: * @param errorCode ICU error code in/out parameter. jpayne@69: * Must fulfill U_SUCCESS before the function call. jpayne@69: * Set to U_ILLEGAL_ARGUMENT_ERROR for bad argument syntax. jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: SimpleFormatter(const UnicodeString& pattern, UErrorCode &errorCode) { jpayne@69: applyPattern(pattern, errorCode); jpayne@69: } jpayne@69: jpayne@69: /** jpayne@69: * Constructs a formatter from the pattern string. jpayne@69: * The number of arguments checked against the given limits is the jpayne@69: * highest argument number plus one, not the number of occurrences of arguments. jpayne@69: * jpayne@69: * @param pattern The pattern string. jpayne@69: * @param min The pattern must have at least this many arguments. jpayne@69: * @param max The pattern must have at most this many arguments. jpayne@69: * @param errorCode ICU error code in/out parameter. jpayne@69: * Must fulfill U_SUCCESS before the function call. jpayne@69: * Set to U_ILLEGAL_ARGUMENT_ERROR for bad argument syntax and jpayne@69: * too few or too many arguments. jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: SimpleFormatter(const UnicodeString& pattern, int32_t min, int32_t max, jpayne@69: UErrorCode &errorCode) { jpayne@69: applyPatternMinMaxArguments(pattern, min, max, errorCode); jpayne@69: } jpayne@69: jpayne@69: /** jpayne@69: * Copy constructor. jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: SimpleFormatter(const SimpleFormatter& other) jpayne@69: : compiledPattern(other.compiledPattern) {} jpayne@69: jpayne@69: /** jpayne@69: * Assignment operator. jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: SimpleFormatter &operator=(const SimpleFormatter& other); jpayne@69: jpayne@69: /** jpayne@69: * Destructor. jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: ~SimpleFormatter(); jpayne@69: jpayne@69: /** jpayne@69: * Changes this object according to the new pattern. jpayne@69: * jpayne@69: * @param pattern The pattern string. jpayne@69: * @param errorCode ICU error code in/out parameter. jpayne@69: * Must fulfill U_SUCCESS before the function call. jpayne@69: * Set to U_ILLEGAL_ARGUMENT_ERROR for bad argument syntax. jpayne@69: * @return TRUE if U_SUCCESS(errorCode). jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: UBool applyPattern(const UnicodeString &pattern, UErrorCode &errorCode) { jpayne@69: return applyPatternMinMaxArguments(pattern, 0, INT32_MAX, errorCode); jpayne@69: } jpayne@69: jpayne@69: /** jpayne@69: * Changes this object according to the new pattern. jpayne@69: * The number of arguments checked against the given limits is the jpayne@69: * highest argument number plus one, not the number of occurrences of arguments. jpayne@69: * jpayne@69: * @param pattern The pattern string. jpayne@69: * @param min The pattern must have at least this many arguments. jpayne@69: * @param max The pattern must have at most this many arguments. jpayne@69: * @param errorCode ICU error code in/out parameter. jpayne@69: * Must fulfill U_SUCCESS before the function call. jpayne@69: * Set to U_ILLEGAL_ARGUMENT_ERROR for bad argument syntax and jpayne@69: * too few or too many arguments. jpayne@69: * @return TRUE if U_SUCCESS(errorCode). jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: UBool applyPatternMinMaxArguments(const UnicodeString &pattern, jpayne@69: int32_t min, int32_t max, UErrorCode &errorCode); jpayne@69: jpayne@69: /** jpayne@69: * @return The max argument number + 1. jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: int32_t getArgumentLimit() const { jpayne@69: return getArgumentLimit(compiledPattern.getBuffer(), compiledPattern.length()); jpayne@69: } jpayne@69: jpayne@69: /** jpayne@69: * Formats the given value, appending to the appendTo builder. jpayne@69: * The argument value must not be the same object as appendTo. jpayne@69: * getArgumentLimit() must be at most 1. jpayne@69: * jpayne@69: * @param value0 Value for argument {0}. jpayne@69: * @param appendTo Gets the formatted pattern and value appended. jpayne@69: * @param errorCode ICU error code in/out parameter. jpayne@69: * Must fulfill U_SUCCESS before the function call. jpayne@69: * @return appendTo jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: UnicodeString &format( jpayne@69: const UnicodeString &value0, jpayne@69: UnicodeString &appendTo, UErrorCode &errorCode) const; jpayne@69: jpayne@69: /** jpayne@69: * Formats the given values, appending to the appendTo builder. jpayne@69: * An argument value must not be the same object as appendTo. jpayne@69: * getArgumentLimit() must be at most 2. jpayne@69: * jpayne@69: * @param value0 Value for argument {0}. jpayne@69: * @param value1 Value for argument {1}. jpayne@69: * @param appendTo Gets the formatted pattern and values appended. jpayne@69: * @param errorCode ICU error code in/out parameter. jpayne@69: * Must fulfill U_SUCCESS before the function call. jpayne@69: * @return appendTo jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: UnicodeString &format( jpayne@69: const UnicodeString &value0, jpayne@69: const UnicodeString &value1, jpayne@69: UnicodeString &appendTo, UErrorCode &errorCode) const; jpayne@69: jpayne@69: /** jpayne@69: * Formats the given values, appending to the appendTo builder. jpayne@69: * An argument value must not be the same object as appendTo. jpayne@69: * getArgumentLimit() must be at most 3. jpayne@69: * jpayne@69: * @param value0 Value for argument {0}. jpayne@69: * @param value1 Value for argument {1}. jpayne@69: * @param value2 Value for argument {2}. jpayne@69: * @param appendTo Gets the formatted pattern and values appended. jpayne@69: * @param errorCode ICU error code in/out parameter. jpayne@69: * Must fulfill U_SUCCESS before the function call. jpayne@69: * @return appendTo jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: UnicodeString &format( jpayne@69: const UnicodeString &value0, jpayne@69: const UnicodeString &value1, jpayne@69: const UnicodeString &value2, jpayne@69: UnicodeString &appendTo, UErrorCode &errorCode) const; jpayne@69: jpayne@69: /** jpayne@69: * Formats the given values, appending to the appendTo string. jpayne@69: * jpayne@69: * @param values The argument values. jpayne@69: * An argument value must not be the same object as appendTo. jpayne@69: * Can be NULL if valuesLength==getArgumentLimit()==0. jpayne@69: * @param valuesLength The length of the values array. jpayne@69: * Must be at least getArgumentLimit(). jpayne@69: * @param appendTo Gets the formatted pattern and values appended. jpayne@69: * @param offsets offsets[i] receives the offset of where jpayne@69: * values[i] replaced pattern argument {i}. jpayne@69: * Can be shorter or longer than values. Can be NULL if offsetsLength==0. jpayne@69: * If there is no {i} in the pattern, then offsets[i] is set to -1. jpayne@69: * @param offsetsLength The length of the offsets array. jpayne@69: * @param errorCode ICU error code in/out parameter. jpayne@69: * Must fulfill U_SUCCESS before the function call. jpayne@69: * @return appendTo jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: UnicodeString &formatAndAppend( jpayne@69: const UnicodeString *const *values, int32_t valuesLength, jpayne@69: UnicodeString &appendTo, jpayne@69: int32_t *offsets, int32_t offsetsLength, UErrorCode &errorCode) const; jpayne@69: jpayne@69: /** jpayne@69: * Formats the given values, replacing the contents of the result string. jpayne@69: * May optimize by actually appending to the result if it is the same object jpayne@69: * as the value corresponding to the initial argument in the pattern. jpayne@69: * jpayne@69: * @param values The argument values. jpayne@69: * An argument value may be the same object as result. jpayne@69: * Can be NULL if valuesLength==getArgumentLimit()==0. jpayne@69: * @param valuesLength The length of the values array. jpayne@69: * Must be at least getArgumentLimit(). jpayne@69: * @param result Gets its contents replaced by the formatted pattern and values. jpayne@69: * @param offsets offsets[i] receives the offset of where jpayne@69: * values[i] replaced pattern argument {i}. jpayne@69: * Can be shorter or longer than values. Can be NULL if offsetsLength==0. jpayne@69: * If there is no {i} in the pattern, then offsets[i] is set to -1. jpayne@69: * @param offsetsLength The length of the offsets array. jpayne@69: * @param errorCode ICU error code in/out parameter. jpayne@69: * Must fulfill U_SUCCESS before the function call. jpayne@69: * @return result jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: UnicodeString &formatAndReplace( jpayne@69: const UnicodeString *const *values, int32_t valuesLength, jpayne@69: UnicodeString &result, jpayne@69: int32_t *offsets, int32_t offsetsLength, UErrorCode &errorCode) const; jpayne@69: jpayne@69: /** jpayne@69: * Returns the pattern text with none of the arguments. jpayne@69: * Like formatting with all-empty string values. jpayne@69: * @stable ICU 57 jpayne@69: */ jpayne@69: UnicodeString getTextWithNoArguments() const { jpayne@69: return getTextWithNoArguments( jpayne@69: compiledPattern.getBuffer(), jpayne@69: compiledPattern.length(), jpayne@69: nullptr, jpayne@69: 0); jpayne@69: } jpayne@69: jpayne@69: #ifndef U_HIDE_INTERNAL_API jpayne@69: /** jpayne@69: * Returns the pattern text with none of the arguments. jpayne@69: * Like formatting with all-empty string values. jpayne@69: * jpayne@69: * TODO(ICU-20406): Replace this with an Iterator interface. jpayne@69: * jpayne@69: * @param offsets offsets[i] receives the offset of where {i} was located jpayne@69: * before it was replaced by an empty string. jpayne@69: * For example, "a{0}b{1}" produces offset 1 for i=0 and 2 for i=1. jpayne@69: * Can be nullptr if offsetsLength==0. jpayne@69: * If there is no {i} in the pattern, then offsets[i] is set to -1. jpayne@69: * @param offsetsLength The length of the offsets array. jpayne@69: * jpayne@69: * @internal jpayne@69: */ jpayne@69: UnicodeString getTextWithNoArguments(int32_t *offsets, int32_t offsetsLength) const { jpayne@69: return getTextWithNoArguments( jpayne@69: compiledPattern.getBuffer(), jpayne@69: compiledPattern.length(), jpayne@69: offsets, jpayne@69: offsetsLength); jpayne@69: } jpayne@69: #endif // U_HIDE_INTERNAL_API jpayne@69: jpayne@69: private: jpayne@69: /** jpayne@69: * Binary representation of the compiled pattern. jpayne@69: * Index 0: One more than the highest argument number. jpayne@69: * Followed by zero or more arguments or literal-text segments. jpayne@69: * jpayne@69: * An argument is stored as its number, less than ARG_NUM_LIMIT. jpayne@69: * A literal-text segment is stored as its length (at least 1) offset by ARG_NUM_LIMIT, jpayne@69: * followed by that many chars. jpayne@69: */ jpayne@69: UnicodeString compiledPattern; jpayne@69: jpayne@69: static inline int32_t getArgumentLimit(const char16_t *compiledPattern, jpayne@69: int32_t compiledPatternLength) { jpayne@69: return compiledPatternLength == 0 ? 0 : compiledPattern[0]; jpayne@69: } jpayne@69: jpayne@69: static UnicodeString getTextWithNoArguments( jpayne@69: const char16_t *compiledPattern, jpayne@69: int32_t compiledPatternLength, jpayne@69: int32_t *offsets, jpayne@69: int32_t offsetsLength); jpayne@69: jpayne@69: static UnicodeString &format( jpayne@69: const char16_t *compiledPattern, int32_t compiledPatternLength, jpayne@69: const UnicodeString *const *values, jpayne@69: UnicodeString &result, const UnicodeString *resultCopy, UBool forbidResultAsValue, jpayne@69: int32_t *offsets, int32_t offsetsLength, jpayne@69: UErrorCode &errorCode); jpayne@69: jpayne@69: // Give access to internals to SimpleModifier for number formatting jpayne@69: friend class number::impl::SimpleModifier; jpayne@69: }; jpayne@69: jpayne@69: U_NAMESPACE_END jpayne@69: jpayne@69: #endif /* U_SHOW_CPLUSPLUS_API */ jpayne@69: jpayne@69: #endif // __SIMPLEFORMATTER_H__