1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ****************************************************************************** 5 * Copyright (C) 2014-2016, International Business Machines 6 * Corporation and others. All Rights Reserved. 7 ****************************************************************************** 8 * simpleformatter.h 9 */ 10 11 #ifndef __SIMPLEFORMATTER_H__ 12 #define __SIMPLEFORMATTER_H__ 13 14 /** 15 * \file 16 * \brief C++ API: Simple formatter, minimal subset of MessageFormat. 17 */ 18 19 #include "unicode/utypes.h" 20 21 #if U_SHOW_CPLUSPLUS_API 22 23 #include "unicode/unistr.h" 24 25 U_NAMESPACE_BEGIN 26 27 // Forward declaration: 28 namespace number::impl { 29 class SimpleModifier; 30 } 31 32 /** 33 * Formats simple patterns like "{1} was born in {0}". 34 * Minimal subset of MessageFormat; fast, simple, minimal dependencies. 35 * Supports only numbered arguments with no type nor style parameters, 36 * and formats only string values. 37 * Quoting via ASCII apostrophe compatible with ICU MessageFormat default behavior. 38 * 39 * Factory methods set error codes for syntax errors 40 * and for too few or too many arguments/placeholders. 41 * 42 * SimpleFormatter objects are thread-safe except for assignment and applying new patterns. 43 * 44 * Example: 45 * <pre> 46 * UErrorCode errorCode = U_ZERO_ERROR; 47 * SimpleFormatter fmt("{1} '{born}' in {0}", errorCode); 48 * UnicodeString result; 49 * 50 * // Output: "paul {born} in england" 51 * fmt.format("england", "paul", result, errorCode); 52 * </pre> 53 * 54 * This class is not intended for public subclassing. 55 * 56 * @see MessageFormat 57 * @see UMessagePatternApostropheMode 58 * @stable ICU 57 59 */ 60 class U_COMMON_API SimpleFormatter final : public UMemory { 61 public: 62 /** 63 * Default constructor. 64 * @stable ICU 57 65 */ SimpleFormatter()66 SimpleFormatter() : compiledPattern((char16_t)0) {} 67 68 /** 69 * Constructs a formatter from the pattern string. 70 * 71 * @param pattern The pattern string. 72 * @param errorCode ICU error code in/out parameter. 73 * Must fulfill U_SUCCESS before the function call. 74 * Set to U_ILLEGAL_ARGUMENT_ERROR for bad argument syntax. 75 * @stable ICU 57 76 */ SimpleFormatter(const UnicodeString & pattern,UErrorCode & errorCode)77 SimpleFormatter(const UnicodeString& pattern, UErrorCode &errorCode) { 78 applyPattern(pattern, errorCode); 79 } 80 81 /** 82 * Constructs a formatter from the pattern string. 83 * The number of arguments checked against the given limits is the 84 * highest argument number plus one, not the number of occurrences of arguments. 85 * 86 * @param pattern The pattern string. 87 * @param min The pattern must have at least this many arguments. 88 * @param max The pattern must have at most this many arguments. 89 * @param errorCode ICU error code in/out parameter. 90 * Must fulfill U_SUCCESS before the function call. 91 * Set to U_ILLEGAL_ARGUMENT_ERROR for bad argument syntax and 92 * too few or too many arguments. 93 * @stable ICU 57 94 */ SimpleFormatter(const UnicodeString & pattern,int32_t min,int32_t max,UErrorCode & errorCode)95 SimpleFormatter(const UnicodeString& pattern, int32_t min, int32_t max, 96 UErrorCode &errorCode) { 97 applyPatternMinMaxArguments(pattern, min, max, errorCode); 98 } 99 100 /** 101 * Copy constructor. 102 * @stable ICU 57 103 */ SimpleFormatter(const SimpleFormatter & other)104 SimpleFormatter(const SimpleFormatter& other) 105 : compiledPattern(other.compiledPattern) {} 106 107 /** 108 * Assignment operator. 109 * @stable ICU 57 110 */ 111 SimpleFormatter &operator=(const SimpleFormatter& other); 112 113 /** 114 * Destructor. 115 * @stable ICU 57 116 */ 117 ~SimpleFormatter(); 118 119 /** 120 * Changes this object according to the new pattern. 121 * 122 * @param pattern The pattern string. 123 * @param errorCode ICU error code in/out parameter. 124 * Must fulfill U_SUCCESS before the function call. 125 * Set to U_ILLEGAL_ARGUMENT_ERROR for bad argument syntax. 126 * @return true if U_SUCCESS(errorCode). 127 * @stable ICU 57 128 */ applyPattern(const UnicodeString & pattern,UErrorCode & errorCode)129 UBool applyPattern(const UnicodeString &pattern, UErrorCode &errorCode) { 130 return applyPatternMinMaxArguments(pattern, 0, INT32_MAX, errorCode); 131 } 132 133 /** 134 * Changes this object according to the new pattern. 135 * The number of arguments checked against the given limits is the 136 * highest argument number plus one, not the number of occurrences of arguments. 137 * 138 * @param pattern The pattern string. 139 * @param min The pattern must have at least this many arguments. 140 * @param max The pattern must have at most this many arguments. 141 * @param errorCode ICU error code in/out parameter. 142 * Must fulfill U_SUCCESS before the function call. 143 * Set to U_ILLEGAL_ARGUMENT_ERROR for bad argument syntax and 144 * too few or too many arguments. 145 * @return true if U_SUCCESS(errorCode). 146 * @stable ICU 57 147 */ 148 UBool applyPatternMinMaxArguments(const UnicodeString &pattern, 149 int32_t min, int32_t max, UErrorCode &errorCode); 150 151 /** 152 * @return The max argument number + 1. 153 * @stable ICU 57 154 */ getArgumentLimit()155 int32_t getArgumentLimit() const { 156 return getArgumentLimit(compiledPattern.getBuffer(), compiledPattern.length()); 157 } 158 159 /** 160 * Formats the given value, appending to the appendTo builder. 161 * The argument value must not be the same object as appendTo. 162 * getArgumentLimit() must be at most 1. 163 * 164 * @param value0 Value for argument {0}. 165 * @param appendTo Gets the formatted pattern and value appended. 166 * @param errorCode ICU error code in/out parameter. 167 * Must fulfill U_SUCCESS before the function call. 168 * @return appendTo 169 * @stable ICU 57 170 */ 171 UnicodeString &format( 172 const UnicodeString &value0, 173 UnicodeString &appendTo, UErrorCode &errorCode) const; 174 175 /** 176 * Formats the given values, appending to the appendTo builder. 177 * An argument value must not be the same object as appendTo. 178 * getArgumentLimit() must be at most 2. 179 * 180 * @param value0 Value for argument {0}. 181 * @param value1 Value for argument {1}. 182 * @param appendTo Gets the formatted pattern and values appended. 183 * @param errorCode ICU error code in/out parameter. 184 * Must fulfill U_SUCCESS before the function call. 185 * @return appendTo 186 * @stable ICU 57 187 */ 188 UnicodeString &format( 189 const UnicodeString &value0, 190 const UnicodeString &value1, 191 UnicodeString &appendTo, UErrorCode &errorCode) const; 192 193 /** 194 * Formats the given values, appending to the appendTo builder. 195 * An argument value must not be the same object as appendTo. 196 * getArgumentLimit() must be at most 3. 197 * 198 * @param value0 Value for argument {0}. 199 * @param value1 Value for argument {1}. 200 * @param value2 Value for argument {2}. 201 * @param appendTo Gets the formatted pattern and values appended. 202 * @param errorCode ICU error code in/out parameter. 203 * Must fulfill U_SUCCESS before the function call. 204 * @return appendTo 205 * @stable ICU 57 206 */ 207 UnicodeString &format( 208 const UnicodeString &value0, 209 const UnicodeString &value1, 210 const UnicodeString &value2, 211 UnicodeString &appendTo, UErrorCode &errorCode) const; 212 213 /** 214 * Formats the given values, appending to the appendTo string. 215 * 216 * @param values The argument values. 217 * An argument value must not be the same object as appendTo. 218 * Can be nullptr if valuesLength==getArgumentLimit()==0. 219 * @param valuesLength The length of the values array. 220 * Must be at least getArgumentLimit(). 221 * @param appendTo Gets the formatted pattern and values appended. 222 * @param offsets offsets[i] receives the offset of where 223 * values[i] replaced pattern argument {i}. 224 * Can be shorter or longer than values. Can be nullptr if offsetsLength==0. 225 * If there is no {i} in the pattern, then offsets[i] is set to -1. 226 * @param offsetsLength The length of the offsets array. 227 * @param errorCode ICU error code in/out parameter. 228 * Must fulfill U_SUCCESS before the function call. 229 * @return appendTo 230 * @stable ICU 57 231 */ 232 UnicodeString &formatAndAppend( 233 const UnicodeString *const *values, int32_t valuesLength, 234 UnicodeString &appendTo, 235 int32_t *offsets, int32_t offsetsLength, UErrorCode &errorCode) const; 236 237 /** 238 * Formats the given values, replacing the contents of the result string. 239 * May optimize by actually appending to the result if it is the same object 240 * as the value corresponding to the initial argument in the pattern. 241 * 242 * @param values The argument values. 243 * An argument value may be the same object as result. 244 * Can be nullptr if valuesLength==getArgumentLimit()==0. 245 * @param valuesLength The length of the values array. 246 * Must be at least getArgumentLimit(). 247 * @param result Gets its contents replaced by the formatted pattern and values. 248 * @param offsets offsets[i] receives the offset of where 249 * values[i] replaced pattern argument {i}. 250 * Can be shorter or longer than values. Can be nullptr if offsetsLength==0. 251 * If there is no {i} in the pattern, then offsets[i] is set to -1. 252 * @param offsetsLength The length of the offsets array. 253 * @param errorCode ICU error code in/out parameter. 254 * Must fulfill U_SUCCESS before the function call. 255 * @return result 256 * @stable ICU 57 257 */ 258 UnicodeString &formatAndReplace( 259 const UnicodeString *const *values, int32_t valuesLength, 260 UnicodeString &result, 261 int32_t *offsets, int32_t offsetsLength, UErrorCode &errorCode) const; 262 263 /** 264 * Returns the pattern text with none of the arguments. 265 * Like formatting with all-empty string values. 266 * @stable ICU 57 267 */ getTextWithNoArguments()268 UnicodeString getTextWithNoArguments() const { 269 return getTextWithNoArguments( 270 compiledPattern.getBuffer(), 271 compiledPattern.length(), 272 nullptr, 273 0); 274 } 275 276 #ifndef U_HIDE_INTERNAL_API 277 /** 278 * Returns the pattern text with none of the arguments. 279 * Like formatting with all-empty string values. 280 * 281 * TODO(ICU-20406): Replace this with an Iterator interface. 282 * 283 * @param offsets offsets[i] receives the offset of where {i} was located 284 * before it was replaced by an empty string. 285 * For example, "a{0}b{1}" produces offset 1 for i=0 and 2 for i=1. 286 * Can be nullptr if offsetsLength==0. 287 * If there is no {i} in the pattern, then offsets[i] is set to -1. 288 * @param offsetsLength The length of the offsets array. 289 * 290 * @internal 291 */ getTextWithNoArguments(int32_t * offsets,int32_t offsetsLength)292 UnicodeString getTextWithNoArguments(int32_t *offsets, int32_t offsetsLength) const { 293 return getTextWithNoArguments( 294 compiledPattern.getBuffer(), 295 compiledPattern.length(), 296 offsets, 297 offsetsLength); 298 } 299 #endif // U_HIDE_INTERNAL_API 300 301 private: 302 /** 303 * Binary representation of the compiled pattern. 304 * Index 0: One more than the highest argument number. 305 * Followed by zero or more arguments or literal-text segments. 306 * 307 * An argument is stored as its number, less than ARG_NUM_LIMIT. 308 * A literal-text segment is stored as its length (at least 1) offset by ARG_NUM_LIMIT, 309 * followed by that many chars. 310 */ 311 UnicodeString compiledPattern; 312 getArgumentLimit(const char16_t * compiledPattern,int32_t compiledPatternLength)313 static inline int32_t getArgumentLimit(const char16_t *compiledPattern, 314 int32_t compiledPatternLength) { 315 return compiledPatternLength == 0 ? 0 : compiledPattern[0]; 316 } 317 318 static UnicodeString getTextWithNoArguments( 319 const char16_t *compiledPattern, 320 int32_t compiledPatternLength, 321 int32_t *offsets, 322 int32_t offsetsLength); 323 324 static UnicodeString &format( 325 const char16_t *compiledPattern, int32_t compiledPatternLength, 326 const UnicodeString *const *values, 327 UnicodeString &result, const UnicodeString *resultCopy, UBool forbidResultAsValue, 328 int32_t *offsets, int32_t offsetsLength, 329 UErrorCode &errorCode); 330 331 // Give access to internals to SimpleModifier for number formatting 332 friend class number::impl::SimpleModifier; 333 }; 334 335 U_NAMESPACE_END 336 337 #endif /* U_SHOW_CPLUSPLUS_API */ 338 339 #endif // __SIMPLEFORMATTER_H__ 340