home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / i18n / unum.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-22  |  16.1 KB  |  606 lines

  1. /*
  2. *******************************************************************************
  3. *                                                                             *
  4. * COPYRIGHT:                                                                  *
  5. *   (C) Copyright Taligent, Inc.,  1996                                       *
  6. *   (C) Copyright International Business Machines Corporation,  1998-1999     *
  7. *   Licensed Material - Program-Property of IBM - All Rights Reserved.        *
  8. *   US Government Users Restricted Rights - Use, duplication, or disclosure   *
  9. *   restricted by GSA ADP Schedule Contract with IBM Corp.                    *
  10. *                                                                             *
  11. * Modification History:
  12. *
  13. *   Date        Name        Description
  14. *   06/24/99    helena      Integrated Alan's NF enhancements and Java2 bug fixes
  15. *******************************************************************************
  16. */
  17.  
  18. #include "unum.h"
  19.  
  20. #include "uloc.h"
  21. #include "numfmt.h"
  22. #include "decimfmt.h"
  23. //#include "spellfmt.h"
  24. #include "ustring.h"
  25. #include "cpputils.h"
  26. #include "fmtable.h"
  27. #include "dcfmtsym.h"
  28.  
  29. U_CAPI UNumberFormat*
  30. unum_open(    UNumberFormatStyle    style,
  31.         const   char*        locale,
  32.         UErrorCode*        status)
  33. {
  34.   if(U_FAILURE(*status)) return 0;
  35.   UNumberFormat *retVal = 0;
  36.   
  37.   switch(style) {
  38.   case UNUM_DECIMAL:
  39.     if(locale == 0)
  40.       retVal = (UNumberFormat*)NumberFormat::createInstance(*status);
  41.     else
  42.       retVal = (UNumberFormat*)NumberFormat::createInstance(Locale().init(locale),
  43.                                 *status);
  44.     break;
  45.  
  46.   case UNUM_CURRENCY:
  47.     if(locale == 0)
  48.       retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(*status);
  49.     else
  50.       retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(Locale().init(locale),
  51.                                     *status);
  52.     break;
  53.  
  54.   case UNUM_PERCENT:
  55.     if(locale == 0)
  56.       retVal = (UNumberFormat*)NumberFormat::createPercentInstance(*status);
  57.     else
  58.       retVal = (UNumberFormat*)NumberFormat::createPercentInstance(Locale().init(locale),
  59.                                 *status);
  60.     break;
  61.  
  62.   case UNUM_SPELLOUT:
  63.     // TBD: Add spellout support
  64.     //retVal = (UNumberFormat*)new NumberSpelloutFormat();
  65.     *status = U_UNSUPPORTED_ERROR;
  66.     return 0;
  67.     break;
  68.   }
  69.  
  70.   if(retVal == 0) {
  71.     *status = U_MEMORY_ALLOCATION_ERROR;
  72.     return 0;
  73.   }
  74.  
  75.   return retVal;
  76. }
  77.  
  78. U_CAPI UNumberFormat*
  79. unum_openPattern(    const    UChar*            pattern,
  80.             int32_t            patternLength,
  81.             const    char*        locale,
  82.             UErrorCode*        status)
  83. {
  84.   if(U_FAILURE(*status)) return 0;
  85.  
  86.   int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
  87.   const UnicodeString pat((UChar*)pattern, len, len);
  88.   DecimalFormatSymbols *syms = 0;
  89.  
  90.   if(locale == 0)
  91.     syms = new DecimalFormatSymbols(*status);
  92.   else
  93.     syms = new DecimalFormatSymbols(Locale().init(locale),
  94.                     *status);
  95.   
  96.   if(syms == 0) {
  97.     *status = U_MEMORY_ALLOCATION_ERROR;
  98.     return 0;
  99.   }
  100.  
  101.   DecimalFormat *fmt = 0;
  102.   fmt = new DecimalFormat(pat, syms, *status);
  103.   if(fmt == 0) {
  104.     *status = U_MEMORY_ALLOCATION_ERROR;
  105.     delete syms;
  106.     return 0;
  107.   }
  108.  
  109.   return (UNumberFormat*) fmt;
  110. }
  111.  
  112. U_CAPI void
  113. unum_close(UNumberFormat* fmt)
  114. {
  115.   delete (NumberFormat*) fmt;
  116. }
  117.  
  118. U_CAPI UNumberFormat*
  119. unum_clone(const UNumberFormat *fmt,
  120.        UErrorCode *status)
  121. {
  122.   if(U_FAILURE(*status)) return 0;
  123.  
  124.   Format *res = ((DecimalFormat*)fmt)->clone();
  125.   
  126.   if(res == 0) {
  127.     *status = U_MEMORY_ALLOCATION_ERROR;
  128.     return 0;
  129.   }
  130.  
  131.   return (UNumberFormat*) res;
  132. }
  133.  
  134. U_CAPI int32_t
  135. unum_format(    const    UNumberFormat*    fmt,
  136.         int32_t            number,
  137.         UChar*            result,
  138.         int32_t            resultLength,
  139.         UFieldPosition    *pos,
  140.         UErrorCode*        status)
  141. {
  142.   if(U_FAILURE(*status)) return -1;
  143.  
  144.   int32_t actSize;
  145.  
  146.   UnicodeString res(result, 0, resultLength);
  147.   FieldPosition fp;
  148.   
  149.   if(pos != 0)
  150.     fp.setField(pos->field);
  151.   
  152.   ((NumberFormat*)fmt)->format(number, res, fp);
  153.   T_fillOutputParams(&res, result, resultLength, &actSize, status);
  154.   
  155.   if(pos != 0) {
  156.     pos->beginIndex = fp.getBeginIndex();
  157.     pos->endIndex = fp.getEndIndex();
  158.   }
  159.   
  160.   return actSize;  
  161. }
  162.  
  163. U_CAPI int32_t
  164. unum_formatDouble(    const    UNumberFormat*  fmt,
  165.             double          number,
  166.             UChar*          result,
  167.             int32_t         resultLength,
  168.             UFieldPosition  *pos, /* 0 if ignore */
  169.             UErrorCode*     status)
  170. {
  171.   if(U_FAILURE(*status)) return -1;
  172.  
  173.   int32_t actSize;
  174.  
  175.   UnicodeString res(result, 0, resultLength);
  176.   FieldPosition fp;
  177.   
  178.   if(pos != 0)
  179.     fp.setField(pos->field);
  180.   
  181.   ((NumberFormat*)fmt)->format(number, res, fp);
  182.   T_fillOutputParams(&res, result, resultLength, &actSize, status);
  183.   
  184.   if(pos != 0) {
  185.     pos->beginIndex = fp.getBeginIndex();
  186.     pos->endIndex = fp.getEndIndex();
  187.   }
  188.   
  189.   return actSize;  
  190. }
  191.  
  192. U_CAPI int32_t
  193. unum_parse(    const   UNumberFormat*  fmt,
  194.         const   UChar*          text,
  195.         int32_t         textLength,
  196.         int32_t         *parsePos /* 0 = start */,
  197.         UErrorCode      *status)
  198. {
  199.   if(U_FAILURE(*status)) return 0;
  200.  
  201.   int32_t len = (textLength == -1 ? u_strlen(text) : textLength);
  202.   const UnicodeString src((UChar*)text, len, len);
  203.   ParsePosition pp;
  204.   Formattable res;
  205.  
  206.   if(parsePos != 0)
  207.     pp.setIndex(*parsePos);
  208.  
  209.   ((NumberFormat*)fmt)->parse(src, res, pp);
  210.  
  211.   if(parsePos != 0) {
  212.     if(pp.getErrorIndex() == -1)
  213.       *parsePos = pp.getIndex();
  214.     else {
  215.       *parsePos = pp.getErrorIndex();
  216.       *status = U_PARSE_ERROR;
  217.     }
  218.   }
  219.  
  220.   /* return the actual type of the result, cast to a long */
  221.   return (res.getType() == Formattable::kLong) 
  222.     ? res.getLong() 
  223.     : (int32_t) res.getDouble();
  224. }
  225.  
  226. U_CAPI double
  227. unum_parseDouble(    const   UNumberFormat*  fmt,
  228.             const   UChar*          text,
  229.             int32_t         textLength,
  230.             int32_t         *parsePos /* 0 = start */,
  231.             UErrorCode      *status)
  232. {
  233.   if(U_FAILURE(*status)) return 0;
  234.  
  235.   int32_t len = (textLength == -1 ? u_strlen(text) : textLength);
  236.   const UnicodeString src((UChar*)text, len, len);
  237.   ParsePosition pp;
  238.   Formattable res;
  239.  
  240.   if(parsePos != 0)
  241.     pp.setIndex(*parsePos);
  242.  
  243.   ((NumberFormat*)fmt)->parse(src, res, pp);
  244.  
  245.   if(parsePos != 0) {
  246.     if(pp.getErrorIndex() == -1)
  247.       *parsePos = pp.getIndex();
  248.     else {
  249.       *parsePos = pp.getErrorIndex();
  250.       *status = U_PARSE_ERROR;
  251.     }
  252.   }
  253.   
  254.   /* return the actual type of the result, cast to a double */
  255.   return (res.getType() == Formattable::kDouble) 
  256.     ? res.getDouble() 
  257.     : (double) res.getLong();
  258. }
  259.  
  260. U_CAPI const char*
  261. unum_getAvailable(int32_t index)
  262. {
  263.   return uloc_getAvailable(index);
  264. }
  265.  
  266. U_CAPI int32_t
  267. unum_countAvailable()
  268. {
  269.   return uloc_countAvailable();
  270. }
  271.  
  272. U_CAPI int32_t
  273. unum_getAttribute(const UNumberFormat*          fmt,
  274.           UNumberFormatAttribute  attr)
  275. {
  276.   switch(attr) {
  277.   case UNUM_PARSE_INT_ONLY:
  278.     return ((NumberFormat*)fmt)->isParseIntegerOnly();
  279.     
  280.   case UNUM_GROUPING_USED:
  281.     return ((NumberFormat*)fmt)->isGroupingUsed();
  282.     
  283.   case UNUM_DECIMAL_ALWAYS_SHOWN:
  284.     return ((DecimalFormat*)fmt)->isDecimalSeparatorAlwaysShown();    
  285.     
  286.   case UNUM_MAX_INTEGER_DIGITS:
  287.     return ((NumberFormat*)fmt)->getMaximumIntegerDigits();
  288.     
  289.   case UNUM_MIN_INTEGER_DIGITS:
  290.     return ((NumberFormat*)fmt)->getMinimumIntegerDigits();
  291.     
  292.   case UNUM_INTEGER_DIGITS:
  293.     // TBD: what should this return?
  294.     return ((NumberFormat*)fmt)->getMinimumIntegerDigits();
  295.     
  296.   case UNUM_MAX_FRACTION_DIGITS:
  297.     return ((NumberFormat*)fmt)->getMaximumFractionDigits();
  298.     
  299.   case UNUM_MIN_FRACTION_DIGITS:
  300.     return ((NumberFormat*)fmt)->getMinimumFractionDigits();
  301.     
  302.   case UNUM_FRACTION_DIGITS:
  303.     // TBD: what should this return?
  304.     return ((NumberFormat*)fmt)->getMinimumFractionDigits();
  305.  
  306.   case UNUM_MULTIPLIER:
  307.     return ((DecimalFormat*)fmt)->getMultiplier();    
  308.     
  309.   case UNUM_GROUPING_SIZE:
  310.     return ((DecimalFormat*)fmt)->getGroupingSize();    
  311.  
  312.   case UNUM_ROUNDING_MODE:
  313.     return ((DecimalFormat*)fmt)->getRoundingMode();
  314.  
  315.   case UNUM_FORMAT_WIDTH:
  316.     return ((DecimalFormat*)fmt)->getFormatWidth();
  317.  
  318.   /** The position at which padding will take place. */
  319.   case UNUM_PADDING_POSITION:
  320.     return ((DecimalFormat*)fmt)->getPadPosition();
  321.  
  322.   default:
  323.     break;
  324.   }
  325.   return -1;
  326. }
  327.  
  328. U_CAPI void
  329. unum_setAttribute(    UNumberFormat*          fmt,
  330.             UNumberFormatAttribute  attr,
  331.             int32_t                 newValue)
  332. {
  333.   switch(attr) {
  334.   case UNUM_PARSE_INT_ONLY:
  335.     ((NumberFormat*)fmt)->setParseIntegerOnly((bool_t)newValue);
  336.     break;
  337.     
  338.   case UNUM_GROUPING_USED:
  339.     ((NumberFormat*)fmt)->setGroupingUsed((bool_t)newValue);
  340.     break;
  341.     
  342.   case UNUM_DECIMAL_ALWAYS_SHOWN:
  343.     ((DecimalFormat*)fmt)->setDecimalSeparatorAlwaysShown((bool_t)newValue);
  344.     break;
  345.     
  346.   case UNUM_MAX_INTEGER_DIGITS:
  347.     ((NumberFormat*)fmt)->setMaximumIntegerDigits(newValue);
  348.     break;
  349.     
  350.   case UNUM_MIN_INTEGER_DIGITS:
  351.     ((NumberFormat*)fmt)->setMinimumIntegerDigits(newValue);
  352.     break;
  353.     
  354.   case UNUM_INTEGER_DIGITS:
  355.     ((NumberFormat*)fmt)->setMinimumIntegerDigits(newValue);
  356.     ((NumberFormat*)fmt)->setMaximumIntegerDigits(newValue);
  357.     break;
  358.     
  359.   case UNUM_MAX_FRACTION_DIGITS:
  360.     ((NumberFormat*)fmt)->setMaximumFractionDigits(newValue);
  361.     break;
  362.     
  363.   case UNUM_MIN_FRACTION_DIGITS:
  364.     ((NumberFormat*)fmt)->setMinimumFractionDigits(newValue);
  365.     break;
  366.     
  367.   case UNUM_FRACTION_DIGITS:
  368.     ((NumberFormat*)fmt)->setMinimumFractionDigits(newValue);
  369.     ((NumberFormat*)fmt)->setMaximumFractionDigits(newValue);
  370.     break;
  371.  
  372.   case UNUM_MULTIPLIER:
  373.     ((DecimalFormat*)fmt)->setMultiplier(newValue);    
  374.     break;
  375.     
  376.   case UNUM_GROUPING_SIZE:
  377.     ((DecimalFormat*)fmt)->setGroupingSize(newValue);    
  378.     break;
  379.  
  380.   case UNUM_ROUNDING_MODE:
  381.       ((DecimalFormat*)fmt)->setRoundingMode((DecimalFormat::ERoundingMode)newValue);
  382.     break;
  383.  
  384.   case UNUM_FORMAT_WIDTH:
  385.     ((DecimalFormat*)fmt)->setFormatWidth(newValue);
  386.     break;
  387.  
  388.   /** The position at which padding will take place. */
  389.   case UNUM_PADDING_POSITION:
  390.       ((DecimalFormat*)fmt)->setPadPosition((DecimalFormat::EPadPosition)newValue);
  391.     break;
  392.   
  393.   }
  394. }
  395.  
  396. U_CAPI double
  397. unum_getDoubleAttribute(const UNumberFormat*          fmt,
  398.           UNumberFormatAttribute  attr)
  399. {
  400.   if(attr==UNUM_ROUNDING_INCREMENT) {
  401.     return ((DecimalFormat*)fmt)->getRoundingIncrement();
  402.   } else {
  403.     return -1.0;
  404.   }
  405. }
  406.  
  407. U_CAPI void
  408. unum_setDoubleAttribute(    UNumberFormat*          fmt,
  409.             UNumberFormatAttribute  attr,
  410.             double                 newValue)
  411. {
  412.   switch(attr) {   
  413.   case UNUM_ROUNDING_INCREMENT:
  414.     ((DecimalFormat*)fmt)->setRoundingIncrement(newValue);
  415.     break;
  416.   
  417.   }
  418. }
  419.  
  420. U_CAPI int32_t
  421. unum_getTextAttribute(    const    UNumberFormat*                    fmt,
  422.             UNumberFormatTextAttribute      tag,
  423.             UChar*                            result,
  424.             int32_t                            resultLength,
  425.             UErrorCode*                        status)
  426. {
  427.   if(U_FAILURE(*status)) return -1;
  428.  
  429.   int32_t actSize = 0;
  430.  
  431.   UnicodeString res(result, 0, resultLength);
  432.  
  433.   switch(tag) {
  434.   case UNUM_POSITIVE_PREFIX:
  435.     ((DecimalFormat*)fmt)->getPositivePrefix(res);
  436.     break;
  437.  
  438.   case UNUM_POSITIVE_SUFFIX:
  439.     ((DecimalFormat*)fmt)->getPositiveSuffix(res);
  440.     break;
  441.  
  442.   case UNUM_NEGATIVE_PREFIX:
  443.     ((DecimalFormat*)fmt)->getNegativePrefix(res);
  444.     break;
  445.  
  446.   case UNUM_NEGATIVE_SUFFIX:
  447.     ((DecimalFormat*)fmt)->getNegativeSuffix(res);
  448.     break;
  449.  
  450.   case UNUM_PADDING_CHARACTER:
  451.     *result = ((DecimalFormat*)fmt)->getPadCharacter();
  452.     actSize = 1;
  453.     break;
  454.  
  455.   default:
  456.     *status = U_UNSUPPORTED_ERROR;
  457.     return -1;
  458.     break;
  459.   }
  460.  
  461.   if (actSize != 1)
  462.     T_fillOutputParams(&res, result, resultLength, &actSize, status);
  463.   return actSize;
  464. }
  465.  
  466. U_CAPI void
  467. unum_setTextAttribute(    UNumberFormat*                    fmt,
  468.             UNumberFormatTextAttribute      tag,
  469.             const    UChar*                            newValue,
  470.             int32_t                            newValueLength,
  471.             UErrorCode                        *status)
  472. {
  473.   if(U_FAILURE(*status)) return;
  474.  
  475.   int32_t len = (newValueLength == -1 ? u_strlen(newValue) : newValueLength);
  476.   const UnicodeString val((UChar*)newValue, len, len);
  477.   
  478.   switch(tag) {
  479.   case UNUM_POSITIVE_PREFIX:
  480.     ((DecimalFormat*)fmt)->setPositivePrefix(val);
  481.     break;
  482.  
  483.   case UNUM_POSITIVE_SUFFIX:
  484.     ((DecimalFormat*)fmt)->setPositiveSuffix(val);
  485.     break;
  486.  
  487.   case UNUM_NEGATIVE_PREFIX:
  488.     ((DecimalFormat*)fmt)->setNegativePrefix(val);
  489.     break;
  490.  
  491.   case UNUM_NEGATIVE_SUFFIX:
  492.     ((DecimalFormat*)fmt)->setNegativeSuffix(val);
  493.     break;
  494.  
  495.   case UNUM_PADDING_CHARACTER:
  496.     ((DecimalFormat*)fmt)->setPadCharacter(*newValue);
  497.     break;
  498.  
  499.   default:
  500.     *status = U_UNSUPPORTED_ERROR;
  501.     break;
  502.   }
  503. }
  504.  
  505. U_CAPI int32_t
  506. unum_toPattern(    const    UNumberFormat*          fmt,
  507.         bool_t                  isPatternLocalized,
  508.         UChar*                  result,
  509.         int32_t                 resultLength,
  510.         UErrorCode*             status)
  511. {
  512.   if(U_FAILURE(*status)) return -1;
  513.  
  514.   int32_t actSize;
  515.  
  516.   UnicodeString pat(result, 0, resultLength);
  517.  
  518.   if(isPatternLocalized)
  519.     ((DecimalFormat*)fmt)->toLocalizedPattern(pat);
  520.   else
  521.     ((DecimalFormat*)fmt)->toPattern(pat);
  522.  
  523.   T_fillOutputParams(&pat, result, resultLength, &actSize, status);
  524.   return actSize;
  525. }
  526.  
  527. U_CAPI void
  528. unum_getSymbols(const UNumberFormat* fmt,
  529.         UNumberFormatSymbols *syms)
  530. {
  531.   UnicodeString temp;
  532.   int32_t len;
  533.   const DecimalFormatSymbols *dfs = 
  534.     ((DecimalFormat*)fmt)->getDecimalFormatSymbols();
  535.   
  536.   syms->decimalSeparator     = dfs->getDecimalSeparator();
  537.   syms->groupingSeparator     = dfs->getGroupingSeparator();
  538.   syms->patternSeparator     = dfs->getPatternSeparator();
  539.   syms->percent         = dfs->getPercent();
  540.   syms->zeroDigit         = dfs->getZeroDigit();
  541.   syms->digit             = dfs->getDigit();
  542.   syms->plusSign          = dfs->getPlusSign();
  543.   syms->minusSign         = dfs->getMinusSign();
  544.   
  545.   dfs->getCurrencySymbol(temp);
  546.   len = icu_min(temp.size(), UNFSYMBOLSMAXSIZE);
  547.   u_strncpy(syms->currency, temp.getUChars(), len);
  548.   syms->currency[len > 0 ? len + 1 : 0] = 0x0000;
  549.  
  550.   dfs->getInternationalCurrencySymbol(temp);
  551.   len = icu_min(temp.size(), UNFSYMBOLSMAXSIZE);
  552.   u_strncpy(syms->intlCurrency, temp.getUChars(), len);
  553.   syms->intlCurrency[len > 0 ? len + 1 : 0] = 0x0000;
  554.   
  555.   syms->monetarySeparator    = dfs->getMonetaryDecimalSeparator();
  556.   syms->exponential         = dfs->getExponentialSymbol();
  557.   syms->perMill         = dfs->getPerMill();
  558.   syms->padEscape       = dfs->getPadEscape();
  559.  
  560.   dfs->getInfinity(temp);
  561.   len = icu_min(temp.size(), UNFSYMBOLSMAXSIZE);
  562.   u_strncpy(syms->infinity, temp.getUChars(), len);
  563.   syms->infinity[len > 0 ? len + 1 : 0] = 0x0000;
  564.  
  565.   dfs->getNaN(temp);
  566.   len = icu_min(temp.size(), UNFSYMBOLSMAXSIZE);
  567.   u_strncpy(syms->naN, temp.getUChars(), len);
  568.   syms->naN[len > 0 ? len + 1 : 0] = 0x0000;
  569. }
  570.  
  571. U_CAPI void
  572. unum_setSymbols(            UNumberFormat*          fmt,
  573.                     const   UNumberFormatSymbols*   symbolsToSet,
  574.                     UErrorCode *status)
  575. {
  576.   if(U_FAILURE(*status)) return;
  577.  
  578.   DecimalFormatSymbols *syms = new DecimalFormatSymbols(*status);
  579.   if(syms == 0) {
  580.     *status = U_MEMORY_ALLOCATION_ERROR;
  581.     return;
  582.   }
  583.  
  584.   syms->setDecimalSeparator(symbolsToSet->decimalSeparator);
  585.   syms->setGroupingSeparator(symbolsToSet->groupingSeparator);
  586.   syms->setPatternSeparator(symbolsToSet->patternSeparator);
  587.   syms->setPercent(symbolsToSet->percent);
  588.   syms->setZeroDigit(symbolsToSet->zeroDigit);
  589.   syms->setDigit(symbolsToSet->digit);
  590.   syms->setPlusSign(symbolsToSet->plusSign);
  591.   syms->setMinusSign(symbolsToSet->minusSign);
  592.   
  593.   syms->setCurrencySymbol(symbolsToSet->currency);
  594.   syms->setInternationalCurrencySymbol(symbolsToSet->intlCurrency);
  595.   
  596.   syms->setMonetaryDecimalSeparator(symbolsToSet->monetarySeparator);
  597.   syms->setExponentialSymbol(symbolsToSet->exponential);
  598.   syms->setPerMill(symbolsToSet->perMill);
  599.   syms->setPadEscape(symbolsToSet->padEscape);
  600.  
  601.   syms->setInfinity(symbolsToSet->infinity);
  602.   syms->setNaN(symbolsToSet->naN);
  603.  
  604.   ((DecimalFormat*)fmt)->adoptDecimalFormatSymbols(syms);
  605. }
  606.