]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/unicode/msgfmt.h
ICU-400.42.tar.gz
[apple/icu.git] / icuSources / i18n / unicode / msgfmt.h
index 3fa678fd1a27b7d2691a9d3566a7eb7a14262e8b..67e17cf0ef8ca2035075e2c868522a1fc057d497 100644 (file)
@@ -1,5 +1,5 @@
 /*
-* Copyright (C) {1997-2003}, International Business Machines Corporation and others. All Rights Reserved.
+* Copyright (C) 2007-2008, International Business Machines Corporation and others. All Rights Reserved.
 ********************************************************************************
 *
 * File MSGFMT.H
 
 #include "unicode/utypes.h"
 
+/**
+ * \file 
+ * \brief C++ API: Formats messages in a language-neutral way.
+ */
 #if !UCONFIG_NO_FORMATTING
 
 #include "unicode/format.h"
 #include "unicode/locid.h"
 #include "unicode/parseerr.h"
+#include "unicode/uchar.h"
 
 U_NAMESPACE_BEGIN
 
@@ -31,6 +37,7 @@ class NumberFormat;
 class DateFormat;
 
 /**
+ *
  * A MessageFormat produces concatenated messages in a
  * language-neutral way.  It should be used for all string
  * concatenations that are visible to end users.
@@ -52,6 +59,42 @@ class DateFormat;
  * formats it into a string.  The resultant strings are then assembled
  * within the string template of the MessageFormat to produce the
  * final output string.
+ * <p>
+ * <strong>Note:</strong>
+ * In ICU 4.0 MessageFormat supports named arguments.  If a named argument
+ * is used, all arguments must be named.  Names start with a character in 
+ * <code>UCHAR_ID_START</code> and continue with characters in 
+ * <code>UCHARID_CONTINUE</code>, in particular they do not start with a digit.
+ * If named arguments are used, {@link #usesNamedArguments()} will return true.
+ * <p>
+ * The other new methods supporting named arguments are 
+ * {@link #getFormatNames(UErrorCode& status)},
+ * {@link #getFormat(const UnicodeString& formatName, UErrorCode& status)}
+ * {@link #setFormat(const UnicodeString& formatName, const Format& format, UErrorCode& status)},
+ * {@link #adoptFormat(const UnicodeString& formatName, Format* formatToAdopt, UErrorCode& status)},
+ * {@link #format(const Formattable* arguments, const UnicodeString *argumentNames, int32_t cnt, UnicodeString& appendTo, FieldPosition& status, int32_t recursionProtection, UErrorCode& success)},
+ * {@link #format(const UnicodeString* argumentNames, const Formattable* arguments, int32_t count, UnicodeString& appendTo,UErrorCode& status)}.
+ * These methods are all compatible with patterns that do not used named arguments-- 
+ * in these cases the keys in the input or output use <code>UnicodeString</code>s 
+ * that name the argument indices, e.g. "0", "1", "2"... etc.
+ * <p>
+ * When named arguments are used, certain methods on MessageFormat that take or
+ * return arrays do not perform any action, since it is not possible to
+ * identify positions in an array using a name.  UErrorCode is set to
+ * U_ARGUMENT_TYPE_MISMATCH if there is a status/success field in the method.
+ * These methods are 
+ * {@link #adoptFormats(Format** newFormats, int32_t count)},
+ * {@link #setFormats(const Format** newFormats,int32_t count)},
+ * {@link #adoptFormat(int32_t n, Format *newFormat)},
+ * {@link #getFormats(int32_t& cnt)},
+ * {@link #format(const Formattable* source,int32_t cnt,UnicodeString& appendTo, FieldPosition& ignore, UErrorCode& success)},
+ * {@link #format(const UnicodeString& pattern,const Formattable* arguments,int32_t cnt,UnicodeString& appendTo,UErrorCode& success)},
+ * {@link #format(const Formattable& source, UnicodeString& appendTo,FieldPosition& ignore, UErrorCode& success)},
+ * {@link #format(const Formattable* arguments, int32_t cnt, UnicodeString& appendTo, FieldPosition& status, int32_t recursionProtection,UErrorCode& success)},
+ * {@link #parse(const UnicodeString& source, ParsePosition& pos,int32_t& count)},
+ * {@link #parse(const UnicodeString& source, int32_t& cnt, UErrorCode& status)}
+ * <p>
+ *
  * <P>
  * During parsing, an input string is matched against the string
  * template of the MessageFormat to produce an array of Formattable
@@ -141,7 +184,7 @@ class DateFormat;
  *  \code
  *       messageFormatPattern := string ( "{" messageFormatElement "}" string )*
  *
- *       messageFormatElement := argumentIndex { "," elementFormat }
+ *       messageFormatElement := argumentIndex | argumentName { "," elementFormat }
  *
  *       elementFormat := "time" { "," datetimeStyle }
  *                      | "date" { "," datetimeStyle }
@@ -160,6 +203,8 @@ class DateFormat;
  *                      | numberFormatPattern
  *
  *       choiceStyle :=   choiceFormatPattern
+ * 
+ *       pluralStyle := pluralFormatPattern
  * \endcode
  * </pre>
  * If there is no elementFormat, then the argument must be a string,
@@ -179,6 +224,21 @@ class DateFormat;
  * If a pattern is used, then unquoted braces in the pattern, if any,
  * must match: that is, "ab {0} de" and "ab '}' de" are ok, but "ab
  * {0'}' de" and "ab } de" are not.
+ * <p>
+ * <dl><dt><b>Warning:</b><dd>The rules for using quotes within message
+ * format patterns unfortunately have shown to be somewhat confusing.
+ * In particular, it isn't always obvious to localizers whether single
+ * quotes need to be doubled or not. Make sure to inform localizers about
+ * the rules, and tell them (for example, by using comments in resource
+ * bundle source files) which strings will be processed by MessageFormat.
+ * Note that localizers may need to use single quotes in translated
+ * strings where the original version doesn't have them.
+ * <br>Note also that the simplest way to avoid the problem is to
+ * use the real apostrophe (single quote) character U+2019 (') for
+ * human-readable text, and to use the ASCII apostrophe (U+0027 ' )
+ * only in program syntax, like quoting in MessageFormat.
+ * See the annotations for U+0027 Apostrophe in The Unicode Standard.</p>
+ * </dl>
  * <P>
  * The argumentIndex is a non-negative integer, which corresponds to the
  * index of the arguments presented in an array to be formatted.  The
@@ -227,7 +287,7 @@ class DateFormat;
  * the string patterns), then be careful not to produce a format that
  * recurses on itself, which will cause an infinite loop.
  * <P>
- * <EM>Note:<EM>Subformats are numbered by their order in the pattern.
+ * <EM>Note:</EM> Subformats are numbered by their order in the pattern.
  * This is <EM>not</EM> the same as the argumentIndex.
  * <pre>
  * \code
@@ -238,6 +298,10 @@ class DateFormat;
  *    format2 affects the second variable {0}
  * \endcode
  * </pre>
+ *
+ * <p><em>User subclasses are not supported.</em> While clients may write
+ * subclasses, such code will not necessarily work and will not be
+ * guaranteed to work stably from release to release.
  */
 class U_I18N_API MessageFormat : public Format {
 public:
@@ -402,7 +466,7 @@ public:
      * @param newFormats the new format to be set.
      * @param cnt        the size of the array.
      */
-    virtual void setFormats(const Format** newFormats,int32_t cnt);
+    virtual void setFormats(const Format** newFormats, int32_t cnt);
 
 
     /**
@@ -428,6 +492,63 @@ public:
      */
     virtual void setFormat(int32_t formatNumber, const Format& format);
 
+    /**
+     * Gets format names. This function returns formatNames in StringEnumerations
+     * which can be used with getFormat() and setFormat() to export formattable 
+     * array from current MessageFormat to another.  It is caller's resposibility 
+     * to delete the returned formatNames.
+     * @param status  output param set to success/failure code.
+     * @draft ICU 4.0
+     */
+    virtual StringEnumeration* getFormatNames(UErrorCode& status);
+    
+    /**
+     * Gets subformat pointer for given format name.   
+     * This function supports both named and numbered
+     * arguments-- if numbered, the formatName is the
+     * corresponding UnicodeStrings (e.g. "0", "1", "2"...).
+     * The returned Format object should not be deleted by the caller,
+     * nor should the ponter of other object .  The pointer and its 
+     * contents remain valid only until the next call to any method
+     * of this class is made with this object. 
+     * @param formatName the name or number specifying a format
+     * @param status  output param set to success/failure code.
+     * @draft ICU 4.0
+     */
+    virtual Format* getFormat(const UnicodeString& formatName, UErrorCode& status);
+    
+    /**
+     * Sets one subformat for given format name.
+     * See the class description about format name. 
+     * This function supports both named and numbered
+     * arguments-- if numbered, the formatName is the
+     * corresponding UnicodeStrings (e.g. "0", "1", "2"...).
+     * If there is no matched formatName or wrong type,
+     * the item will be ignored.
+     * @param formatName  Name of the subformat.
+     * @param format      the format to be set.
+     * @param status  output param set to success/failure code.
+     * @draft ICU 4.0
+     */
+    virtual void setFormat(const UnicodeString& formatName, const Format& format, UErrorCode& status);
+    
+    /**
+     * Sets one subformat for given format name.
+     * See the class description about format name. 
+     * This function supports both named and numbered
+     * arguments-- if numbered, the formatName is the
+     * corresponding UnicodeStrings (e.g. "0", "1", "2"...).
+     * If there is no matched formatName or wrong type,
+     * the item will be ignored.
+     * The caller should not delete the Format object after this call.
+     * @param formatName  Name of the subformat.
+     * @param formatToAdopt  Format to be adopted.
+     * @param status      output param set to success/failure code.
+     * @draft ICU 4.0
+     */
+    virtual void adoptFormat(const UnicodeString& formatName, Format* formatToAdopt, UErrorCode& status);
+
+
     /**
      * Gets an array of subformats of this object.  The returned array
      * should not be deleted by the caller, nor should the pointers
@@ -475,11 +596,11 @@ public:
      * @return          Reference to 'appendTo' parameter.
      * @stable ICU 2.0
      */
-    static UnicodeString& format(   const UnicodeString& pattern,
-                                    const Formattable* arguments,
-                                    int32_t count,
-                                    UnicodeString& appendTo,
-                                    UErrorCode& status);
+    static UnicodeString& format(const UnicodeString& pattern,
+                                 const Formattable* arguments,
+                                 int32_t count,
+                                 UnicodeString& appendTo,
+                                 UErrorCode& status);
 
     /**
      * Formats the given array of arguments into a user-readable
@@ -520,7 +641,31 @@ public:
     UnicodeString& format(const Formattable& obj,
                           UnicodeString& appendTo,
                           UErrorCode& status) const;
+    
 
+    /**
+     * Formats the given array of arguments into a user-defined argument name
+     * array. This function supports both named and numbered
+     * arguments-- if numbered, the formatName is the
+     * corresponding UnicodeStrings (e.g. "0", "1", "2"...).
+     *
+     * @param argumentNames argument name array
+     * @param arguments An array of objects to be formatted.
+     * @param count     The number of elements of 'argumentNames' and 
+     *                  arguments.  The number of argumentNames and arguments
+     *                  must be the same.
+     * @param appendTo  Output parameter to receive result.
+     *                  Result is appended to existing contents.
+     * @param status    Input/output error code.  If the
+     *                  pattern cannot be parsed, set to failure code.
+     * @return          Reference to 'appendTo' parameter.
+     * @stable ICU 4.0
+     */
+    UnicodeString& format(const UnicodeString* argumentNames,
+                          const Formattable* arguments,
+                          int32_t count,
+                          UnicodeString& appendTo,
+                          UErrorCode& status) const;
     /**
      * Parses the given string into an array of output arguments.
      *
@@ -544,9 +689,12 @@ public:
      * @param source    String to be parsed.
      * @param count     Output param to receive size of returned array.
      * @param status    Input/output error code.  If the
-     *                  pattern cannot be parsed, set to failure code.
+     *                  pattern cannot be parsed, set to failure code. 
+     *                  If the MessageFormat is named argument, the status is 
+     *                  set to U_ARGUMENT_TYPE_MISMATCH.
      * @return an array of parsed arguments.  The caller owns both
-     * the array and its contents.
+     * the array and its contents. Return NULL if status is not U_ZERO_ERROR.
+     * 
      * @stable ICU 2.0
      */
     virtual Formattable* parse( const UnicodeString& source,
@@ -569,6 +717,37 @@ public:
                              Formattable& result,
                              ParsePosition& pos) const;
 
+    /**
+     * Convert an 'apostrophe-friendly' pattern into a standard
+     * pattern.  Standard patterns treat all apostrophes as
+     * quotes, which is problematic in some languages, e.g. 
+     * French, where apostrophe is commonly used.  This utility
+     * assumes that only an unpaired apostrophe immediately before
+     * a brace is a true quote.  Other unpaired apostrophes are paired,
+     * and the resulting standard pattern string is returned.
+     *
+     * <p><b>Note</b> it is not guaranteed that the returned pattern
+     * is indeed a valid pattern.  The only effect is to convert
+     * between patterns having different quoting semantics.
+     *
+     * @param pattern the 'apostrophe-friendly' patttern to convert
+     * @param status    Input/output error code.  If the pattern
+     *                  cannot be parsed, the failure code is set.
+     * @return the standard equivalent of the original pattern
+     * @stable ICU 3.4
+     */
+    static UnicodeString autoQuoteApostrophe(const UnicodeString& pattern, 
+        UErrorCode& status);
+    
+    /**
+     * Returns true if this MessageFormat uses named arguments,
+     * and false otherwise.  See class description.
+     *
+     * @return true if named arguments are used.
+     * @draft ICU 4.0
+     */
+    UBool usesNamedArguments() const;
+    
     /**
      * Returns a unique class ID POLYMORPHICALLY.  Pure virtual override.
      * This method is to implement a simple version of RTTI, since not all
@@ -593,70 +772,27 @@ public:
      * @return          The class ID for all objects of this class.
      * @stable ICU 2.0
      */
-    static inline UClassID getStaticClassID(void);
+    static UClassID U_EXPORT2 getStaticClassID(void);
     
 private:
-    static const char fgClassID;
 
     Locale              fLocale;
     UnicodeString       fPattern;
     Format**            formatAliases; // see getFormats
     int32_t             formatAliasesCapacity;
+    UProperty           idStart;
+    UProperty           idContinue;
 
     MessageFormat(); // default constructor not implemented
 
-    /**
+    /*
      * A structure representing one subformat of this MessageFormat.
      * Each subformat has a Format object, an offset into the plain
      * pattern text fPattern, and an argument number.  The argument
      * number corresponds to the array of arguments to be formatted.
      * @internal
      */
-    class Subformat {
-    public:
-        /**
-         * @internal 
-         */
-        Format* format; // formatter
-        /**
-         * @internal 
-         */
-        int32_t offset; // offset into fPattern
-        /**
-         * @internal 
-         */
-        int32_t arg;    // 0-based argument number
-
-        /**
-         * Clone that.format and assign it to this.format
-         * Do NOT delete this.format
-         * @internal
-         */
-        Subformat& operator=(const Subformat& that) {
-            format = that.format ? that.format->clone() : NULL;
-            offset = that.offset;
-            arg = that.arg;
-            return *this;
-        }
-
-        /**
-         * @internal 
-         */
-        UBool operator==(const Subformat& that) const {
-            // Do cheap comparisons first
-            return offset == that.offset &&
-                   arg == that.arg &&
-                   ((format == that.format) || // handles NULL
-                    (*format == *that.format));
-        }
-
-        /**
-         * @internal
-         */
-        UBool operator!=(const Subformat& that) const {
-            return !operator==(that);
-        }
-    };
+    class Subformat;
 
     /**
      * A MessageFormat contains an array of subformats.  This array
@@ -678,6 +814,12 @@ private:
     int32_t            argTypeCount;
     int32_t            argTypeCapacity;
 
+    /**
+      * Is true iff all argument names are non-negative numbers.
+      * 
+      */
+    UBool isArgNumeric;
+
     // Variable-size array management
     UBool allocateSubformats(int32_t capacity);
     UBool allocateArgTypes(int32_t capacity);
@@ -730,6 +872,14 @@ private:
                             FieldPosition& status,
                             int32_t recursionProtection,
                             UErrorCode& success) const;
