/*
-* Copyright (C) 1997-2006, 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/format.h"
#include "unicode/locid.h"
#include "unicode/parseerr.h"
+#include "unicode/uchar.h"
U_NAMESPACE_BEGIN
* 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
* \code
* messageFormatPattern := string ( "{" messageFormatElement "}" string )*
*
- * messageFormatElement := argumentIndex { "," elementFormat }
+ * messageFormatElement := argumentIndex | argumentName { "," elementFormat }
*
* elementFormat := "time" { "," datetimeStyle }
* | "date" { "," datetimeStyle }
* | numberFormatPattern
*
* choiceStyle := choiceFormatPattern
+ *
+ * pluralStyle := pluralFormatPattern
* \endcode
* </pre>
* If there is no elementFormat, then the argument must be a string,
* @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);
/**
*/
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
* @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
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.
*
* @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,
*/
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
UnicodeString fPattern;
Format** formatAliases; // see getFormats
int32_t formatAliasesCapacity;
+ UProperty idStart;
+ UProperty idContinue;
MessageFormat(); // default constructor not implemented
* 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
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);
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,
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
};