• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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