home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / include / choicfmt.h < prev    next >
C/C++ Source or Header  |  1999-11-12  |  17KB  |  431 lines

  1. /*
  2. ********************************************************************************
  3. *                                                                              *
  4. * COPYRIGHT:                                                                   *
  5. *   (C) Copyright Taligent, Inc.,  1997                                        *
  6. *   (C) Copyright International Business Machines Corporation,  1997-1999      *
  7. *   Copyright (C) 1999 Alan Liu and others. All rights reserved.               *
  8. *   Licensed Material - Program-Property of IBM - All Rights Reserved.         *
  9. *   US Government Users Restricted Rights - Use, duplication, or disclosure    *
  10. *   restricted by GSA ADP Schedule Contract with IBM Corp.                     *
  11. *                                                                              *
  12. ********************************************************************************
  13. *
  14. * File CHOICFMT.H
  15. *
  16. * Modification History:
  17. *
  18. *   Date        Name        Description
  19. *   02/19/97    aliu        Converted from java.
  20. *   03/20/97    helena      Finished first cut of implementation and got rid 
  21. *                           of nextDouble/previousDouble and replaced with
  22. *                           boolean array.
  23. *   4/10/97     aliu        Clean up.  Modified to work on AIX.
  24. *   8/6/97      nos         Removed overloaded constructor, member var 'buffer'.
  25. *    07/22/98    stephen        Removed operator!= (implemented in Format)
  26. ********************************************************************************
  27. */
  28.  
  29. #ifndef CHOICFMT_H
  30. #define CHOICFMT_H
  31.  
  32.  
  33. #include "utypes.h"
  34. #include "unistr.h"
  35. #include "numfmt.h"
  36. #include "fieldpos.h"
  37. #include "format.h"
  38.  
  39.  
  40. /**
  41.  * A ChoiceFormat allows you to attach a format to a range of numbers.
  42.  * It is generally used in a MessageFormat for doing things like plurals.
  43.  * The choice is specified with an ascending list of doubles, where each item
  44.  * specifies a half-open interval up to the next item:
  45.  * <pre>
  46.  * .    X matches j if and only if limit[j] <= X < limit[j+1]
  47.  * </pre>
  48.  * If there is no match, then either the first or last index is used, depending
  49.  * on whether the number is too low or too high.  The length of the array of
  50.  * formats must be the same as the length of the array of limits.
  51.  * For example,
  52.  * <pre>
  53.  * .     {1,2,3,4,5,6,7},
  54.  * .          {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"}
  55.  * .     {0, 1, ChoiceFormat::nextDouble(1)},
  56.  * .          {"no files", "one file", "many files"}
  57.  * </pre>
  58.  * (nextDouble can be used to get the next higher double, to make the half-open
  59.  * interval.)
  60.  * <P>
  61.  * Here is a simple example that shows formatting and parsing:
  62.  * <pre>
  63.  * .  void SimpleChoiceExample( void )
  64.  * .  {
  65.  * .      double limits[] = {1,2,3,4,5,6,7};
  66.  * .      UnicodeString monthNames[] = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"};
  67.  * .      ChoiceFormat* form = new ChoiceFormat(limits, monthNames, 7 );
  68.  * .      ParsePosition* status = new ParsePosition(0);
  69.  * .      UnicodeString str;
  70.  * .      FieldPosition f1(0), f2(0);
  71.  * .      for (double i = 0.0; i <= 8.0; ++i) {
  72.  * .          status->setIndex(0);
  73.  * .          Formattable parseResult;
  74.  * .          str.remove();
  75.  * .          cout << i << " -> " << form->format(i,str, f1) 
  76.  * .                    << " -> " << parseResult << endl;
  77.  * .      }
  78.  * .      delete form;
  79.  * .      delete status;
  80.  * .      cout << endl;
  81.  * .  }
  82.  * </pre>
  83.  * Here is a more complex example, with a pattern format.
  84.  * <pre>
  85.  * .  void ComplexChoiceExample( void )
  86.  * .  {
  87.  * .      double filelimits[] = {0,1,2};
  88.  * .      UnicodeString filepart[] = {"are no files","is one file","are {2} files"};
  89.  * .      ChoiceFormat* fileform = new ChoiceFormat(filelimits, filepart, 3 );
  90.  * .      UErrorCode success = U_ZERO_ERROR;
  91.  * .      const Format* testFormats[] = { fileform, NULL, NumberFormat::createInstance(success) };
  92.  * .      MessageFormat* pattform = new MessageFormat("There {0} on {1}", success );
  93.  * .      pattform->setFormats( testFormats, 3 );
  94.  * .      Formattable testArgs[] = {0L, "Disk_A", 0L};
  95.  * .      FieldPosition fp(0);
  96.  * .      UnicodeString str;
  97.  * .      for (int32_t i = 0; i < 4; ++i) {
  98.  * .          Formattable fInt(i);
  99.  * .          testArgs[0] = fInt;
  100.  * .          testArgs[2] = testArgs[0];
  101.  * .          str.remove();
  102.  * .          pattform->format(testArgs, 3, str, fp, success );
  103.  * .          cout << "Output for i=" << i << " : " << str << endl;
  104.  * .      }
  105.  * .      delete pattform;
  106.  * .      cout << endl;
  107.  * .  }
  108.  * </pre>
  109.  * ChoiceFormat objects may be converted to and from patterns.  The
  110.  * syntax of these patterns is [TODO fill in this section with detail].
  111.  * Here is an example of a ChoiceFormat pattern:
  112.  * <P>
  113.  * You can either do this programmatically, as in the above example,
  114.  * or by using a pattern (see ChoiceFormat for more information) as in:
  115.  * <pre>
  116.  * .       "0#are no files|1#is one file|1<are many files"
  117.  * </pre>
  118.  * Here the notation is:
  119.  * <pre>
  120.  * .       <number> "#"  Specifies a limit value.
  121.  * .       <number> "<"  Specifies a limit of nextDouble(<number>).
  122.  * .       <number> ">"  Specifies a limit of previousDouble(<number>).
  123.  * </pre>
  124.  * Each limit value is followed by a string, which is terminated by
  125.  * a vertical bar character ("|"), except for the last string, which
  126.  * is terminated by the end of the string.
  127.  */
  128. class U_I18N_API ChoiceFormat: public NumberFormat {
  129. public:
  130.     /**
  131.      * Construct a new ChoiceFormat with the limits and the corresponding formats
  132.      * based on the pattern.
  133.      *
  134.      * @param pattern   Pattern used to construct object.
  135.      * @param status    Output param to receive success code.  If the
  136.      *                  pattern cannot be parsed, set to failure code.
  137.      */
  138.     ChoiceFormat(const UnicodeString& newPattern,
  139.                  UErrorCode& status);
  140.  
  141.  
  142.     /**
  143.      * Construct a new ChoiceFormat with the given limits and formats.  Copy
  144.      * the limits and formats instead of adopting them.
  145.      *
  146.      * @param limits    Array of limit values.
  147.      * @param formats   Array of formats.
  148.      * @param count     Size of 'limits' and 'formats' arrays.
  149.      */
  150.     
  151.     ChoiceFormat(const double* limits,
  152.                  const UnicodeString* formats,
  153.                  int32_t count );
  154.  
  155.     /**
  156.      * Copy constructor.
  157.      */
  158.     ChoiceFormat(const ChoiceFormat&);
  159.  
  160.     /**
  161.      * Assignment operator.
  162.      */
  163.     const ChoiceFormat& operator=(const ChoiceFormat&);
  164.  
  165.     /**
  166.      * Destructor.
  167.      */
  168.     virtual ~ChoiceFormat();
  169.  
  170.     /**
  171.      * Clone this Format object polymorphically. The caller owns the
  172.      * result and should delete it when done.
  173.      */
  174.     virtual Format* clone(void) const;
  175.  
  176.     /**
  177.      * Return true if the given Format objects are semantically equal.
  178.      * Objects of different subclasses are considered unequal.
  179.      */
  180.     virtual bool_t operator==(const Format& other) const;
  181.  
  182.     /**
  183.      * Sets the pattern.
  184.      * @param pattern   The pattern to be applied.
  185.      * @param status    Output param set to success/failure code on
  186.      *                  exit. If the pattern is invalid, this will be
  187.      *                  set to a failure result.
  188.      */
  189.     virtual void applyPattern(const UnicodeString& pattern,
  190.                               UErrorCode& status);
  191.  
  192.     /**
  193.      * Gets the pattern.
  194.      */
  195.     virtual UnicodeString& toPattern(UnicodeString &pattern) const;
  196.  
  197.     /**
  198.      * Set the choices to be used in formatting.  The arrays are adopted and
  199.      * should not be deleted by the caller.
  200.      *
  201.      * @param limitsToAdopt     Contains the top value that you want
  202.      *                          parsed with that format,and should be in
  203.      *                          ascending sorted order. When formatting X,
  204.      *                          the choice will be the i, where limit[i]
  205.      *                          <= X < limit[i+1].
  206.      * @param formatsToAdopt    The format strings you want to use for each limit.
  207.      * @param count             The size of the above arrays.
  208.      */
  209.     virtual void adoptChoices(double* limitsToAdopt,
  210.                               UnicodeString* formatsToAdopt,
  211.                               int32_t count );  
  212.  
  213.     /**
  214.      * Set the choices to be used in formatting.
  215.      *
  216.      * @param limitsToCopy      Contains the top value that you want
  217.      *                          parsed with that format,and should be in
  218.      *                          ascending sorted order. When formatting X,
  219.      *                          the choice will be the i, where limit[i]
  220.      *                          <= X < limit[i+1].
  221.      * @param formatsToCopy     The format strings you want to use for each limit.
  222.      * @param count             The size of the above arrays.
  223.      */
  224.     virtual void setChoices(const double* limitsToCopy,
  225.                             const UnicodeString* formatsToCopy,
  226.                             int32_t count );    
  227.     /**
  228.      * Get the limits passed in the constructor.
  229.      * @return the limits.
  230.      */
  231.     virtual const double* getLimits(int32_t& count) const;
  232.  
  233.     /**
  234.      * Get the formats passed in the constructor.
  235.      * @return the formats.
  236.      */
  237.     virtual const UnicodeString* getFormats(int32_t& count) const;
  238.  
  239.    /**
  240.     * Format a double or long number using this object's choices.
  241.     *
  242.     * @param number     The value to be formatted.
  243.     * @param toAppendTo The string to append the formatted string to.
  244.     *                   This is an output parameter.
  245.     * @param pos        On input: an alignment field, if desired.
  246.     *                   On output: the offsets of the alignment field.
  247.     * @return           A reference to 'toAppendTo'.
  248.     */
  249.     virtual UnicodeString& format(double number,
  250.                                   UnicodeString& toAppendTo,
  251.                                   FieldPosition& pos) const;
  252.     virtual UnicodeString& format(int32_t number,
  253.                                   UnicodeString& toAppendTo,
  254.                                   FieldPosition& pos) const;
  255.     virtual UnicodeString& format(const Formattable* objs,
  256.                                   int32_t cnt,
  257.                                   UnicodeString& toAppendTo,
  258.                                   FieldPosition& pos,
  259.                                   UErrorCode& success) const;
  260.     virtual UnicodeString& format(const Formattable& obj,
  261.                                   UnicodeString& toAppendTo,
  262.                                   FieldPosition& pos, 
  263.                                   UErrorCode& status) const;
  264.  
  265.     /**
  266.      * Redeclared NumberFormat method.
  267.      */
  268.     UnicodeString& format(const Formattable& obj,
  269.                           UnicodeString& result,
  270.                           UErrorCode& status) const;
  271.  
  272.     /**
  273.      * Redeclared NumberFormat method.
  274.      */
  275.     UnicodeString& format(  double number,
  276.                             UnicodeString& output) const;
  277.  
  278.     /**
  279.      * Redeclared NumberFormat method.
  280.      */
  281.     UnicodeString& format(  int32_t number,
  282.                             UnicodeString& output) const;
  283.  
  284.    /**
  285.     * Return a long if possible (e.g. within range LONG_MAX,
  286.     * LONG_MAX], and with no decimals), otherwise a double.  If
  287.     * IntegerOnly is set, will stop at a decimal point (or equivalent;
  288.     * e.g. for rational numbers "1 2/3", will stop after the 1).
  289.     * <P>
  290.     * If no object can be parsed, parsePosition is unchanged, and NULL is
  291.     * returned.
  292.     *
  293.     * @param text           The text to be parsed.
  294.     * @param result         Formattable to be set to the parse result.
  295.     *                       If parse fails, return contents are undefined.
  296.     * @param parsePosition  The position to start parsing at on input.
  297.     *                       On output, moved to after the last successfully
  298.     *                       parse character. On parse failure, does not change.
  299.     * @return               A Formattable object of numeric type.  The caller
  300.     *                       owns this an must delete it.  NULL on failure.
  301.     * @see                  NumberFormat::isParseIntegerOnly
  302.     */
  303.     virtual void parse(const UnicodeString& text,
  304.                        Formattable& result,
  305.                        ParsePosition& parsePosition) const;
  306.     virtual void parse(const UnicodeString& text,
  307.                        Formattable& result,
  308.                        UErrorCode& status) const;
  309.     
  310.     
  311. public:
  312.     /**
  313.      * Returns a unique class ID POLYMORPHICALLY.  Pure virtual override.
  314.      * This method is to implement a simple version of RTTI, since not all
  315.      * C++ compilers support genuine RTTI.  Polymorphic operator==() and
  316.      * clone() methods call this method.
  317.      *
  318.      * @return          The class ID for this object. All objects of a
  319.      *                  given class have the same class ID.  Objects of
  320.      *                  other classes have different class IDs.
  321.      */
  322.     virtual UClassID getDynamicClassID(void) const;
  323.  
  324.     /**
  325.      * Return the class ID for this class.  This is useful only for
  326.      * comparing to a return value from getDynamicClassID().  For example:
  327.      * <pre>
  328.      * .       Base* polymorphic_pointer = createPolymorphicObject();
  329.      * .       if (polymorphic_pointer->getDynamicClassID() ==
  330.      * .           Derived::getStaticClassID()) ...
  331.      * </pre>
  332.      * @return          The class ID for all objects of this class.
  333.      */
  334.     static UClassID getStaticClassID(void) { return (UClassID)&fgClassID; }
  335.  
  336.     /*
  337.      * Finds the least double greater than d (if positive == true),
  338.      * or the greatest double less than d (if positive == false).
  339.      * If NaN, returns same value.
  340.      * <P>
  341.      * Does not affect floating-point flags,
  342.      */
  343.     static double nextDouble(double d, bool_t positive);
  344.  
  345.     /**
  346.      * Finds the least double greater than d.
  347.      * If NaN, returns same value.
  348.      * Used to make half-open intervals.
  349.      * @see ChoiceFormat::previousDouble
  350.      */
  351.     static double nextDouble(double d );
  352.  
  353.     /**
  354.      * Finds the greatest double less than d.
  355.      * If NaN, returns same value.
  356.      * @see ChoiceFormat::nextDouble
  357.      */
  358.     static double previousDouble(double d );
  359.  
  360. private:
  361.     // static cache management (thread-safe)
  362.     static NumberFormat* getNumberFormat(UErrorCode &status); // call this function to 'check out' a numberformat from the cache.
  363.     static void          releaseNumberFormat(NumberFormat *adopt); // call this function to 'return' the number format to the cache.
  364.     
  365.     /**
  366.      * Converts a string to a double value using a default NumberFormat object
  367.      * which is static (shared by all ChoiceFormat instances).
  368.      * @param string the string to be converted with.
  369.      * @param status error code.
  370.      * @return the converted double number.
  371.      */
  372.     static double stod(const UnicodeString& string, UErrorCode& status);
  373.  
  374.     /**
  375.      * Converts a double value to a string using a default NumberFormat object
  376.      * which is static (shared by all ChoiceFormat instances).
  377.      * @@param value the double number to be converted with.
  378.      * @@param string the result string.
  379.      * @@param status error code.
  380.      * @@return the converted string.
  381.      */
  382.     static UnicodeString& dtos(double value, UnicodeString& string, UErrorCode& status);
  383.  
  384.     static NumberFormat* fgNumberFormat;
  385.     static char fgClassID;
  386.  
  387.     double*         fChoiceLimits;
  388.     UnicodeString*  fChoiceFormats;
  389.     int32_t         fCount;
  390. };
  391.  
  392. inline UClassID 
  393. ChoiceFormat::getDynamicClassID() const
  394.     return ChoiceFormat::getStaticClassID(); 
  395. }
  396.  
  397. inline double ChoiceFormat::nextDouble( double d )
  398. {
  399.     return ChoiceFormat::nextDouble( d, TRUE );
  400. }
  401.     
  402. inline double ChoiceFormat::previousDouble( double d )
  403. {
  404.     return ChoiceFormat::nextDouble( d, FALSE );
  405. }
  406.  
  407. inline UnicodeString&
  408. ChoiceFormat::format(const Formattable& obj,
  409.                      UnicodeString& result,
  410.                      UErrorCode& status) const {
  411.     // Don't use Format:: - use immediate base class only,
  412.     // in case immediate base modifies behavior later.
  413.     return NumberFormat::format(obj, result, status);
  414. }
  415.  
  416. inline UnicodeString&
  417. ChoiceFormat::format(double number,
  418.                      UnicodeString& output) const {
  419.     return NumberFormat::format(number, output);
  420. }
  421.  
  422. inline UnicodeString&
  423. ChoiceFormat::format(int32_t number,
  424.                      UnicodeString& output) const {
  425.     return NumberFormat::format(number, output);
  426. }
  427.  
  428. #endif // _CHOICFMT
  429. //eof
  430.