static UChar* myNumformat(const UNumberFormat* numfor, double d) { UChar *result2=NULL; int32_t resultlength, resultlengthneeded; UErrorCode status = U_ZERO_ERROR; resultlength=0; resultlengthneeded=unum_formatDouble(numfor, d, NULL, resultlength, NULL, &status); if(status==U_BUFFER_OVERFLOW_ERROR) { status=U_ZERO_ERROR; resultlength=resultlengthneeded+1; /*result2=(UChar*)malloc(sizeof(UChar) * resultlength);*/ /* this leaks */ result2=(UChar*)ctst_malloc(sizeof(UChar) * resultlength); /*this won't*/ unum_formatDouble(numfor, d, result2, resultlength, NULL, &status); } if(U_FAILURE(status)) { log_err("FAIL: Error in formatting using unum_format(.....) %s\n", myErrorName(status) ); return 0; } return result2; }
int icu_format_number(lua_State *L) { double a = luaL_checknumber(L, 1); /* See http://www.unicode.org/repos/cldr/tags/latest/common/bcp47/number.xml for valid system names */ const char* system = luaL_checkstring(L, 2); char locale[18]; // "@numbers=12345678"; UChar buf[256]; char utf8[256]; int32_t needed; UErrorCode status = U_ZERO_ERROR; snprintf(locale, 18, "@numbers=%s", system); UNumberFormat* fmt = unum_open(UNUM_DECIMAL, 0, 0, locale, 0, &status); if(U_FAILURE(status)) { luaL_error(L, "Locale %s unavailable: %s", locale, u_errorName(status)); } needed = unum_formatDouble(fmt, a, buf, 256, NULL, &status); assert(!U_FAILURE(status)); u_austrncpy(utf8, buf, 256); lua_pushstring(L, utf8); return 1; }
void IntlTestNumberFormatAPI::testRegistration() { #if !UCONFIG_NO_SERVICE UErrorCode status = U_ZERO_ERROR; NumberFormat* f0 = NumberFormat::createInstance(SWAP_LOC, status); NumberFormat* f1 = NumberFormat::createInstance(SRC_LOC, status); NumberFormat* f2 = NumberFormat::createCurrencyInstance(SRC_LOC, status); URegistryKey key = NumberFormat::registerFactory(new NFTestFactory(), status); NumberFormat* f3 = NumberFormat::createCurrencyInstance(SRC_LOC, status); NumberFormat* f3a = NumberFormat::createCurrencyInstance(SRC_LOC, status); NumberFormat* f4 = NumberFormat::createInstance(SRC_LOC, status); StringEnumeration* locs = NumberFormat::getAvailableLocales(); UNumberFormat* uf3 = unum_open(UNUM_CURRENCY, NULL, 0, SRC_LOC.getName(),NULL, &status); UNumberFormat* uf4 = unum_open(UNUM_DEFAULT, NULL, 0, SRC_LOC.getName(), NULL, &status); const UnicodeString* res; for (res = locs->snext(status); res; res = locs->snext(status)) { logln(*res); // service is still in synch } NumberFormat::unregister(key, status); // restore for other tests NumberFormat* f5 = NumberFormat::createCurrencyInstance(SRC_LOC, status); UNumberFormat* uf5 = unum_open(UNUM_CURRENCY, NULL, 0, SRC_LOC.getName(),NULL, &status); if (U_FAILURE(status)) { dataerrln("Error creating instnaces."); return; } else { float n = 1234.567f; UnicodeString res0, res1, res2, res3, res4, res5; UChar ures3[50]; UChar ures4[50]; UChar ures5[50]; f0->format(n, res0); f1->format(n, res1); f2->format(n, res2); f3->format(n, res3); f4->format(n, res4); f5->format(n, res5); unum_formatDouble(uf3, n, ures3, 50, NULL, &status); unum_formatDouble(uf4, n, ures4, 50, NULL, &status); unum_formatDouble(uf5, n, ures5, 50, NULL, &status); logln((UnicodeString)"f0 swap int: " + res0); logln((UnicodeString)"f1 src int: " + res1); logln((UnicodeString)"f2 src cur: " + res2); logln((UnicodeString)"f3 reg cur: " + res3); logln((UnicodeString)"f4 reg int: " + res4); logln((UnicodeString)"f5 unreg cur: " + res5); log("uf3 reg cur: "); logln(ures3); log("uf4 reg int: "); logln(ures4); log("uf5 ureg cur: "); logln(ures5); if (f3 == f3a) { errln("did not get new instance from service"); } else { delete f3a; } if (res3 != res0) { errln("registered service did not match"); } if (res4 != res1) { errln("registered service did not inherit"); } if (res5 != res2) { errln("unregistered service did not match original"); } if (res0 != ures3) { errln("registered service did not match / unum"); } if (res1 != ures4) { errln("registered service did not inherit / unum"); } if (res2 != ures5) { errln("unregistered service did not match original / unum"); } } unum_close(uf5); delete f5; unum_close(uf4); unum_close(uf3); delete f4; delete f3; delete f2; delete f1; delete f0; for (res = locs->snext(status); res; res = locs->snext(status)) { errln(*res); // service should be out of synch } locs->reset(status); // now in synch again, we hope for (res = locs->snext(status); res; res = locs->snext(status)) { logln(*res); } delete locs; #endif }
int32_t u_sprintf_percent_handler(u_localized_string *output, const u_sprintf_spec_info *info, const ufmt_args *args) { double num = (double) (args[0].doubleValue); UNumberFormat *format; UChar result [USPRINTF_BUFFER_SIZE]; int32_t minDecimalDigits; int32_t maxDecimalDigits; UErrorCode status = U_ZERO_ERROR; /* mask off any necessary bits */ /* if(! info->fIsLongDouble) num &= DBL_MAX;*/ /* get the formatter */ format = u_locbund_getPercentFormat(output->fBundle); /* handle error */ if(format == 0) return 0; /* set the appropriate flags on the formatter */ /* clone the stream's bundle if it isn't owned */ if(! output->fOwnBundle) { output->fBundle = u_locbund_clone(output->fBundle); output->fOwnBundle = TRUE; format = u_locbund_getPercentFormat(output->fBundle); } /* set the number of decimal digits */ /* save the formatter's state */ minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS); maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS); if(info->fPrecision != -1) { /* set the # of decimal digits */ unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision); } else if(info->fPrecision == 0 && ! info->fAlt) { /* no decimal point in this case */ unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0); } else if(info->fAlt) { /* '#' means always show decimal point */ /* copy of printf behavior on Solaris - '#' shows 6 digits */ unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6); } else { /* # of decimal digits is 6 if precision not specified */ unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6); } /* set whether to show the sign */ u_sprintf_set_sign(format, info, &status); /* format the number */ unum_formatDouble(format, num, result, USPRINTF_BUFFER_SIZE, 0, &status); /* restore the number format */ unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits); unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits); return u_sprintf_pad_and_justify(output, info, result, u_strlen(result)); }
int32_t u_sprintf_scientific_handler(u_localized_string *output, const u_sprintf_spec_info *info, const ufmt_args *args) { double num = (double) (args[0].doubleValue); UNumberFormat *format; UChar result [USPRINTF_BUFFER_SIZE]; int32_t minDecimalDigits; int32_t maxDecimalDigits; UErrorCode status = U_ZERO_ERROR; UChar srcExpBuf[USPRINTF_SYMBOL_BUFFER_SIZE]; int32_t srcLen, expLen; UChar expBuf[USPRINTF_SYMBOL_BUFFER_SIZE]; /* mask off any necessary bits */ /* if(! info->fIsLongDouble) num &= DBL_MAX;*/ /* get the formatter */ format = u_locbund_getScientificFormat(output->fBundle); /* handle error */ if(format == 0) return 0; /* set the appropriate flags on the formatter */ /* clone the stream's bundle if it isn't owned */ if(! output->fOwnBundle) { output->fBundle = u_locbund_clone(output->fBundle); output->fOwnBundle = TRUE; format = u_locbund_getScientificFormat(output->fBundle); } srcLen = unum_getSymbol(format, UNUM_EXPONENTIAL_SYMBOL, srcExpBuf, sizeof(srcExpBuf), &status); /* Upper/lower case the e */ if (info->fSpec == (UChar)0x65 /* e */) { expLen = u_strToLower(expBuf, (int32_t)sizeof(expBuf), srcExpBuf, srcLen, output->fBundle->fLocale, &status); } else { expLen = u_strToUpper(expBuf, (int32_t)sizeof(expBuf), srcExpBuf, srcLen, output->fBundle->fLocale, &status); } unum_setSymbol(format, UNUM_EXPONENTIAL_SYMBOL, expBuf, expLen, &status); /* set the number of decimal digits */ /* save the formatter's state */ minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS); maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS); if(info->fPrecision != -1) { /* set the # of decimal digits */ unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision); } else if(info->fPrecision == 0 && ! info->fAlt) { /* no decimal point in this case */ unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0); } else if(info->fAlt) { /* '#' means always show decimal point */ /* copy of printf behavior on Solaris - '#' shows 6 digits */ unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6); } else { /* # of decimal digits is 6 if precision not specified */ unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6); } /* set whether to show the sign */ u_sprintf_set_sign(format, info, &status); /* format the number */ unum_formatDouble(format, num, result, USPRINTF_BUFFER_SIZE, 0, &status); /* restore the number format */ unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits); unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits); /* Since we clone the fBundle and we're only using the scientific format, we don't need to save the old exponent value. */ /*unum_setSymbol(format, UNUM_EXPONENTIAL_SYMBOL, srcExpBuf, srcLen, &status);*/ return u_sprintf_pad_and_justify(output, info, result, u_strlen(result)); }
/** * Test currency "object" (we use this name to match the other C++ * test name and the Jave name). Actually, test ISO currency code * support in the C API. */ static void TestCurrencyObject(void) { UNumberFormat *currencyFmt; UChar *str=NULL, *res=NULL; int32_t lneed, i; UFieldPosition pos; UErrorCode status = U_ZERO_ERROR; const char* locale[]={ "fr_FR", "fr_FR", }; const char* currency[]={ "", "JPY", }; const char* result[]={ "1\\u202F234,56\\u00A0\\u20AC", "1\\u202F235\\u00A0JPY", }; log_verbose("\nTesting the number format with different currency codes\n"); for(i=0; i < 2; i++) { char cStr[20]={0}; UChar isoCode[16]={0}; currencyFmt = unum_open(UNUM_CURRENCY, NULL,0,locale[i],NULL, &status); if(U_FAILURE(status)){ log_data_err("Error in the construction of number format with style currency: %s (Are you missing data?)\n", myErrorName(status)); } else { if (*currency[i]) { u_uastrcpy(isoCode, currency[i]); unum_setTextAttribute(currencyFmt, UNUM_CURRENCY_CODE, isoCode, u_strlen(isoCode), &status); if(U_FAILURE(status)) { log_err("FAIL: can't set currency code %s\n", myErrorName(status) ); } } unum_getTextAttribute(currencyFmt, UNUM_CURRENCY_CODE, isoCode, sizeof(isoCode), &status); if(U_FAILURE(status)) { log_err("FAIL: can't get currency code %s\n", myErrorName(status) ); } u_UCharsToChars(isoCode,cStr,u_strlen(isoCode)); log_verbose("ISO code %s\n", cStr); if (*currency[i] && uprv_strcmp(cStr, currency[i])) { log_err("FAIL: currency should be %s, but is %s\n", currency[i], cStr); } lneed=0; lneed= unum_formatDouble(currencyFmt, 1234.56, NULL, lneed, NULL, &status); if(status==U_BUFFER_OVERFLOW_ERROR){ status=U_ZERO_ERROR; str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); pos.field = 0; unum_formatDouble(currencyFmt, 1234.56, str, lneed+1, &pos, &status); } if(U_FAILURE(status)) { log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) ); } else { res=(UChar*)malloc(sizeof(UChar) * (strlen(result[i])+1) ); u_unescape(result[i],res, (int32_t)(strlen(result[i])+1)); if (u_strcmp(str, res) != 0){ log_err("FAIL: Expected %s Got: %s for locale: %s\n", result[i],aescstrdup(str, -1),locale[i]); } } } unum_close(currencyFmt); free(str); free(res); } }
/** * Test localized currency patterns for PREEURO variants. */ static void TestCurrencyPreEuro(void) { UNumberFormat *currencyFmt; UChar *str=NULL, *res=NULL; int32_t lneed, i; UFieldPosition pos; UErrorCode status = U_ZERO_ERROR; const char* locale[]={ "ca_ES_PREEURO", "de_LU_PREEURO", "en_IE_PREEURO", "fi_FI_PREEURO", "fr_LU_PREEURO", "it_IT_PREEURO", "pt_PT_PREEURO", "de_AT_PREEURO", "el_GR_PREEURO", "es_ES_PREEURO", "fr_BE_PREEURO", "ga_IE_PREEURO", "nl_BE_PREEURO", "de_DE_PREEURO", "en_BE_PREEURO", "eu_ES_PREEURO", "fr_FR_PREEURO", "gl_ES_PREEURO", "nl_NL_PREEURO", }; const char* result[]={ "\\u20A7\\u00A02", "2\\u00A0F", "IEP\\u00A01.50", "1,50\\u00A0mk", "2\\u00A0F", "ITL\\u00A02", "1$50\\u00A0\\u200B", "\\u00F6S\\u00A01,50", "1,50\\u00A0\\u0394\\u03C1\\u03C7", "2\\u00A0\\u20A7", "1,50\\u00A0FB", "IEP\\u00A01.50", "BEF\\u00A01,50", "1,50\\u00A0DM", "1,50\\u00A0BEF", "\\u20A7\\u00A02", "1,50\\u00A0F", "2\\u00A0\\u20A7", "NLG\\u00A01,50" }; log_verbose("\nTesting the number format with different currency patterns\n"); for(i=0; i < 19; i++) { char curID[256] = {0}; uloc_canonicalize(locale[i], curID, 256, &status); if(U_FAILURE(status)){ log_data_err("Could not canonicalize %s. Error: %s (Are you missing data?)\n", locale[i], u_errorName(status)); continue; } currencyFmt = unum_open(UNUM_CURRENCY, NULL,0,curID,NULL, &status); if(U_FAILURE(status)){ log_data_err("Error in the construction of number format with style currency: %s (Are you missing data?)\n", myErrorName(status)); } else { lneed=0; lneed= unum_formatDouble(currencyFmt, 1.50, NULL, lneed, NULL, &status); if(status==U_BUFFER_OVERFLOW_ERROR){ status=U_ZERO_ERROR; str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); pos.field = 0; unum_formatDouble(currencyFmt, 1.50, str, lneed+1, &pos, &status); } if(U_FAILURE(status)) { log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) ); } else { res=(UChar*)malloc(sizeof(UChar) * (strlen(result[i])+1) ); u_unescape(result[i],res,(int32_t)(strlen(result[i])+1)); if (u_strcmp(str, res) != 0){ log_err("FAIL: Expected %s Got: %s for locale: %s\n", result[i],aescstrdup(str, -1),locale[i]); } } } unum_close(currencyFmt); free(str); free(res); } }
/** * Test the handling of the currency symbol in patterns. */ static void TestCurrencySign(void) { int32_t lneed; UNumberFormat *fmt; UChar *pattern=NULL; UChar *str=NULL; UChar *pat=NULL; UChar *res=NULL; UErrorCode status = U_ZERO_ERROR; char tempBuf[256]; pattern=(UChar*)malloc(sizeof(UChar) * (strlen("*#,##0.00;-*#,##0.00") + 1) ); u_uastrcpy(pattern, "*#,##0.00;-*#,##0.00"); pattern[0]=pattern[11]=0xa4; /* insert latin-1 currency symbol */ fmt = unum_open(UNUM_IGNORE,pattern, u_strlen(pattern), "en_US",NULL, &status); if(U_FAILURE(status)){ log_err_status(status, "Error in number format construction with pattern \"\\xA4#,##0.00;-\\xA4#,##0.00\\\" -> %s\n", u_errorName(status)); } lneed=0; lneed=unum_formatDouble(fmt, 1234.56, NULL, lneed, NULL, &status); if(status==U_BUFFER_OVERFLOW_ERROR){ status=U_ZERO_ERROR; str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); unum_formatDouble(fmt, 1234.56, str, lneed+1, NULL, &status); } if(U_FAILURE(status)) { log_err_status(status, "Error in formatting using unum_format(.....): %s\n", myErrorName(status) ); } lneed=0; lneed=unum_toPattern(fmt, FALSE, NULL, lneed, &status); if(status==U_BUFFER_OVERFLOW_ERROR){ status=U_ZERO_ERROR; pat=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); unum_formatDouble(fmt, FALSE, pat, lneed+1, NULL, &status); } log_verbose("Pattern \" %s \" \n", u_austrcpy(tempBuf, pat)); log_verbose("Format 1234.56 -> %s\n", u_austrcpy(tempBuf, str) ); if(U_SUCCESS(status) && str) { res=(UChar*)malloc(sizeof(UChar) * (strlen("$1,234.56")+1) ); u_uastrcpy(res, "$1,234.56"); if (u_strcmp(str, res) !=0) log_data_err("FAIL: Expected $1,234.56\n"); } else { log_err_status(status, "Error formatting -> %s\n", u_errorName(status)); } free(str); free(res); free(pat); lneed=0; lneed=unum_formatDouble(fmt, -1234.56, NULL, lneed, NULL, &status); if(status==U_BUFFER_OVERFLOW_ERROR){ status=U_ZERO_ERROR; str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); unum_formatDouble(fmt, -1234.56, str, lneed+1, NULL, &status); } if(U_FAILURE(status)) { log_err_status(status, "Error in formatting using unum_format(.....): %s\n", myErrorName(status) ); } if(str) { res=(UChar*)malloc(sizeof(UChar) * (strlen("-$1,234.56")+1) ); u_uastrcpy(res, "-$1,234.56"); if (u_strcmp(str, res) != 0) log_data_err("FAIL: Expected -$1,234.56\n"); free(str); free(res); } unum_close(fmt); free(pattern); }
/* Test exponential pattern*/ static void TestExponential(void) { int32_t pat_length, val_length, lval_length; int32_t ival, ilval, p, v, lneed; UNumberFormat *fmt; int32_t ppos; UChar *upat; UChar pattern[20]; UChar *str=NULL; UChar uvalfor[20], ulvalfor[20]; char tempMsgBug[256]; double a; UErrorCode status = U_ZERO_ERROR; #if U_PLATFORM == U_PF_OS390 static const double val[] = { 0.01234, 123456789, 1.23e75, -3.141592653e-78 }; #else static const double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 }; #endif static const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" }; static const int32_t lval[] = { 0, -1, 1, 123456789 }; static const char* valFormat[] = { "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271", "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272", "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273", "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]" }; static const char* lvalFormat[] = { "0E0", "-1E0", "1E0", "1.2346E8", "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07", "0E000", "-1E000", "1E000", "123.4568E006", "0E0", "[1E0]", "1E0", "1.235E8" }; static const double valParse[] = { #if U_PLATFORM == U_PF_OS390 0.01234, 123460000, 1.23E75, -3.1416E-78, 0.01234, 123460000, 1.23E75, -3.1416E-78, 0.01234, 123456800, 1.23E75, -3.141593E-78, 0.01234, 123500000, 1.23E75, -3.142E-78 #else /* We define the whole IEEE 754 number in the 4th column because Visual Age 7 has a bug in rounding numbers. */ 0.01234, 123460000, 1.23E300, -3.1415999999999999E-271, 0.01234, 123460000, 1.23E300, -3.1415999999999999E-271, 0.01234, 123456800, 1.23E300, -3.1415929999999999E-271, 0.01234, 123500000, 1.23E300, -3.1420000000000001E-271 #endif }; static const int32_t lvalParse[] = { 0, -1, 1, 123460000, 0, -1, 1, 123460000, 0, -1, 1, 123456800, 0, -1, 1, 123500000 }; pat_length = UPRV_LENGTHOF(pat); val_length = UPRV_LENGTHOF(val); lval_length = UPRV_LENGTHOF(lval); ival = 0; ilval = 0; for (p=0; p < pat_length; ++p) { upat=(UChar*)malloc(sizeof(UChar) * (strlen(pat[p])+1) ); u_uastrcpy(upat, pat[p]); fmt=unum_open(UNUM_IGNORE,upat, u_strlen(upat), "en_US",NULL, &status); if (U_FAILURE(status)) { log_err_status(status, "FAIL: Bad status returned by Number format construction with pattern %s -> %s\n", pat[p], u_errorName(status)); continue; } lneed= u_strlen(upat) + 1; unum_toPattern(fmt, FALSE, pattern, lneed, &status); log_verbose("Pattern \" %s \" -toPattern-> \" %s \" \n", upat, u_austrcpy(tempMsgBug, pattern) ); for (v=0; v<val_length; ++v) { /*format*/ lneed=0; lneed=unum_formatDouble(fmt, val[v], NULL, lneed, NULL, &status); if(status==U_BUFFER_OVERFLOW_ERROR){ status=U_ZERO_ERROR; str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); unum_formatDouble(fmt, val[v], str, lneed+1, NULL, &status); } if(U_FAILURE(status)) { log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) ); } u_uastrcpy(uvalfor, valFormat[v+ival]); if(u_strcmp(str, uvalfor) != 0) log_verbose("FAIL: Expected %s ( %s )\n", valFormat[v+ival], u_austrcpy(tempMsgBug, uvalfor) ); /*parsing*/ ppos=0; a=unum_parseDouble(fmt, str, u_strlen(str), &ppos, &status); if (ppos== u_strlen(str)) { if (a != valParse[v+ival]) log_err("FAIL: Expected: %e, Got: %g\n", valParse[v+ival], a); } else log_err(" FAIL: Partial parse ( %d chars ) -> %e\n", ppos, a); free(str); } for (v=0; v<lval_length; ++v) { /*format*/ lneed=0; lneed=unum_formatDouble(fmt, lval[v], NULL, lneed, NULL, &status); if(status==U_BUFFER_OVERFLOW_ERROR){ status=U_ZERO_ERROR; str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); unum_formatDouble(fmt, lval[v], str, lneed+1, NULL, &status); } if(U_FAILURE(status)) { log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) ); } /*printf(" Format %e -> %s\n", lval[v], austrdup(str) );*/ u_uastrcpy(ulvalfor, lvalFormat[v+ilval]); if(u_strcmp(str, ulvalfor) != 0) log_err("FAIL: Expected %s ( %s )\n", valFormat[v+ilval], austrdup(ulvalfor) ); /*parsing*/ ppos=0; a=unum_parseDouble(fmt, str, u_strlen(str), &ppos, &status); if (ppos== u_strlen(str)) { /*printf(" Parse -> %e\n", a);*/ if (a != lvalParse[v+ilval]) log_err("FAIL: Expected : %e\n", valParse[v+ival]); } else log_err(" FAIL: Partial parse ( %d chars ) -> %e\n", ppos, a); free(str); } ival += val_length; ilval += lval_length; unum_close(fmt); free(upat); } }
static int32_t u_printf_spellout_handler(const u_printf_stream_handler *handler, void *context, ULocaleBundle *formatBundle, const u_printf_spec_info *info, const ufmt_args *args) { double num = (double) (args[0].doubleValue); UNumberFormat *format; UChar result[UPRINTF_BUFFER_SIZE]; UChar prefixBuffer[UPRINTF_BUFFER_SIZE]; int32_t prefixBufferLen = sizeof(prefixBuffer); int32_t minDecimalDigits; int32_t maxDecimalDigits; int32_t resultLen; UErrorCode status = U_ZERO_ERROR; prefixBuffer[0] = 0; /* mask off any necessary bits */ /* if(! info->fIsLongDouble) num &= DBL_MAX;*/ /* get the formatter */ format = u_locbund_getNumberFormat(formatBundle, UNUM_SPELLOUT); /* handle error */ if(format == 0) return 0; /* save the formatter's state */ minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS); maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS); /* set the appropriate flags and number of decimal digits on the formatter */ if(info->fPrecision != -1) { /* set the # of decimal digits */ unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision); } else if(info->fAlt) { /* '#' means always show decimal point */ /* copy of printf behavior on Solaris - '#' shows 6 digits */ unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6); } else { /* # of decimal digits is 6 if precision not specified */ unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6); } /* set whether to show the sign */ if (info->fShowSign) { u_printf_set_sign(format, info, prefixBuffer, &prefixBufferLen, &status); } /* format the number */ resultLen = unum_formatDouble(format, num, result, UPRINTF_BUFFER_SIZE, 0, &status); if (U_FAILURE(status)) { resultLen = 0; } /* restore the number format */ /* TODO: Is this needed? */ unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits); unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits); if (info->fShowSign) { /* Reset back to original value regardless of what the error was */ UErrorCode localStatus = U_ZERO_ERROR; u_printf_reset_sign(format, info, prefixBuffer, &prefixBufferLen, &localStatus); } return handler->pad_and_justify(context, info, result, resultLen); }
static int32_t u_printf_scientific_handler(const u_printf_stream_handler *handler, void *context, ULocaleBundle *formatBundle, const u_printf_spec_info *info, const ufmt_args *args) { double num = (double) (args[0].doubleValue); UNumberFormat *format; UChar result[UPRINTF_BUFFER_SIZE]; UChar prefixBuffer[UPRINTF_BUFFER_SIZE]; int32_t prefixBufferLen = sizeof(prefixBuffer); int32_t minDecimalDigits; int32_t maxDecimalDigits; UErrorCode status = U_ZERO_ERROR; UChar srcExpBuf[UPRINTF_SYMBOL_BUFFER_SIZE]; int32_t srcLen, expLen; int32_t resultLen; UChar expBuf[UPRINTF_SYMBOL_BUFFER_SIZE]; prefixBuffer[0] = 0; /* mask off any necessary bits */ /* if(! info->fIsLongDouble) num &= DBL_MAX;*/ /* get the formatter */ format = u_locbund_getNumberFormat(formatBundle, UNUM_SCIENTIFIC); /* handle error */ if(format == 0) return 0; /* set the appropriate flags on the formatter */ srcLen = unum_getSymbol(format, UNUM_EXPONENTIAL_SYMBOL, srcExpBuf, sizeof(srcExpBuf), &status); /* Upper/lower case the e */ if (info->fSpec == (UChar)0x65 /* e */) { expLen = u_strToLower(expBuf, (int32_t)sizeof(expBuf), srcExpBuf, srcLen, formatBundle->fLocale, &status); } else { expLen = u_strToUpper(expBuf, (int32_t)sizeof(expBuf), srcExpBuf, srcLen, formatBundle->fLocale, &status); } unum_setSymbol(format, UNUM_EXPONENTIAL_SYMBOL, expBuf, expLen, &status); /* save the formatter's state */ minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS); maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS); /* set the appropriate flags and number of decimal digits on the formatter */ if(info->fPrecision != -1) { /* set the # of decimal digits */ if (info->fOrigSpec == (UChar)0x65 /* e */ || info->fOrigSpec == (UChar)0x45 /* E */) { unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision); } else { unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, 1); unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, info->fPrecision); } } else if(info->fAlt) { /* '#' means always show decimal point */ /* copy of printf behavior on Solaris - '#' shows 6 digits */ unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6); } else { /* # of decimal digits is 6 if precision not specified */ unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6); } /* set whether to show the sign */ if (info->fShowSign) { u_printf_set_sign(format, info, prefixBuffer, &prefixBufferLen, &status); } /* format the number */ resultLen = unum_formatDouble(format, num, result, UPRINTF_BUFFER_SIZE, 0, &status); if (U_FAILURE(status)) { resultLen = 0; } /* restore the number format */ /* TODO: Is this needed? */ unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits); unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits); /* Since we're the only one using the scientific format, we don't need to save the old exponent value. */ /*unum_setSymbol(format, UNUM_EXPONENTIAL_SYMBOL, srcExpBuf, srcLen, &status);*/ if (info->fShowSign) { /* Reset back to original value regardless of what the error was */ UErrorCode localStatus = U_ZERO_ERROR; u_printf_reset_sign(format, info, prefixBuffer, &prefixBufferLen, &localStatus); } return handler->pad_and_justify(context, info, result, resultLen); }
/** * call-seq: * 23874.localize(:decimal, 'es_ES') => 23.874 */ VALUE rb_numeric_localize(int argc, VALUE *argv, VALUE self) { VALUE style, options; UNumberFormatStyle formatStyle; char *locale = NULL; UNumberFormat *format; UErrorCode status; UChar result[256]; /* arguments */ rb_scan_args(argc, argv, "02", &style, &options); if (style == Qnil) { formatStyle = UNUM_DECIMAL; } else { ID style_ID; Check_Type(style, T_SYMBOL); style_ID = SYM2ID(style); if (style_ID == rb_intern("decimal")) { formatStyle = UNUM_DECIMAL; } else if (style_ID == rb_intern("currency")) { formatStyle = UNUM_CURRENCY; } else if (style_ID == rb_intern("percent")) { formatStyle = UNUM_PERCENT; } else if (style_ID == rb_intern("scientific")) { formatStyle = UNUM_SCIENTIFIC; } else if (style_ID == rb_intern("spellout")) { formatStyle = UNUM_SPELLOUT; } else { rb_raise(rb_eArgError, "unsupported format style %s", rb_id2name(style_ID)); } } if (options != Qnil) { VALUE rb_locale; Check_Type(options, T_HASH); rb_locale = rb_hash_aref(options, ID2SYM(rb_intern("locale"))); if (rb_locale != Qnil) { locale = StringValuePtr(rb_locale); } } /* formatter */ status = U_ZERO_ERROR; format = unum_open(formatStyle, NULL, 0, locale, NULL, &status); RAISE_ON_ERROR(status); /* set format attributes */ if (options != Qnil) { VALUE currency, precision, round_mode, round_increment; switch (formatStyle) { case UNUM_CURRENCY: currency = rb_hash_aref(options, ID2SYM(rb_intern("currency"))); if (currency != Qnil) { UChar *uStr; int32_t uStrLen; uStr = u_strFromRString(currency, &uStrLen); status = U_ZERO_ERROR; unum_setTextAttribute(format, UNUM_CURRENCY_CODE, uStr, uStrLen, &status); RAISE_ON_ERROR(status); } case UNUM_DECIMAL: /* precision */ precision = rb_hash_aref(options, ID2SYM(rb_intern("precision"))); if (precision != Qnil) { Check_Type(precision, T_FIXNUM); status = U_ZERO_ERROR; unum_setAttribute(format, UNUM_FRACTION_DIGITS, NUM2INT(precision)); RAISE_ON_ERROR(status); } round_mode = rb_hash_aref(options, ID2SYM(rb_intern("round_mode"))); if (round_mode != Qnil) { ID round_mode_ID; UNumberFormatRoundingMode rounding_mode; Check_Type(round_mode, T_SYMBOL); round_mode_ID = SYM2ID(round_mode); if (round_mode_ID == rb_intern("ceil")) { rounding_mode = UNUM_ROUND_CEILING; } else if (round_mode_ID == rb_intern("floor")) { rounding_mode = UNUM_ROUND_FLOOR; } else if (round_mode_ID == rb_intern("down")) { rounding_mode = UNUM_ROUND_DOWN; } else if (round_mode_ID == rb_intern("up")) { rounding_mode = UNUM_ROUND_UP; } else if (round_mode_ID == rb_intern("halfeven")) { rounding_mode = UNUM_FOUND_HALFEVEN; } else if (round_mode_ID == rb_intern("halfdown")) { rounding_mode = UNUM_ROUND_HALFDOWN; } else if (round_mode_ID == rb_intern("halfup")) { rounding_mode = UNUM_ROUND_HALFUP; } else { rb_raise(rb_eArgError, "unsupported rounding mode '%s'", rb_id2name(round_mode_ID)); } status = U_ZERO_ERROR; unum_setAttribute(format, UNUM_ROUNDING_MODE, rounding_mode); RAISE_ON_ERROR(status); } round_increment = rb_hash_aref(options, ID2SYM(rb_intern("round_increment"))); if (round_increment != Qnil) { Check_Type(round_increment, T_FLOAT); status = U_ZERO_ERROR; unum_setDoubleAttribute(format, UNUM_ROUNDING_INCREMENT, NUM2DBL(round_increment)); RAISE_ON_ERROR(status); } } } /* format */ status = U_ZERO_ERROR; switch (TYPE(self)) { case T_FIXNUM: unum_format(format, NUM2INT(self), result, 256, NULL, &status); break; case T_FLOAT: unum_formatDouble(format, NUM2DBL(self), result, 256, NULL, &status); break; case T_BIGNUM: unum_formatInt64(format, rb_big2ll(self), result, 256, NULL, &status); break; } RAISE_ON_ERROR(status); /* free resources */ unum_close(format); return u_strToRString(result, -1); }