1 /* 2 ****************************************************************************** 3 * Copyright (C) 2014, International Business Machines 4 * Corporation and others. All Rights Reserved. 5 ****************************************************************************** 6 * simplepatternformatter.h 7 */ 8 9 #ifndef __SIMPLEPATTERNFORMATTER_H__ 10 #define __SIMPLEPATTERNFORMATTER_H__ 11 12 #define EXPECTED_PLACEHOLDER_COUNT 3 13 14 #include "cmemory.h" 15 #include "unicode/utypes.h" 16 #include "unicode/unistr.h" 17 18 U_NAMESPACE_BEGIN 19 20 class SimplePatternFormatterPlaceholderValues; 21 22 struct PlaceholderInfo { 23 int32_t id; 24 int32_t offset; 25 }; 26 27 /** 28 * Compiled version of a pattern string such as "{1} was born in {0}". 29 * <p> 30 * Using SimplePatternFormatter is both faster and safer than adhoc replacement. 31 * They are faster because they are precompiled; they are safer because they 32 * account for curly braces escaped by apostrophe ('). 33 * 34 * Placeholders are of the form \{[0-9]+\}. If a curly brace is preceded 35 * by a single quote, it becomes a curly brace instead of the start of a 36 * placeholder. Two single quotes resolve to one single quote. 37 * <p> 38 * Example: 39 * <pre> 40 * SimplePatternFormatter fmt("{1} '{born} in {0}"); 41 * UnicodeString result; 42 * UErrorCode status = U_ZERO_ERROR; 43 * // Evaluates to: "paul {born} in england" 44 * fmt.format("england", "paul", result, status); 45 * </pre> 46 */ 47 class U_COMMON_API SimplePatternFormatter : public UMemory { 48 public: 49 /** 50 * Default constructor 51 */ 52 SimplePatternFormatter(); 53 54 /** 55 * Construct from a pattern. Will never fail if pattern has three or 56 * fewer placeholders in it. 57 */ 58 explicit SimplePatternFormatter(const UnicodeString& pattern); 59 60 /** 61 * Copy constructor. 62 */ 63 SimplePatternFormatter(const SimplePatternFormatter& other); 64 65 /** 66 * Assignment operator 67 */ 68 SimplePatternFormatter &operator=(const SimplePatternFormatter& other); 69 70 /** 71 * Destructor. 72 */ 73 ~SimplePatternFormatter(); 74 75 /** 76 * Compiles pattern and makes this object represent pattern. 77 * 78 * Returns TRUE on success; FALSE on failure. Will not fail if 79 * there are three or fewer placeholders in pattern. May fail with 80 * U_MEMORY_ALLOCATION_ERROR if there are more than three placeholders. 81 */ 82 UBool compile(const UnicodeString &pattern, UErrorCode &status); 83 84 /** 85 * Returns (maxPlaceholderId + 1). For example 86 * <code>SimplePatternFormatter("{0} {2}").getPlaceholderCount() 87 * evaluates to 3. 88 * Callers use this function to find out how many values this object 89 * expects when formatting. 90 */ getPlaceholderCount()91 int32_t getPlaceholderCount() const { 92 return placeholderCount; 93 } 94 95 /** 96 * Returns this pattern with none of the placeholders. 97 */ getPatternWithNoPlaceholders()98 const UnicodeString &getPatternWithNoPlaceholders() const { 99 return noPlaceholders; 100 } 101 102 /** 103 * Formats given value. arg0 cannot be appendTo. 104 */ 105 UnicodeString &format( 106 const UnicodeString &args0, 107 UnicodeString &appendTo, 108 UErrorCode &status) const; 109 110 /** 111 * Formats given values. Neither arg0 nor arg1 can be appendTo. 112 */ 113 UnicodeString &format( 114 const UnicodeString &args0, 115 const UnicodeString &args1, 116 UnicodeString &appendTo, 117 UErrorCode &status) const; 118 119 /** 120 * Formats given values. Neither arg0, arg1, nor arg2 can be appendTo. 121 */ 122 UnicodeString &format( 123 const UnicodeString &args0, 124 const UnicodeString &args1, 125 const UnicodeString &args2, 126 UnicodeString &appendTo, 127 UErrorCode &status) const; 128 129 /** 130 * Formats given values. 131 * 132 * The caller retains ownership of all pointers. 133 * @param placeholderValues 1st one corresponds to {0}; 2nd to {1}; 134 * 3rd to {2} etc. If any of these point to appendTo, this method 135 * sets status to U_ILLEGAL_ARGUMENT_ERROR. 136 * @param placeholderValueCount the number of placeholder values 137 * must be at least large enough to provide values for all placeholders 138 * in this object. Otherwise status set to U_ILLEGAL_ARGUMENT_ERROR. 139 * @param appendTo resulting string appended here. 140 * @param offsetArray The offset of each placeholder value in appendTo 141 * stored here. The first value gets the offset of the value for {0}; 142 * the 2nd for {1}; the 3rd for {2} etc. -1 means that the corresponding 143 * placeholder does not exist in this object. If caller is not 144 * interested in offsets, it may pass NULL and 0 for the length. 145 * @param offsetArrayLength the size of offsetArray. If less than 146 * placeholderValueCount only the first offsets get recorded. If 147 * greater than placeholderValueCount, then extra values in offset 148 * array are set to -1. 149 * @param status any error stored here. 150 */ 151 UnicodeString &formatAndAppend( 152 const UnicodeString * const *placeholderValues, 153 int32_t placeholderValueCount, 154 UnicodeString &appendTo, 155 int32_t *offsetArray, 156 int32_t offsetArrayLength, 157 UErrorCode &status) const; 158 159 /** 160 * Formats given values. 161 * 162 * The caller retains ownership of all pointers. 163 * @param placeholderValues 1st one corresponds to {0}; 2nd to {1}; 164 * 3rd to {2} etc. May include pointer to result in which case 165 * the previous value of result is used for the corresponding 166 * placeholder. 167 * @param placeholderValueCount the number of placeholder values 168 * must be at least large enough to provide values for all placeholders 169 * in this object. Otherwise status set to U_ILLEGAL_ARGUMENT_ERROR. 170 * @param result resulting string stored here overwriting any previous 171 * value. 172 * @param offsetArray The offset of each placeholder value in result 173 * stored here. The first value gets the offset of the value for {0}; 174 * the 2nd for {1}; the 3rd for {2} etc. -1 means that the corresponding 175 * placeholder does not exist in this object. If caller is not 176 * interested in offsets, it may pass NULL and 0 for the length. 177 * @param offsetArrayLength the size of offsetArray. If less than 178 * placeholderValueCount only the first offsets get recorded. If 179 * greater than placeholderValueCount, then extra values in offset 180 * array are set to -1. 181 * @param status any error stored here. 182 */ 183 UnicodeString &formatAndReplace( 184 const UnicodeString * const *placeholderValues, 185 int32_t placeholderValueCount, 186 UnicodeString &result, 187 int32_t *offsetArray, 188 int32_t offsetArrayLength, 189 UErrorCode &status) const; 190 private: 191 UnicodeString noPlaceholders; 192 MaybeStackArray<PlaceholderInfo, 3> placeholders; 193 int32_t placeholderSize; 194 int32_t placeholderCount; 195 UBool firstPlaceholderReused; 196 197 // A Placeholder value that is the same as appendTo is treated as the 198 // empty string. 199 UnicodeString &formatAndAppend( 200 const SimplePatternFormatterPlaceholderValues &placeholderValues, 201 UnicodeString &appendTo, 202 int32_t *offsetArray, 203 int32_t offsetArrayLength) const; 204 205 // Returns the placeholder at the beginning of this pattern 206 // (e.g 3 for placeholder {3}). Returns -1 if the beginning of pattern 207 // is text or if the placeholder at the beginning of this pattern 208 // is used again in the middle of the pattern. 209 int32_t getUniquePlaceholderAtStart() const; 210 211 // ensureCapacity ensures that the capacity of the placeholders array 212 // is desiredCapacity. If ensureCapacity must resize the placeholders 213 // array, the first placeholderSize elements stay in the array. Note 214 // that ensureCapcity NEVER changes the value of placeholderSize only 215 // the capacity of the placeholders array. 216 // If there is no memory allocation error when resizing, this 217 // function returns desiredCapacity. If there is a memory allocation 218 // error, this function leaves the placeholders array unchanged and 219 // returns the smaller, old capacity. ensureCapacity resizes only if 220 // the current capacity of placeholders array is less than desiredCapacity. 221 // Otherwise, it leaves the placeholders array unchanged. If caller 222 // specifies an allocation size, then it must be at least as large as 223 // desiredCapacity. In that case, if ensureCapacity resizes, it will 224 // allocate allocationSize spots instead of desiredCapacity spots in 225 // the array. If caller is calling ensureCapacity in a loop while adding 226 // elements, it is recommended that it use an allocationSize of 227 // approximately twice desiredCapacity to avoid memory allocation with 228 // every call to ensureCapacity. 229 int32_t ensureCapacity(int32_t desiredCapacity, int32_t allocationSize=0); 230 231 // Records the offset of an individual placeholder in the noPlaceholders 232 // string. 233 UBool addPlaceholder(int32_t id, int32_t offset); 234 }; 235 236 U_NAMESPACE_END 237 238 #endif 239