| Viewing file:  main.cpp (9.11 KB)      -rw-r--r-- Select action/file-type:
 
  (+) |  (+) |  (+) | Code (+) | Session (+) |  (+) | SDB (+) |  (+) |  (+) |  (+) |  (+) |  (+) | 
 
/*********************************************************************   © 2016 and later: Unicode, Inc. and others.
 *   License & terms of use: http://www.unicode.org/copyright.html#License
 *************************************************************************
 *************************************************************************
 * COPYRIGHT:
 * Copyright (c) 1999-2014, International Business Machines Corporation and
 * others. All Rights Reserved.
 *************************************************************************/
 
 #include "unicode/utypes.h"
 #include "unicode/unistr.h"
 #include "unicode/numfmt.h"
 #include "unicode/dcfmtsym.h"
 #include "unicode/decimfmt.h"
 #include "unicode/locid.h"
 #include "unicode/uclean.h"
 #include "util.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 extern "C" void capi();
 void cppapi();
 
 static void
 showCurrencyFormatting(UBool useICU26API);
 
 int main(int argc, char **argv) {
 printf("%s output is in UTF-8\n", argv[0]);
 
 printf("C++ API\n");
 cppapi();
 
 printf("C API\n");
 capi();
 
 showCurrencyFormatting(FALSE);
 showCurrencyFormatting(TRUE);
 
 u_cleanup();    // Release any additional storage held by ICU.
 
 printf("Exiting successfully\n");
 return 0;
 }
 
 /**
 * Sample code for the C++ API to NumberFormat.
 */
 void cppapi() {
 Locale us("en", "US");
 UErrorCode status = U_ZERO_ERROR;
 
 // Create a number formatter for the US locale
 NumberFormat *fmt = NumberFormat::createInstance(us, status);
 check(status, "NumberFormat::createInstance");
 
 // Parse a string.  The string uses the digits '0' through '9'
 // and the decimal separator '.', standard in the US locale
 UnicodeString str("9876543210.123");
 Formattable result;
 fmt->parse(str, result, status);
 check(status, "NumberFormat::parse");
 
 printf("NumberFormat::parse(\""); // Display the result
 uprintf(str);
 printf("\") => ");
 uprintf(formattableToString(result));
 printf("\n");
 
 // Take the number parsed above, and use the formatter to
 // format it.
 str.remove(); // format() will APPEND to this string
 fmt->format(result, str, status);
 check(status, "NumberFormat::format");
 
 printf("NumberFormat::format("); // Display the result
 uprintf(formattableToString(result));
 printf(") => \"");
 uprintf(str);
 printf("\"\n");
 
 delete fmt; // Release the storage used by the formatter
 
 }
 
 // currency formatting ----------------------------------------------------- ***
 
 /*
 * Set a currency on a NumberFormat with pre-ICU 2.6 APIs.
 * This is a "hack" that will not work properly for all cases because
 * only ICU 2.6 introduced a more complete framework and data for this.
 *
 * @param nf The NumberFormat on which to set the currency; takes effect on
 *           currency-formatting NumberFormat instances.
 *           This must actually be a DecimalFormat instance.
 *           The display style of the output is controlled by nf (its pattern,
 *           usually from the display locale ID used to create this instance)
 *           while the currency symbol and number of decimals are set for
 *           the currency.
 * @param currency The 3-letter ISO 4217 currency code, NUL-terminated.
 * @param errorCode ICU error code, must pass U_SUCCESS() on input.
 */
 static void
 setNumberFormatCurrency_2_4(NumberFormat &nf, const char *currency, UErrorCode &errorCode) {
 // argument checking
 if(U_FAILURE(errorCode)) {
 return;
 }
 if(currency==NULL || strlen(currency)!=3) {
 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
 return;
 }
 
 // check that the formatter is a DecimalFormat instance
 // necessary because we will cast to the DecimalFormat subclass to set
 // the currency symbol
 DecimalFormat *dnf=dynamic_cast<DecimalFormat *>(&nf);
 if(dnf==NULL) {
 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
 return;
 }
 
 // map the currency code to a locale ID
 // only the currencies in this array are supported
 // it would be possible to map to a locale ID, instantiate a currency
 // formatter for that and copy its values, but that would be slower,
 // and we have to hardcode something here anyway
 static const struct {
 // ISO currency ID
 const char *currency;
 
 // fractionDigits==minimumFractionDigits==maximumFractionDigits
 // for these currencies
 int32_t fractionDigits;
 
 /*
 * Set the rounding increment to 0 if it is implied with the number of
 * fraction digits. Setting an explicit rounding increment makes
 * number formatting slower.
 * In other words, set it to something other than 0 only for unusual
 * cases like "nickel rounding" (0.05) when the increment differs from
 * 10^(-maximumFractionDigits).
 */
 double roundingIncrement;
 
 // Unicode string with the desired currency display symbol or name
 UChar symbol[16];
 } currencyMap[]={
 { "USD", 2, 0.0, { 0x24, 0 } },
 { "GBP", 2, 0.0, { 0xa3, 0 } },
 { "EUR", 2, 0.0, { 0x20ac, 0 } },
 { "JPY", 0, 0.0, { 0xa5, 0 } }
 };
 
 int32_t i;
 
 for(i=0; i<UPRV_LENGTHOF(currencyMap); ++i) {
 if(strcmp(currency, currencyMap[i].currency)==0) {
 break;
 }
 }
 if(i==UPRV_LENGTHOF(currencyMap)) {
 // a more specific error code would be useful in a real application
 errorCode=U_UNSUPPORTED_ERROR;
 return;
 }
 
 // set the currency-related data into the caller's formatter
 
 nf.setMinimumFractionDigits(currencyMap[i].fractionDigits);
 nf.setMaximumFractionDigits(currencyMap[i].fractionDigits);
 
 dnf->setRoundingIncrement(currencyMap[i].roundingIncrement);
 
 DecimalFormatSymbols symbols(*dnf->getDecimalFormatSymbols());
 symbols.setSymbol(DecimalFormatSymbols::kCurrencySymbol, currencyMap[i].symbol);
 dnf->setDecimalFormatSymbols(symbols); // do not adopt symbols: Jitterbug 2889
 }
 
 /*
 * Set a currency on a NumberFormat with ICU 2.6 APIs.
 *
 * @param nf The NumberFormat on which to set the currency; takes effect on
 *           currency-formatting NumberFormat instances.
 *           The display style of the output is controlled by nf (its pattern,
 *           usually from the display locale ID used to create this instance)
 *           while the currency symbol and number of decimals are set for
 *           the currency.
 * @param currency The 3-letter ISO 4217 currency code, NUL-terminated.
 * @param errorCode ICU error code, must pass U_SUCCESS() on input.
 */
 static void
 setNumberFormatCurrency_2_6(NumberFormat &nf, const char *currency, UErrorCode &errorCode) {
 if(U_FAILURE(errorCode)) {
 return;
 }
 if(currency==NULL || strlen(currency)!=3) {
 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
 return;
 }
 
 // invariant-character conversion to UChars (see utypes.h and putil.h)
 UChar uCurrency[4];
 u_charsToUChars(currency, uCurrency, 4);
 
 // set the currency
 // in ICU 3.0 this API (which was @draft ICU 2.6) gained a UErrorCode& argument
 #if (U_ICU_VERSION_MAJOR_NUM < 3)
 nf.setCurrency(uCurrency);
 #else
 nf.setCurrency(uCurrency, errorCode);
 #endif
 }
 
 static const char *const
 sampleLocaleIDs[]={
 // use locale IDs complete with country code to be sure to
 // pick up number/currency format patterns
 "en_US", "en_GB", "de_DE", "ja_JP", "fr_FR", "hi_IN"
 };
 
 static const char *const
 sampleCurrencies[]={
 "USD", "GBP", "EUR", "JPY"
 };
 
 static void
 showCurrencyFormatting(UBool useICU26API) {
 NumberFormat *nf;
 int32_t i, j;
 
 UnicodeString output;
 
 UErrorCode errorCode;
 
 // TODO: Using printf() here assumes that the runtime encoding is ASCII-friendly
 // and can therefore be mixed with UTF-8
 
 for(i=0; i<UPRV_LENGTHOF(sampleLocaleIDs); ++i) {
 printf("show currency formatting (method for %s) in the locale \"%s\"\n",
 useICU26API ? "ICU 2.6" : "before ICU 2.6",
 sampleLocaleIDs[i]);
 
 // get a currency formatter for this locale ID
 errorCode=U_ZERO_ERROR;
 nf=NumberFormat::createCurrencyInstance(sampleLocaleIDs[i], errorCode);
 if(U_FAILURE(errorCode)) {
 printf("NumberFormat::createCurrencyInstance(%s) failed - %s\n",
 sampleLocaleIDs[i], u_errorName(errorCode));
 continue;
 }
 
 for(j=0; j<UPRV_LENGTHOF(sampleCurrencies); ++j) {
 printf("  - format currency \"%s\": ", sampleCurrencies[j]);
 
 // set the actual currency to be formatted
 if(useICU26API) {
 setNumberFormatCurrency_2_6(*nf, sampleCurrencies[j], errorCode);
 } else {
 setNumberFormatCurrency_2_4(*nf, sampleCurrencies[j], errorCode);
 }
 if(U_FAILURE(errorCode)) {
 printf("setNumberFormatCurrency(%s) failed - %s\n",
 sampleCurrencies[j], u_errorName(errorCode));
 continue;
 }
 
 // output=formatted currency value
 output.remove();
 nf->format(12345678.93, output);
 output+=(UChar)0x0a; // '\n'
 uprintf(output);
 }
 }
 }
 
 |