/* ******************************************************************************** * * * COPYRIGHT: * * (C) Copyright Taligent, Inc., 1997 * * (C) Copyright International Business Machines Corporation, 1997 * * Licensed Material - Program-Property of IBM - All Rights Reserved. * * US Government Users Restricted Rights - Use, duplication, or disclosure * * restricted by GSA ADP Schedule Contract with IBM Corp. * * * ******************************************************************************** * * File MSGFMT.H * * Modification History: * * Date Name Description * 02/19/97 aliu Converted from java. * 03/20/97 helena Finished first cut of implementation. ******************************************************************************** */ // ***************************************************************************** // This file was generated from the java source file MessageFormat.java // ***************************************************************************** #ifndef _MSGFMT #define _MSGFMT #include "format.h" #include "ptypes.h" #include "locid.h" class NumberFormat; /** * Provides means to produce concatenated messages in language-neutral way. * Use this for all concatenations that show up to end users. *
* Takes a set of objects, formats them, then inserts the formatted * strings into the pattern at the appropriate places. *
* Here are some examples of usage: *
* . GregorianCalendar cal;
* . Formattable arguments[] = {
* . 7L,
* . Formattable(Date(cal.getTime()), Formattable::kIsDate),
* . "a disturbance in the Force"
* . };
* .
* . String result = MessageFormat::format(
* . "At {1,time} on {1,date}, there was {2} on planet {0,integer}.",
* . arguments);
* .
* . <output>: At 12:30 PM on Jul 3, 2053, there was a disturbance
* . in the Force on planet 7.
*
* Typically, the message format will come from resources, and the
* arguments will be dynamically set at runtime.
*
* Example 2:
* .
* . Formattable testArgs[] = {3L, "MyDisk"};
*
* . MessageFormat* form = new MessageFormat(
* . "The disk \"{1}\" contains {0} file(s).");
* .
* . UnicodeString string;
* . cout << form->format(testArgs, string) << endl;
* .
* . // output, with different testArgs
* . output: The disk "MyDisk" contains 0 file(s).
* . output: The disk "MyDisk" contains 1 file(s).
* . output: The disk "MyDisk" contains 1,273 file(s).
*
*
* The pattern is of the following form. Legend:
*
* . {optional item}
* . (group that may be repeated)*
*
* Do not confuse optional items with items inside quotes braces, such
* as this: "{". Quoted braces are literals.
*
* . messageFormatPattern := string ( "{" messageFormatElement "}" string )*
* .
* . messageFormatElement := argument { "," elementFormat }
* .
* . elementFormat := "time" { "," datetimeStyle }
* . | "date" { "," datetimeStyle }
* . | "number" { "," numberStyle }
* . | "choice" "," choiceStyle
* .
* . datetimeStyle := "short"
* . | "medium"
* . | "long"
* . | "full"
* . | dateFormatPattern
* .
* . numberStyle := "currency"
* . | "percent"
* . | "integer"
* . | numberFormatPattern
* .
* . choiceStyle := choiceFormatPattern
*
* If there is no elementFormat, then the argument must be a string,
* which is substituted. If there is no dateTimeStyle or numberStyle,
* then the default format is used (e.g. NumberFormat.getInstance(),
* DateFormat.getDefaultTime() or DateFormat.getDefaultDate(). For
* a ChoiceFormat, the pattern must always be specified, since there
* is no default.
* * In strings, single quotes can be used to quote the "{" sign if * necessary. A real single quote is represented by ''. Inside a * messageFormatElement, quotes are [not] removed. For example, * {1,number,$'#',##} will produce a number format with the pound-sign * quoted, with a result such as: "$#31,45". *
* 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. *
* The argument is a number from 0 to 9, which corresponds to the * arguments presented in an array to be formatted. *
* It is ok to have unused arguments in the array. With missing * arguments or arguments that are not of the right class for the * specified format, a failing ErrorCode result is set. *
* For more sophisticated patterns, you can use a ChoiceFormat to get * output such as: *
* . MessageFormat* form = new MessageFormat("The disk \"{1}\" contains {0}.");
* . double filelimits[] = {0,1,2};
* . UnicodeString filepart[] = {"no files","one file","{0,number} files"};
* . ChoiceFormat* fileform = new ChoiceFormat(filelimits, filepart, 3);
* . form->setFormat(1,fileform); // NOT zero, see below
* .
* . Formattable testArgs[] = {12373L, "MyDisk"};
* .
* . UnicodeString string;
* . cout << form->format(testArgs, string) << endl;
* .
* . // output, with different testArgs
* . output: The disk "MyDisk" contains no files.
* . output: The disk "MyDisk" contains one file.
* . output: The disk "MyDisk" contains 1,273 files.
*
* You can either do this programmatically, as in the above example,
* or by using a pattern (see ChoiceFormat for more information) as in:
*
* . form->applyPattern(
* . "There {0,choice,0#are no files|1#is one file|1<are {0,number,integer} files}.");
*
* * [Note:] As we see above, the string produced by a ChoiceFormat in * MessageFormat is treated specially; occurances of '{' are used to * indicated subformats, and cause recursion. If you create both a * MessageFormat and ChoiceFormat programmatically (instead of using * the string patterns), then be careful not to produce a format that * recurses on itself, which will cause an infinite loop. *
* [Note:] Formats are numbered by order of variable in the string. * This is [not] the same as the argument numbering! *
* . For example: with "abc{2}def{3}ghi{0}...",
* .
* . format0 affects the first variable {2}
* . format1 affects the second variable {3}
* . format2 affects the second variable {0}
*
* and so on.
*/
#ifdef NLS_MAC
#pragma export on
#endif
class T_FORMAT_API MessageFormat : public Format {
public:
enum EFormatNumber { MAX_FORMAT = 10 };
/**
* Construct a new MessageFormat using the given pattern.
*
* @param pattern Pattern used to construct object.
* @param status Output param to receive success code. If the
* pattern cannot be parsed, set to failure code.
*/
MessageFormat(const UnicodeString& pattern,
ErrorCode &status);
/**
* Copy constructor.
*/
MessageFormat(const MessageFormat&);
/**
* Assignment operator.
*/
const MessageFormat& operator=(const MessageFormat&);
/**
* Destructor.
*/
virtual ~MessageFormat();
/**
* Clone this Format object polymorphically. The caller owns the
* result and should delete it when done.
*/
virtual Format* clone() const;
/**
* Return true if the given Format objects are semantically equal.
* Objects of different subclasses are considered unequal.
*/
virtual t_bool operator==(const Format& other) const;
/**
* Return true if the given Format objects are not semantically equal.
* Objects of different subclasses are considered unequal.
*/
virtual t_bool operator!=(const Format& other) const;
/**
* Sets the locale. This locale is used for fetching default number or date
* format information.
*/
virtual void setLocale(const Locale& theLocale);
/**
* Gets the locale. This locale is used for fetching default number or date
* format information.
*/
virtual const Locale& getLocale() const;
/**
* Apply the given pattern string to this message format.
*
* @param pattern The pattern to be applied.
* @param status Output param set to success/failure code on
* exit. If the pattern is invalid, this will be
* set to a failure result.
*/
virtual void applyPattern(const UnicodeString& pattern,
ErrorCode& status);
/**
* Gets the pattern. See the class description.
*/
virtual UnicodeString& toPattern(UnicodeString& result) const;
/**
* Sets formats to use on parameters.
* See the class description about format numbering.
* The caller should not delete the Format objects after this call.
*/
virtual void adoptFormats(Format** formatsToAdopt, t_int32 count);
/**
* Sets formats to use on parameters.
* See the class description about format numbering.
*/
virtual void setFormats(const Format** newFormats,t_int32 cnt);
/**
* Sets formats individually to use on parameters.
* See the class description about format numbering.
* The caller should not delete the Format object after this call.
*/
virtual void adoptFormat(t_int32 formatNumber, Format* formatToAdopt);
/**
* Sets formats individually to use on parameters.
* See the class description about format numbering.
*/
virtual void setFormat(t_int32 variable, const Format& newFormat);
/**
* Gets formats that were set with setFormats.
* See the class description about format numbering.
*/
virtual const Format** getFormats(t_int32& count) const;
/**
* Returns pattern with formatted objects. Does not take ownership
* of the Formattable* array; just reads it and uses it to generate
* the format string.
*
* @param source An array of objects to be formatted & substituted.
* @param result Where text is appended.
* @param ignore No useful status is returned.
*/
UnicodeString& format( const Formattable* source,
t_int32 count,
UnicodeString& result,
FieldPosition& ignore,
ErrorCode& success) const;
/**
* Convenience routine. Avoids explicit creation of
* MessageFormat, but doesn't allow future optimizations.
*/
static UnicodeString& format( const UnicodeString& pattern,
const Formattable* arguments,
t_int32 count,
UnicodeString& result,
ErrorCode& success);
/**
* Format an object to produce a message. This method handles
* Formattable objects of type kArray. If the Formattable
* object type is not of type kArray, then it returns a failing
* ErrorCode.
*
* @param obj The object to format
* @param toAppendTo Where the text is to be appended
* @param pos On input: an alignment field, if desired.
* On output: the offsets of the alignment field.
* @param status Output param filled with success/failure status.
* @return The value passed in as toAppendTo (this allows chaining,
* as with UnicodeString::append())
*/
virtual UnicodeString& format(const Formattable& obj,
UnicodeString& toAppendTo,
FieldPosition& pos,
ErrorCode& status) const;
/**
* Parses the string.
* * Caveats: The parse may fail in a number of circumstances. For * example: *
* If one of the arguments does not occur in the pattern. *
* If the format of an argument is loses information, such as with * a choice format where a large number formats to "many". *
* Does not yet handle recursion (where the substituted strings * contain {n} references.) *
* Will not always find a match (or the correct match) if some * part of the parse is ambiguous. For example, if the pattern * "{1},{2}" is used with the string arguments {"a,b", "c"}, it * will format as "a,b,c". When the result is parsed, it will * return {"a", "b,c"}. *
* If a single argument is formatted twice in the string, then the * later parse wins. * * @param source String to be parsed. * @param status On input, starting position for parse. On output, * final position after parse. * @param count Output param to receive size of returned array. * @result Array of Formattable objects, with length * 'count', owned by the caller. */ virtual Formattable* parse( const UnicodeString& source, ParsePosition& status, t_int32& count) const; /** * Parses the string. Does not yet handle recursion (where * the substituted strings contain {n} references.) * * @param source String to be parsed. * @param count Output param to receive size of returned array. * @param status Output param to receive success/error code. * @result Array of Formattable objects, with length * 'count', owned by the caller. */ virtual Formattable* parse( const UnicodeString& source, t_int32& count, ErrorCode& status) const; /** * Parse a string to produce an object. This methods handles * parsing of message strings into arrays of Formattable objects. * Does not yet handle recursion (where the substituted strings * contain %n references.) *
* Before calling, set parse_pos.index to the offset you want to * start parsing at in the source. After calling, parse_pos.index * is the end of the text you parsed. If error occurs, index is * unchanged. *
* When parsing, leading whitespace is discarded (with successful * parse), while trailing whitespace is left as is. *
* See Format::parseObject() for more. * * @param source The string to be parsed into an object. * @param result Formattable to be set to the parse result. * If parse fails, return contents are undefined. * @param parse_pos The position to start parsing at. Upon return * this param is set to the position after the * last character successfully parsed. If the * source is not parsed successfully, this param * will remain unchanged. * @return A newly created Formattable* object, or NULL * on failure. The caller owns this and should * delete it when done. */ virtual void parseObject(const UnicodeString& source, Formattable& result, ParsePosition& parse_pos) const; public: /** * Returns a unique class ID POLYMORPHICALLY. Pure virtual override. * This method is to implement a simple version of RTTI, since not all * C++ compilers support genuine RTTI. Polymorphic operator==() and * clone() methods call this method. * * @return The class ID for this object. All objects of a * given class have the same class ID. Objects of * other classes have different class IDs. */ virtual ClassID getDynamicClassID() const; /** * Return the class ID for this class. This is useful only for * comparing to a return value from getDynamicClassID(). For example: *
* . Base* polymorphic_pointer = createPolymorphicObject();
* . if (polymorphic_pointer->getDynamicClassID() ==
* . Derived::getStaticClassID()) ...
*
* @return The class ID for all objects of this class.
*/
static ClassID getStaticClassID() { return (ClassID)&fgClassID; }
private:
static char fgClassID;
static NumberFormat* fgNumberFormat;
Locale locale;
UnicodeString pattern;
// later, allow more than ten items
Format *formats[MAX_FORMAT];
t_int32 *offsets;
t_int32 count;
t_int32 *argumentNumbers;
t_int32 maxOffset;
UnicodeString buffer;
/**
* Internal routine used by format.
* @param recursionProtection Initially zero. Bits 0..9 are used to indicate
* that a parameter has already been seen, to avoid recursion. Currently
* unused.
*/
static const int LIST_LENGTH;
static const UnicodeString typeList[];
static const UnicodeString modifierList[];
static const UnicodeString dateModifierList[];
/**
* Internal ctor that allows the locale specification.
* @param pattern Pattern used to construct object.
* @param newLocale the new locale.
* @param status Output param to receive success code. If the
* pattern cannot be parsed, set to failure code.
*/
MessageFormat(const UnicodeString& pattern,
const Locale& newLocale,
ErrorCode& success);
/**
* Finds the word s, in the keyword list and returns the located index.
* @param s the keyword to be searched for.
* @param list the list of keywords to be searched with.
* @return the index of the list which matches the keyword s.
*/
static int findKeyword( const UnicodeString& s,
const UnicodeString* list);
/**
* Formats the array of arguments and copies the result into the result buffer,
* updates the field position.
* @param arguments the formattable objects array.
* @param cnt the array count.
* @param status field position status.
* @param recursionProtection Initially zero. Bits 0..9 are used to indicate
* that a parameter has already been seen, to avoid recursion. Currently
* unused.
* @param success the error code status.
*/
UnicodeString& format( const Formattable* arguments,
t_int32 cnt,
UnicodeString& result,
FieldPosition& status,
int recursionProtection,
ErrorCode& success) const;
/**
* Checks the segments for the closest matched format instance and
* updates the format array with the new format instance.
* @param position the last processed offset in the pattern
* @param offsetNumber the offset number of the last processed segment
* @param segments the string that contains the parsed pattern segments.
* @param success the error code
*/
void makeFormat( int position,
int offsetNumber,
UnicodeString* segments,
ErrorCode& success);
/**
* Checks the range of the source text to quote the special
* characters, { and ' and copy to target buffer.
* @param source
* @param start the text offset to start the process of in the source string
* @param end the text offset to end the process of in the source string
* @param target the result buffer
*/
static void copyAndFixQuotes(const UnicodeString& source, int start, int end, UnicodeString& target);
/**
* Converts a string to an integer value using a default NumberFormat object
* which is static (shared by all MessageFormat instances). This replaces
* a call to wtoi().
* @param string the source string to convert with
* @param status the error code.
* @return the converted number.
*/
static t_int32 stoi(const UnicodeString& string, ErrorCode& status);
};
#ifdef NLS_MAC
#pragma export off
#endif
inline ClassID
MessageFormat::getDynamicClassID() const
{
return MessageFormat::getStaticClassID();
}
inline t_bool
MessageFormat::operator!= (const Format& that) const
{
return !(*this == that);
}
#endif // _MSGFMT
//eof