ICU-7892 add missing implementation for unum_parseDecimal() and unum_formatDecimal().

X-SVN-Rev: 28789
This commit is contained in:
Andy Heninger 2010-10-12 05:11:41 +00:00
parent a788c4e44c
commit 801abaa192
2 changed files with 180 additions and 3 deletions

View file

@ -26,6 +26,7 @@
#include "unicode/curramt.h"
#include "uassert.h"
#include "cpputils.h"
#include "cstring.h"
U_NAMESPACE_USE
@ -261,6 +262,51 @@ unum_formatDouble( const UNumberFormat* fmt,
return res.extract(result, resultLength, *status);
}
U_DRAFT int32_t U_EXPORT2
unum_formatDecimal(const UNumberFormat* fmt,
const char * number,
int32_t length,
UChar* result,
int32_t resultLength,
UFieldPosition *pos, /* 0 if ignore */
UErrorCode* status) {
if(U_FAILURE(*status)) {
return -1;
}
if ((result == NULL && resultLength != 0) || resultLength < 0) {
*status = U_ILLEGAL_ARGUMENT_ERROR;
return -1;
}
FieldPosition fp;
if(pos != 0) {
fp.setField(pos->field);
}
if (length < 0) {
length = uprv_strlen(number);
}
StringPiece numSP(number, length);
Formattable numFmtbl(numSP, *status);
UnicodeString resultStr;
if (resultLength > 0) {
// Alias the destination buffer.
resultStr.setTo(result, 0, resultLength);
}
((const NumberFormat*)fmt)->format(numFmtbl, resultStr, fp, *status);
if(pos != 0) {
pos->beginIndex = fp.getBeginIndex();
pos->endIndex = fp.getEndIndex();
}
return resultStr.extract(result, resultLength, *status);
}
U_CAPI int32_t U_EXPORT2
unum_formatDoubleCurrency(const UNumberFormat* fmt,
double number,
@ -370,6 +416,38 @@ unum_parseDouble( const UNumberFormat* fmt,
return res.getDouble(*status);
}
U_CAPI int32_t U_EXPORT2
unum_parseDecimal(const UNumberFormat* fmt,
const UChar* text,
int32_t textLength,
int32_t *parsePos /* 0 = start */,
char *outBuf,
int32_t outBufLength,
UErrorCode *status)
{
if (U_FAILURE(*status)) {
return -1;
}
if ((outBuf == NULL && outBufLength != 0) || outBufLength < 0) {
*status = U_ILLEGAL_ARGUMENT_ERROR;
return -1;
}
Formattable res;
parseRes(res, fmt, text, textLength, parsePos, FALSE, status);
StringPiece sp = res.getDecimalNumber(*status);
if (U_FAILURE(*status)) {
return -1;
} else if (sp.size() > outBufLength) {
*status = U_BUFFER_OVERFLOW_ERROR;
} else if (sp.size() == outBufLength) {
uprv_strncpy(outBuf, sp.data(), sp.size());
*status = U_STRING_NOT_TERMINATED_WARNING;
} else {
uprv_strcpy(outBuf, sp.data());
}
return sp.size();
}
U_CAPI double U_EXPORT2
unum_parseDoubleCurrency(const UNumberFormat* fmt,
const UChar* text,

View file

@ -24,8 +24,10 @@
#if !UCONFIG_NO_FORMATTING
#include "unicode/uloc.h"
#include "unicode/umisc.h"
#include "unicode/unum.h"
#include "unicode/ustring.h"
#include "cintltst.h"
#include "cnumtst.h"
#include "cmemory.h"
@ -98,9 +100,8 @@ static void TestInt64Parse()
UErrorCode st = U_ZERO_ERROR;
UErrorCode* status = &st;
char* st1 = "009223372036854775808";
const char* st1 = "009223372036854775808";
const int size = 21;
/*const int textLength = size;*/
UChar text[21];
@ -407,7 +408,8 @@ free(result);
}
/*
* Note: "for strict standard conformance all operations and constants are now supposed to be evaluated in precision of long double". So, we assign a1 before comparing to a double. Bug #7932.
* Note: "for strict standard conformance all operations and constants are now supposed to be
evaluated in precision of long double". So, we assign a1 before comparing to a double. Bug #7932.
*/
a1 = 462.12345;
@ -823,6 +825,103 @@ free(result);
}
unum_close(dec_en);
}
{ /* Test parse & format of big decimals. Use a number with too many digits to fit in a double,
to verify that it is taking the pure decimal path. */
UNumberFormat *fmt;
const char *bdpattern = "#,##0.#########";
const char *numInitial = "12345678900987654321.1234567896";
const char *numFormatted = "12,345,678,900,987,654,321.12345679";
const char *parseExpected = "12345678900987654321.12345679";
int32_t resultSize = 0;
int32_t parsePos = 0; /* Output parameter for Parse operations. */
#define DESTCAPACITY 100
UChar dest[DESTCAPACITY];
char desta[DESTCAPACITY];
UFieldPosition fieldPos = {0};
/* Format */
status = U_ZERO_ERROR;
u_uastrcpy(dest, bdpattern);
fmt = unum_open(UNUM_PATTERN_DECIMAL, dest, -1, "en", NULL /*parseError*/, &status);
if (U_FAILURE(status)) log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
resultSize = unum_formatDecimal(fmt, numInitial, -1, dest, DESTCAPACITY, NULL, &status);
if (U_FAILURE(status)) {
log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
}
u_austrncpy(desta, dest, DESTCAPACITY);
if (strcmp(numFormatted, desta) != 0) {
log_err("File %s, Line %d, (expected, acutal) = (\"%s\", \"%s\")\n",
__FILE__, __LINE__, numFormatted, desta);
}
if (strlen(numFormatted) != resultSize) {
log_err("File %s, Line %d, (expected, actual) = (%d, %d)\n",
__FILE__, __LINE__, strlen(numFormatted), resultSize);
}
/* Format with a FieldPosition parameter */
fieldPos.field = 2; /* Ticket 8034 - need enum constants for the field values. */
/* 2 = kDecimalSeparatorField */
resultSize = unum_formatDecimal(fmt, numInitial, -1, dest, DESTCAPACITY, &fieldPos, &status);
if (U_FAILURE(status)) {
log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
}
u_austrncpy(desta, dest, DESTCAPACITY);
if (strcmp(numFormatted, desta) != 0) {
log_err("File %s, Line %d, (expected, acutal) = (\"%s\", \"%s\")\n",
__FILE__, __LINE__, numFormatted, desta);
}
if (fieldPos.beginIndex != 26) { /* index of "." in formatted number */
log_err("File %s, Line %d, (expected, acutal) = (%d, %d)\n",
__FILE__, __LINE__, 0, fieldPos.beginIndex);
}
if (fieldPos.endIndex != 27) {
log_err("File %s, Line %d, (expected, acutal) = (%d, %d)\n",
__FILE__, __LINE__, 0, fieldPos.endIndex);
}
/* Parse */
status = U_ZERO_ERROR;
u_uastrcpy(dest, numFormatted); /* Parse the expected output of the formatting test */
resultSize = unum_parseDecimal(fmt, dest, -1, NULL, desta, DESTCAPACITY, &status);
if (U_FAILURE(status)) {
log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
}
if (strcmp(parseExpected, desta) != 0) {
log_err("File %s, Line %d, (expected, actual) = (\"%s\", \"%s\")\n",
__FILE__, __LINE__, parseExpected, desta);
}
if (strlen(parseExpected) != resultSize) {
log_err("File %s, Line %d, (expected, actual) = (%d, %d)\n",
__FILE__, __LINE__, strlen(parseExpected), resultSize);
}
/* Parse with a parsePos parameter */
status = U_ZERO_ERROR;
u_uastrcpy(dest, numFormatted); /* Parse the expected output of the formatting test */
parsePos = 3; /* 12,345,678,900,987,654,321.12345679 */
/* start parsing at the the third char */
resultSize = unum_parseDecimal(fmt, dest, -1, &parsePos, desta, DESTCAPACITY, &status);
if (U_FAILURE(status)) {
log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
}
if (strcmp(parseExpected+2, desta) != 0) { /* "345678900987654321.12345679" */
log_err("File %s, Line %d, (expected, actual) = (\"%s\", \"%s\")\n",
__FILE__, __LINE__, parseExpected+2, desta);
}
if (strlen(numFormatted) != parsePos) {
log_err("File %s, Line %d, parsePos (expected, actual) = (\"%d\", \"%d\")\n",
__FILE__, __LINE__, strlen(parseExpected), parsePos);
}
unum_close(fmt);
}
/*closing the NumberFormat() using unum_close(UNumberFormat*)")*/
unum_close(def);