+    
+    UnicodeString&  format( const Formattable* arguments, 
+                            const UnicodeString *argumentNames,
+                            int32_t cnt,
+                            UnicodeString& appendTo,
+                            FieldPosition& status,
+                            int32_t recursionProtection,
+                            UErrorCode& success) const;
 
     void             makeFormat(int32_t offsetNumber,
                                 UnicodeString* segments,
@@ -764,19 +914,17 @@ private:
         listCount = argTypeCount;
         return argTypes; 
     }
-
+    
+    /**
+     * Returns FALSE if the argument name is not legal.
+     * @param  argName   argument name.
+     * @return TRUE if the argument name is legal, otherwise return FALSE.
+     */
+    UBool isLegalArgName(const UnicodeString& argName) const;
+    
     friend class MessageFormatAdapter; // getFormatTypeList() access
 };
 
-inline UClassID
-MessageFormat::getStaticClassID(void)
-{ return (UClassID)&fgClassID; }
-
-inline UClassID
-MessageFormat::getDynamicClassID() const
-{ return MessageFormat::getStaticClassID(); }
-
-
 inline UnicodeString&
 MessageFormat::format(const Formattable& obj,
                       UnicodeString& appendTo,
@@ -789,3 +937,4 @@ U_NAMESPACE_END
 
 #endif // _MSGFMT
 //eof
+