ICU-329 First take on add better error reporting with UParseError struct.

X-SVN-Rev: 5472
This commit is contained in:
Ram Viswanadha 2001-08-16 00:55:16 +00:00
parent ae8bfdff08
commit d7d6c296e2
14 changed files with 1412 additions and 329 deletions

View file

@ -35,9 +35,9 @@
char ChoiceFormat::fgClassID = 0; // Value is irrelevant
UMTX ChoiceFormat::fgMutex = NULL; // lock for fgNumberFormat
//UMTX ChoiceFormat::fgMutex = NULL; // lock for fgNumberFormat
NumberFormat* ChoiceFormat::fgNumberFormat = 0;
//NumberFormat* ChoiceFormat::fgNumberFormat = 0;
inline double _getDouble(const Formattable& f) {
return (f.getType() == Formattable::kLong) ?
@ -113,6 +113,21 @@ ChoiceFormat::ChoiceFormat(const ChoiceFormat& that)
*this = that;
}
// -------------------------------------
// Private constructor that creates a
// ChoiceFormat instance based on the
// pattern and populates UParseError
ChoiceFormat::ChoiceFormat(const UnicodeString& newPattern,
UParseError& parseError,
UErrorCode& status)
: fChoiceLimits(0),
fClosures(0),
fChoiceFormats(0),
fCount(0)
{
applyPattern(newPattern,parseError, status);
}
// -------------------------------------
UBool
@ -172,7 +187,7 @@ ChoiceFormat::~ChoiceFormat()
// -------------------------------------
// NumberFormat cache management
/*
NumberFormat*
ChoiceFormat::getNumberFormat(UErrorCode &status)
{
@ -199,7 +214,8 @@ ChoiceFormat::getNumberFormat(UErrorCode &status)
return theFormat;
}
*/
/*
void
ChoiceFormat::releaseNumberFormat(NumberFormat *adopt)
{
@ -216,56 +232,41 @@ ChoiceFormat::releaseNumberFormat(NumberFormat *adopt)
delete adopt;
}
*/
/**
* Convert a string to a double value using a default NumberFormat object
* which is static (shared by all ChoiceFormat instances).
* Convert a string to a double value
*/
double
ChoiceFormat::stod(const UnicodeString& string,
UErrorCode& status)
{
// Use a shared global number format to convert a double value to
// or string or vice versa.
NumberFormat *myFormat = getNumberFormat(status);
if(U_FAILURE(status))
return -1; // OK?
Formattable result;
myFormat->parse(string, result, status);
releaseNumberFormat(myFormat);
double value = 0.0;
if (U_SUCCESS(status)) {
value = _getDouble(result);
if (uprv_isNaN(value)) {
status = U_ILLEGAL_ARGUMENT_ERROR;
}
}
return value;
char source[256] = { '\0' };
char* end;
u_UCharsToChars(string.getUChars(),source,string.length());
return uprv_strtod(source,&end);
}
// -------------------------------------
/**
* Convert a double value to a string using a default NumberFormat object
* which is static (shared by all ChoiceFormat instances).
* Convert a double value to a string
*/
UnicodeString&
ChoiceFormat::dtos(double value,
UnicodeString& string,
UErrorCode& status)
{
NumberFormat *myFormat = getNumberFormat(status);
if (U_SUCCESS(status)) {
FieldPosition fieldPos(0);
myFormat->format(value, string, fieldPos);
}
releaseNumberFormat(myFormat);
char temp[256] = {'\0'};
uprv_dtostr(value,temp,3,TRUE);
string = UnicodeString(temp);
return string;
}
#if 0
// -------------------------------------
// Applies the pattern to this ChoiceFormat instance.
@ -407,7 +408,167 @@ ChoiceFormat::applyPattern(const UnicodeString& pattern,
delete[] newFormats;
return;
}
#endif
// -------------------------------------
// calls the overloaded applyPattern method.
void
ChoiceFormat::applyPattern(const UnicodeString& pattern,
UErrorCode& status)
{
UParseError parseError;
applyPattern(pattern,parseError,status);
}
// -------------------------------------
// Applies the pattern to this ChoiceFormat instance.
void
ChoiceFormat::applyPattern(const UnicodeString& pattern,
UParseError& parseError,
UErrorCode& status)
{
if (U_FAILURE(status))
{
return;
}
// Clear error struct
parseError.offset = 0;
parseError.preContext[0] = parseError.postContext[0] = (UChar)0;
// Perform 2 passes. The first computes the number of limits in
// this pattern (fCount), which is 1 more than the number of
// literal VERTICAL_BAR characters.
int32_t count = 1;
int32_t i;
for (i=0; i<pattern.length(); ++i) {
UChar c = pattern[i];
if (c == SINGLE_QUOTE) {
// Skip over the entire quote, including embedded
// contiguous pairs of SINGLE_QUOTE.
for (;;) {
do {
++i;
} while (i<pattern.length() &&
pattern[i] != SINGLE_QUOTE);
if ((i+1)<pattern.length() &&
pattern[i+1] == SINGLE_QUOTE) {
// SINGLE_QUOTE pair; skip over it
++i;
} else {
break;
}
}
} else if (c == VERTICAL_BAR) {
++count;
}
}
// Allocate the required storage.
double *newLimits = new double[count];
UBool *newClosures = new UBool[count];
UnicodeString *newFormats = new UnicodeString[count];
// Perform the second pass
int32_t k = 0; // index into newXxx[] arrays
UnicodeString buf; // scratch buffer
UBool inQuote = FALSE;
UBool inNumber = TRUE; // TRUE before < or #, FALSE after
for (i=0; i<pattern.length(); ++i) {
UChar c = pattern[i];
if (c == SINGLE_QUOTE) {
// Check for SINGLE_QUOTE pair indicating a literal quote
if ((i+1) < pattern.length() &&
pattern[i+1] == SINGLE_QUOTE) {
buf += SINGLE_QUOTE;
++i;
} else {
inQuote = !inQuote;
}
} else if (inQuote) {
buf += c;
} else if (c == LESS_THAN || c == LESS_EQUAL || c == LESS_EQUAL2) {
if (!inNumber || buf.length() == 0) {
goto error;
}
inNumber = FALSE;
double limit;
buf.trim();
if (!buf.compare(fgPositiveInfinity, POSITIVE_INF_STRLEN)) {
limit = uprv_getInfinity();
} else if (!buf.compare(fgNegativeInfinity, NEGATIVE_INF_STRLEN)) {
limit = -uprv_getInfinity();
} else {
limit = stod(buf, status);
if (U_FAILURE(status)) {
goto error;
}
}
if (k == count) {
// This shouldn't happen. If it does, it means that
// the count determined in the first pass did not
// match the number of elements found in the second
// pass.
goto error;
}
newLimits[k] = limit;
newClosures[k] = (c == LESS_THAN);
if (k > 0 && limit <= newLimits[k-1]) {
// Each limit must be strictly > than the previous
// limit. One exception: Two subsequent limits may be
// == if the first closure is FALSE and the second
// closure is TRUE. This places the limit value in
// the second interval.
if (!(limit == newLimits[k-1] &&
!newClosures[k-1] &&
newClosures[k])) {
goto error;
}
}
buf.truncate(0);
} else if (c == VERTICAL_BAR) {
if (inNumber) {
goto error;
}
inNumber = TRUE;
newFormats[k] = buf;
++k;
buf.truncate(0);
} else {
buf += c;
}
}
if (k != (count-1) || inNumber || inQuote) {
goto error;
}
newFormats[k] = buf;
// Don't modify this object until the parse succeeds
delete[] fChoiceLimits;
delete[] fClosures;
delete[] fChoiceFormats;
fCount = count;
fChoiceLimits = newLimits;
fClosures = newClosures;
fChoiceFormats = newFormats;
return;
error:
//status = U_ILLEGAL_ARGUMENT_ERROR;
syntaxError(pattern,i,parseError,status);
delete[] newLimits;
delete[] newClosures;
delete[] newFormats;
return;
}
// -------------------------------------
// Reconstruct the original input pattern.
@ -473,7 +634,7 @@ ChoiceFormat::adoptChoices(double *limits,
UnicodeString *formats,
int32_t cnt )
{
adoptChoices(limits, 0, formats, cnt);
adoptChoices(limits, (UBool *)0, formats, cnt);
}
// -------------------------------------

View file

@ -65,6 +65,7 @@ static void debugout(UnicodeString s) {
// *****************************************************************************
char DecimalFormat::fgClassID = 0; // Value is irrelevan
UParseError DecimalFormat::fParseError;
// Constants for characters used in programmatic (unlocalized) patterns.
const UChar DecimalFormat::kPatternZeroDigit = 0x0030 /*'0'*/;
@ -103,7 +104,7 @@ DecimalFormat::DecimalFormat(UErrorCode& status)
fNegSuffixPattern(0),
fSymbols(0)
{
construct(status);
construct(status,fParseError);
}
//------------------------------------------------------------------------------
@ -119,7 +120,7 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern,
fNegSuffixPattern(0),
fSymbols(0)
{
construct(status, &pattern);
construct(status,fParseError, &pattern);
}
//------------------------------------------------------------------------------
@ -139,9 +140,24 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern,
{
if (symbolsToAdopt == NULL)
status = U_ILLEGAL_ARGUMENT_ERROR;
construct(status, &pattern, symbolsToAdopt);
construct(status,fParseError, &pattern, symbolsToAdopt);
}
DecimalFormat::DecimalFormat( const UnicodeString& pattern,
DecimalFormatSymbols* symbolsToAdopt,
UParseError& parseErr,
UErrorCode& status)
: NumberFormat(),
fPosPrefixPattern(0),
fPosSuffixPattern(0),
fNegPrefixPattern(0),
fNegSuffixPattern(0),
fSymbols(0)
{
if (symbolsToAdopt == NULL)
status = U_ILLEGAL_ARGUMENT_ERROR;
construct(status,parseErr, &pattern, symbolsToAdopt);
}
//------------------------------------------------------------------------------
// Constructs a DecimalFormat instance with the specified number format
// pattern and the number format symbols in the default locale. The
@ -157,7 +173,7 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern,
fNegSuffixPattern(0),
fSymbols(0)
{
construct(status, &pattern, new DecimalFormatSymbols(symbols));
construct(status,fParseError, &pattern, new DecimalFormatSymbols(symbols));
}
//------------------------------------------------------------------------------
@ -167,6 +183,7 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern,
void
DecimalFormat::construct(UErrorCode& status,
UParseError& parseErr,
const UnicodeString* pattern,
DecimalFormatSymbols* symbolsToAdopt,
const Locale& locale)
@ -192,7 +209,9 @@ DecimalFormat::construct(UErrorCode& status,
fMinExponentDigits = 0;
if (fSymbols == NULL)
{
fSymbols = new DecimalFormatSymbols(locale, status);
}
UnicodeString str;
// Uses the default locale's number format pattern if there isn't
@ -206,9 +225,11 @@ DecimalFormat::construct(UErrorCode& status,
}
if (U_FAILURE(status))
{
return;
applyPattern(*pattern, FALSE /*not localized*/, status);
}
applyPattern(*pattern, FALSE /*not localized*/,parseErr, status);
}
//------------------------------------------------------------------------------
@ -2151,15 +2172,36 @@ DecimalFormat::toPattern(UnicodeString& result, UBool localized) const
void
DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status)
{
applyPattern(pattern, FALSE, status);
UParseError parseError;
applyPattern(pattern, FALSE, parseError, status);
}
//------------------------------------------------------------------------------
void
DecimalFormat::applyPattern(const UnicodeString& pattern,
UParseError& parseError,
UErrorCode& status)
{
applyPattern(pattern, FALSE, parseError, status);
}
//------------------------------------------------------------------------------
void
DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status)
{
applyPattern(pattern, TRUE, status);
UParseError parseError;
applyPattern(pattern, TRUE,parseError,status);
}
//------------------------------------------------------------------------------
void
DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern,
UParseError& parseError,
UErrorCode& status)
{
applyPattern(pattern, TRUE,parseError,status);
}
//------------------------------------------------------------------------------
@ -2167,10 +2209,17 @@ DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& s
void
DecimalFormat::applyPattern(const UnicodeString& pattern,
UBool localized,
UParseError& parseError,
UErrorCode& status)
{
if (U_FAILURE(status))
{
return;
}
// Clear error struct
parseError.offset = 0;
parseError.preContext[0] = parseError.postContext[0] = (UChar)0;
// Set the significant pattern symbols
UChar zeroDigit = kPatternZeroDigit;
UChar groupingSeparator = kPatternGroupingSeparator;
@ -2263,7 +2312,7 @@ DecimalFormat::applyPattern(const UnicodeString& pattern,
if (digitRightCount > 0) {
// Unexpected '0'
debug("Unexpected '0'")
status = U_ILLEGAL_ARGUMENT_ERROR;
syntaxError(pattern,pos,parseError,status);
return;
}
++zeroDigitCount;
@ -2280,7 +2329,7 @@ DecimalFormat::applyPattern(const UnicodeString& pattern,
if (decimalPos >= 0) {
// Grouping separator after decimal
debug("Grouping separator after decimal")
status = U_ILLEGAL_ARGUMENT_ERROR;
syntaxError(pattern,pos,parseError,status);
return;
}
groupingCount2 = groupingCount;
@ -2289,7 +2338,7 @@ DecimalFormat::applyPattern(const UnicodeString& pattern,
if (decimalPos >= 0) {
// Multiple decimal separators
debug("Multiple decimal separators")
status = U_ILLEGAL_ARGUMENT_ERROR;
syntaxError(pattern,pos,parseError,status);
return;
}
// Intentionally incorporate the digitRightCount,
@ -2301,13 +2350,13 @@ DecimalFormat::applyPattern(const UnicodeString& pattern,
if (expDigits >= 0) {
// Multiple exponential symbols
debug("Multiple exponential symbols")
status = U_ILLEGAL_ARGUMENT_ERROR;
syntaxError(pattern,pos,parseError,status);
return;
}
if (groupingCount >= 0) {
// Grouping separator in exponential pattern
debug("Grouping separator in exponential pattern")
status = U_ILLEGAL_ARGUMENT_ERROR;
syntaxError(pattern,pos,parseError,status);
return;
}
// Check for positive prefix
@ -2328,7 +2377,7 @@ DecimalFormat::applyPattern(const UnicodeString& pattern,
expDigits < 1) {
// Malformed exponential pattern
debug("Malformed exponential pattern")
status = U_ILLEGAL_ARGUMENT_ERROR;
syntaxError(pattern,pos,parseError,status);
return;
}
}
@ -2387,7 +2436,7 @@ DecimalFormat::applyPattern(const UnicodeString& pattern,
if (subpart == 1 || part == 1) {
// Unexpected separator
debug("Unexpected separator")
status = U_ILLEGAL_ARGUMENT_ERROR;
syntaxError(pattern,pos,parseError,status);
return;
}
sub2Limit = pos;
@ -2398,7 +2447,7 @@ DecimalFormat::applyPattern(const UnicodeString& pattern,
if (multiplier != 1) {
// Too many percent/perMill characters
debug("Too many percent/perMill characters")
status = U_ILLEGAL_ARGUMENT_ERROR;
syntaxError(pattern,pos,parseError,status);
return;
}
affix->append(kQuote); // Encode percent/perMill
@ -2414,7 +2463,7 @@ DecimalFormat::applyPattern(const UnicodeString& pattern,
if (padPos >= 0 || // Multiple pad specifiers
(pos+1) == pattern.length()) { // Nothing after padEscape
debug("Multiple pad specifiers")
status = U_ILLEGAL_ARGUMENT_ERROR;
syntaxError(pattern,pos,parseError,status);
return;
}
padPos = pos;
@ -2494,7 +2543,7 @@ DecimalFormat::applyPattern(const UnicodeString& pattern,
groupingCount == 0 || groupingCount2 == 0 ||
subpart > 2) { // subpart > 2 == unmatched quote
debug("Syntax error")
status = U_ILLEGAL_ARGUMENT_ERROR;
syntaxError(pattern,pos,parseError,status);
return;
}
@ -2511,7 +2560,7 @@ DecimalFormat::applyPattern(const UnicodeString& pattern,
} else {
// Illegal pad position
debug("Illegal pad position")
status = U_ILLEGAL_ARGUMENT_ERROR;
syntaxError(pattern,pos,parseError,status);
return;
}
}

View file

@ -20,7 +20,7 @@
// *****************************************************************************
#include "unicode/format.h"
// *****************************************************************************
// class Format
// *****************************************************************************
@ -98,5 +98,31 @@ Format::operator==(const Format& /*that*/) const
// Add this implementation to make linker happy.
return TRUE;
}
//------------------------------------------------------------------------------
// handle syntax errors
inline void
Format::syntaxError(const UnicodeString& pattern,
int32_t pos,
UParseError& parseError,
UErrorCode& status){
parseError.offset = pos;
// for pre-context
int32_t start = (pos <=U_PARSE_CONTEXT_LEN)? 0 : (pos - U_PARSE_CONTEXT_LEN);
int32_t stop = pos;
pattern.extract(start,stop,parseError.preContext,0);
//null terminate the buffer
parseError.preContext[stop-start] = 0;
//for post-context
start = pos;
stop = ((pos+U_PARSE_CONTEXT_LEN)<=pattern.length()) ? (pos+U_PARSE_CONTEXT_LEN) :
pattern.length();
pattern.extract(start,stop,parseError.postContext,0);
//null terminate the buffer
parseError.postContext[stop-start]= 0;
status = U_PARSE_ERROR;
}
//eof

View file

@ -302,10 +302,6 @@ SOURCE=.\ucol_elm.cpp
# End Source File
# Begin Source File
SOURCE=.\ucol_sol.c
# End Source File
# Begin Source File
SOURCE=.\ucol_tok.cpp
# End Source File
# Begin Source File
@ -1402,10 +1398,6 @@ SOURCE=.\ucol_imp.h
# End Source File
# Begin Source File
SOURCE=.\ucol_sol.h
# End Source File
# Begin Source File
SOURCE=.\ucol_tok.h
# End Source File
# Begin Source File
@ -1495,10 +1487,6 @@ InputPath=.\unicode\umsg.h
# End Source File
# Begin Source File
SOURCE=.\umsg_imp.h
# End Source File
# Begin Source File
SOURCE=.\unicode\uni2name.h
!IF "$(CFG)" == "i18n - Win32 Release"

View file

@ -24,9 +24,10 @@
#include "unicode/datefmt.h"
#include "unicode/smpdtfmt.h"
#include "unicode/choicfmt.h"
#include "mutex.h"
//#include "mutex.h"
#include "unicode/ustring.h"
#include "umsg_imp.h"
#include "unicode/ucnv_err.h"
// *****************************************************************************
// class MessageFormat
@ -40,9 +41,72 @@
// -------------------------------------
char MessageFormat::fgClassID = 0; // Value is irrelevant
//---------------------------------------
// static data
static const UChar g_umsg_number[] = {
0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0 /* "number" */
};
static const UChar g_umsg_date[] = {
0x64, 0x61, 0x74, 0x65, 0 /* "date" */
};
static const UChar g_umsg_time[] = {
0x74, 0x69, 0x6D, 0x65, 0 /* "time" */
};
static const UChar g_umsg_choice[] = {
0x63, 0x68, 0x6F, 0x69, 0x63, 0x65, 0 /* "choice" */
};
// MessageFormat Type List Number, Date, Time or Choice
static const UChar *g_umsgTypeList[] = {
NULL, NULL, g_umsg_number,
NULL, g_umsg_date, NULL,
g_umsg_time, NULL, g_umsg_choice
};
static const UChar g_umsg_currency[] = {
0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x63, 0x79, 0 /* "currency" */
};
static const UChar g_umsg_percent[] = {
0x70, 0x65, 0x72, 0x63, 0x65, 0x6E, 0x74, 0 /* "percent" */
};
static const UChar g_umsg_integer[] = {
0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0 /* "integer" */
};
// NumberFormat modifier list, default, currency, percent or integer
static const UChar *g_umsgModifierList[] = {
NULL, NULL, g_umsg_currency,
NULL, g_umsg_percent, NULL,
g_umsg_integer, NULL, NULL
};
static const UChar g_umsg_short[] = {
0x73, 0x68, 0x6F, 0x72, 0x74, 0 /* "short" */
};
static const UChar g_umsg_medium[] = {
0x6D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0 /* "medium" */
};
static const UChar g_umsg_long[] = {
0x6C, 0x6F, 0x6E, 0x67, 0 /* "long" */
};
static const UChar g_umsg_full[] = {
0x66, 0x75, 0x6C, 0x6C, 0 /* "full" */
};
// DateFormat modifier list, default, short, medium, long or full
static const UChar *g_umsgDateModifierList[] = {
NULL, NULL, g_umsg_short,
NULL, g_umsg_medium, NULL,
g_umsg_long, NULL, g_umsg_full
};
static const int32_t g_umsgListLength = 9;
//--------------------------------------
// This global NumberFormat instance is shared by all MessageFormat to
// convert a number to(format)/from(parse) a string.
NumberFormat* MessageFormat::fgNumberFormat = 0;
//NumberFormat* MessageFormat::fgNumberFormat = 0;
// -------------------------------------
// Creates a MessageFormat instance based on the pattern.
@ -51,10 +115,9 @@ MessageFormat::MessageFormat(const UnicodeString& pattern,
UErrorCode& success)
: fLocale(Locale::getDefault()), // Uses the default locale
fOffsets(NULL),
fCount(0),
fCount(kMaxFormat),
fArgumentNumbers(NULL)
{
fCount = kMaxFormat;
fOffsets = new int32_t[fCount];
fArgumentNumbers = new int32_t[fCount];
for (int32_t i = 0; i < fCount; i++) {
@ -84,6 +147,26 @@ MessageFormat::MessageFormat(const UnicodeString& pattern,
applyPattern(pattern, success);
}
MessageFormat::MessageFormat(const UnicodeString& pattern,
const Locale& newLocale,
UParseError& parseError,
UErrorCode& success)
: fLocale(newLocale), // Uses the default locale
fOffsets(NULL),
fCount(0),
fArgumentNumbers(NULL)
{
fCount = kMaxFormat;
fOffsets = new int32_t[fCount];
fArgumentNumbers = new int32_t[fCount];
for (int32_t i = 0; i < fCount; i++) {
fFormats[i] = NULL; // Format instances
fOffsets[i] = 0; // Starting offset
fArgumentNumbers[i] = 0; // Argument numbers.
}
applyPattern(pattern,parseError, success);
}
MessageFormat::~MessageFormat()
{
for (int32_t i = 0; i < fCount; i++)
@ -203,7 +286,9 @@ MessageFormat::getLocale() const
{
return fLocale;
}
#if 0
// -------------------------------------
// Applies the new pattern and returns an error if the pattern
// is not correct.
@ -287,7 +372,103 @@ MessageFormat::applyPattern(const UnicodeString& newPattern,
}
fPattern = segments[0];
}
#endif
void
MessageFormat::applyPattern(const UnicodeString& newPattern,
UErrorCode& status)
{
UParseError parseError;
applyPattern(newPattern,parseError,status);
}
void
MessageFormat::applyPattern(const UnicodeString& newPattern,
UParseError& parseError,
UErrorCode& success)
{
if(U_FAILURE(success))
{
return;
}
UnicodeString segments[4];
int32_t part = 0;
int32_t formatNumber = 0;
UBool inQuote = FALSE;
int32_t braceStack = 0;
fMaxOffset = -1;
// Clear error struct
parseError.offset = 0;
parseError.preContext[0] = parseError.postContext[0] = (UChar)0;
int i = 0;
for (; i < newPattern.length(); ++i) {
UChar ch = newPattern[i];
if (part == 0) {
if (ch == SINGLE_QUOTE) {
if (i + 1 < newPattern.length()
&& newPattern[i+1] == SINGLE_QUOTE) {
segments[part] += ch; // handle doubles
++i;
} else {
inQuote = !inQuote;
}
} else if (ch == LEFT_CURLY_BRACE && !inQuote) {
part = 1;
} else {
segments[part] += ch;
}
} else if (inQuote) { // just copy quotes in parts
segments[part] += ch;
if (ch == SINGLE_QUOTE) {
inQuote = FALSE;
}
} else {
switch (ch) {
case COMMA:
if (part < 3)
part += 1;
else
segments[part] += ch;
break;
case LEFT_CURLY_BRACE:
++braceStack;
segments[part] += ch;
break;
case RIGHT_CURLY_BRACE:
if (braceStack == 0) {
part = 0;
makeFormat(/*i,*/ formatNumber, segments, parseError,success);
if(U_FAILURE(success)){
parseError.offset=i;
return;
}
formatNumber++;
} else {
--braceStack;
segments[part] += ch;
}
break;
case SINGLE_QUOTE:
inQuote = TRUE;
// fall through, so we keep quotes in other parts
default:
segments[part] += ch;
break;
}
}
}
if (braceStack == 0 && part != 0) {
fMaxOffset = -1;
syntaxError(newPattern,i,parseError,success);
return;
//throw new IllegalArgumentException("Unmatched braces in the pattern.");
}
fPattern = segments[0];
fListCount = formatNumber;
}
// -------------------------------------
// Converts this MessageFormat instance to a pattern.
UnicodeString&
@ -693,64 +874,6 @@ MessageFormat::format(const Formattable* arguments,
return result;
}
extern const UChar g_umsg_number[] = {
0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0 /* "number" */
};
extern const UChar g_umsg_date[] = {
0x64, 0x61, 0x74, 0x65, 0 /* "date" */
};
extern const UChar g_umsg_time[] = {
0x74, 0x69, 0x6D, 0x65, 0 /* "time" */
};
extern const UChar g_umsg_choice[] = {
0x63, 0x68, 0x6F, 0x69, 0x63, 0x65, 0 /* "choice" */
};
// MessageFormat Type List Number, Date, Time or Choice
extern const UChar *g_umsgTypeList[] = {
NULL, NULL, g_umsg_number,
NULL, g_umsg_date, NULL,
g_umsg_time, NULL, g_umsg_choice
};
extern const UChar g_umsg_currency[] = {
0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x63, 0x79, 0 /* "currency" */
};
extern const UChar g_umsg_percent[] = {
0x70, 0x65, 0x72, 0x63, 0x65, 0x6E, 0x74, 0 /* "percent" */
};
extern const UChar g_umsg_integer[] = {
0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0 /* "integer" */
};
// NumberFormat modifier list, default, currency, percent or integer
extern const UChar *g_umsgModifierList[] = {
NULL, NULL, g_umsg_currency,
NULL, g_umsg_percent, NULL,
g_umsg_integer, NULL, NULL
};
extern const UChar g_umsg_short[] = {
0x73, 0x68, 0x6F, 0x72, 0x74, 0 /* "short" */
};
extern const UChar g_umsg_medium[] = {
0x6D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0 /* "medium" */
};
extern const UChar g_umsg_long[] = {
0x6C, 0x6F, 0x6E, 0x67, 0 /* "long" */
};
extern const UChar g_umsg_full[] = {
0x66, 0x75, 0x6C, 0x6C, 0 /* "full" */
};
// DateFormat modifier list, default, short, medium, long or full
extern const UChar *g_umsgDateModifierList[] = {
NULL, NULL, g_umsg_short,
NULL, g_umsg_medium, NULL,
g_umsg_long, NULL, g_umsg_full
};
extern const int32_t g_umsgListLength = 9;
// -------------------------------------
// Parses the source pattern and returns the Formattable objects array,
@ -894,6 +1017,7 @@ MessageFormat::parseObject( const UnicodeString& source,
// -------------------------------------
// NumberFormat cache management
/*
NumberFormat*
MessageFormat::getNumberFormat(UErrorCode &status)
{
@ -937,7 +1061,7 @@ MessageFormat::releaseNumberFormat(NumberFormat *adopt)
delete adopt;
}
*/
/**
* Converts a string to an integer value using a default NumberFormat object
@ -948,6 +1072,7 @@ int32_t
MessageFormat::stoi(const UnicodeString& string,
UErrorCode& status)
{
/*
NumberFormat *myFormat = getNumberFormat(status);
if(U_FAILURE(status))
@ -965,6 +1090,21 @@ MessageFormat::stoi(const UnicodeString& string,
return value;
*/
/* this ignores any white spaces between '{' and digit char
* so now we can have { 0, date} {0 , date }
*/
for(int i=0;i<string.length();i++){
UChar32 ch = string.char32At(i);
if(u_isdigit(ch)){
return u_charDigitValue(ch);
}else if(!u_isspace(ch)){
break;
}
}
return -1;
}
// -------------------------------------
@ -978,11 +1118,12 @@ UnicodeString&
MessageFormat::itos(int32_t i,
UnicodeString& string)
{
/*
UErrorCode status = U_ZERO_ERROR;
NumberFormat *myFormat = getNumberFormat(status);
if(U_FAILURE(status)) {
/* "<ERROR>" */
// "<ERROR>"
static const UChar ERROR[] = {0x3C, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x3E, 0};
return string = ERROR; // TODO: maybe toPattern should take an errorcode.
@ -991,8 +1132,12 @@ MessageFormat::itos(int32_t i,
UnicodeString &retval = myFormat->format(i, string);
releaseNumberFormat(myFormat);
return retval;
*/
UChar temp[10] = { '\0' };
uprv_itou(temp,i,16,0);
string.append(temp);
return string;
}
// -------------------------------------
@ -1002,6 +1147,7 @@ void
MessageFormat::makeFormat(/*int32_t position, */
int32_t offsetNumber,
UnicodeString* segments,
UParseError& parseError,
UErrorCode& success)
{
if(U_FAILURE(success))
@ -1018,14 +1164,18 @@ MessageFormat::makeFormat(/*int32_t position, */
fMaxOffset = offsetNumber;
fOffsets[offsetNumber] = segments[0].length();
fArgumentNumbers[offsetNumber] = argumentNumber;
int test = 0;
// now get the format
Format *newFormat = NULL;
switch (findKeyword(segments[2], g_umsgTypeList)) {
case 0:
fFormatTypeList[argumentNumber] = Formattable::kString;
break;
case 1: case 2:// number
switch (findKeyword(segments[3], g_umsgModifierList)) {
test=findKeyword(segments[3], g_umsgModifierList);
fFormatTypeList[argumentNumber] = Formattable::kDouble;
switch (test) {
case 0: // default;
newFormat = NumberFormat::createInstance(fLocale, success);
break;
@ -1036,6 +1186,7 @@ MessageFormat::makeFormat(/*int32_t position, */
newFormat = NumberFormat::createPercentInstance(fLocale, success);
break;
case 5: case 6:// integer
fFormatTypeList[argumentNumber] = Formattable::kLong;
newFormat = createIntegerFormat(fLocale, success);
break;
default: // pattern
@ -1044,11 +1195,11 @@ MessageFormat::makeFormat(/*int32_t position, */
newFormat = NULL;
return;
}
if(newFormat->getDynamicClassID() == DecimalFormat::getStaticClassID())
((DecimalFormat*)newFormat)->applyPattern(segments[3], success);
if(newFormat->getDynamicClassID() == DecimalFormat::getStaticClassID()){
((DecimalFormat*)newFormat)->applyPattern(segments[3],parseError,success);
}
if(U_FAILURE(success)) {
fMaxOffset = oldMaxOffset;
success = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
break;
@ -1056,6 +1207,8 @@ MessageFormat::makeFormat(/*int32_t position, */
break;
case 3: case 4: // date
fFormatTypeList[argumentNumber] = Formattable::kDate;
switch (findKeyword(segments[3], g_umsgDateModifierList)) {
case 0: // default
newFormat = DateFormat::createDateInstance(DateFormat::kDefault, fLocale);
@ -1074,17 +1227,24 @@ MessageFormat::makeFormat(/*int32_t position, */
break;
default:
newFormat = DateFormat::createDateInstance(DateFormat::kDefault, fLocale);
if(newFormat->getDynamicClassID() == SimpleDateFormat::getStaticClassID())
if(newFormat->getDynamicClassID() == SimpleDateFormat::getStaticClassID()){
((SimpleDateFormat*)newFormat)->applyPattern(segments[3]);
}
/* Ram: 'success' is not passed to above methods
and is not set so we donot have to check for failure.
if(U_FAILURE(success)) {
fMaxOffset = oldMaxOffset;
success = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
*/
break;
}
break;
case 5: case 6:// time
fFormatTypeList[argumentNumber]= Formattable::kDate;
switch (findKeyword(segments[3], g_umsgDateModifierList)) {
case 0: // default
newFormat = DateFormat::createTimeInstance(DateFormat::kDefault, fLocale);
@ -1103,21 +1263,26 @@ MessageFormat::makeFormat(/*int32_t position, */
break;
default:
newFormat = DateFormat::createTimeInstance(DateFormat::kDefault, fLocale);
if(newFormat->getDynamicClassID() == SimpleDateFormat::getStaticClassID())
if(newFormat->getDynamicClassID() == SimpleDateFormat::getStaticClassID()){
((SimpleDateFormat*)newFormat)->applyPattern(segments[3]);
}
/* Ram: 'success' is not passed to above methods
and is not set so we donot have to check for failure.
if(U_FAILURE(success)) {
fMaxOffset = oldMaxOffset;
success = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
*/
break;
}
break;
case 7: case 8:// choice
newFormat = new ChoiceFormat(segments[3], success);
fFormatTypeList[argumentNumber] = Formattable::kDouble;
newFormat = new ChoiceFormat(segments[3],parseError,success);
if(U_FAILURE(success)) {
fMaxOffset = oldMaxOffset;
success = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
break;

View file

@ -468,16 +468,16 @@ int32_t RuleHalf::parse(const UnicodeString& rule, int32_t pos, int32_t limit) {
}
if (anchorEnd) {
// Text after a presumed end anchor is a syntax err
return syntaxError(RuleBasedTransliterator::MALFORMED_VARIABLE_REFERENCE, rule, start);
return syntaxError(U_MALFORMED_VARIABLE_REFERENCE, rule, start);
}
// Handle escapes
if (c == ESCAPE) {
if (pos == limit) {
return syntaxError(RuleBasedTransliterator::TRAILING_BACKSLASH, rule, start);
return syntaxError(U_TRAILING_BACKSLASH, rule, start);
}
UChar32 escaped = rule.unescapeAt(pos); // pos is already past '\\'
if (escaped == (UChar32) -1) {
return syntaxError(RuleBasedTransliterator::MALFORMED_UNICODE_ESCAPE, rule, start);
return syntaxError(U_MALFORMED_UNICODE_ESCAPE, rule, start);
}
buf.append(escaped);
continue;
@ -498,7 +498,7 @@ int32_t RuleHalf::parse(const UnicodeString& rule, int32_t pos, int32_t limit) {
quoteStart = buf.length();
for (;;) {
if (iq < 0) {
return syntaxError(RuleBasedTransliterator::UNTERMINATED_QUOTE, rule, start);
return syntaxError(U_UNTERMINATED_QUOTE, rule, start);
}
scratch.truncate(0);
rule.extractBetween(pos, iq, scratch);
@ -521,7 +521,7 @@ int32_t RuleHalf::parse(const UnicodeString& rule, int32_t pos, int32_t limit) {
if (buf.length() == 0 && !anchorStart) {
anchorStart = TRUE;
} else {
return syntaxError(RuleBasedTransliterator::MISPLACED_ANCHOR_START,
return syntaxError(U_MISPLACED_ANCHOR_START,
rule, start);
}
break;
@ -564,7 +564,7 @@ int32_t RuleHalf::parse(const UnicodeString& rule, int32_t pos, int32_t limit) {
}
if (r > 214748364 ||
(r == 214748364 && d > 7)) {
return syntaxError(RuleBasedTransliterator::UNDEFINED_SEGMENT_REFERENCE,
return syntaxError(U_UNDEFINED_SEGMENT_REFERENCE,
rule, start);
}
r = 10*r + d;
@ -599,13 +599,13 @@ int32_t RuleHalf::parse(const UnicodeString& rule, int32_t pos, int32_t limit) {
break;
case CONTEXT_ANTE:
if (ante >= 0) {
return syntaxError(RuleBasedTransliterator::MULTIPLE_ANTE_CONTEXTS, rule, start);
return syntaxError(U_MULTIPLE_ANTE_CONTEXTS, rule, start);
}
ante = buf.length();
break;
case CONTEXT_POST:
if (post >= 0) {
return syntaxError(RuleBasedTransliterator::MULTIPLE_POST_CONTEXTS, rule, start);
return syntaxError(U_MULTIPLE_POST_CONTEXTS, rule, start);
}
post = buf.length();
break;
@ -613,25 +613,25 @@ int32_t RuleHalf::parse(const UnicodeString& rule, int32_t pos, int32_t limit) {
pp.setIndex(pos-1); // Backup to opening '['
buf.append(parser.parseSet(rule, pp));
if (U_FAILURE(parser.status)) {
return syntaxError(RuleBasedTransliterator::MALFORMED_SET, rule, start);
return syntaxError(U_MALFORMED_SET, rule, start);
}
pos = pp.getIndex();
break;
case CURSOR_POS:
if (cursor >= 0) {
return syntaxError(RuleBasedTransliterator::MULTIPLE_CURSORS, rule, start);
return syntaxError(U_MULTIPLE_CURSORS, rule, start);
}
cursor = buf.length();
break;
case CURSOR_OFFSET:
if (cursorOffset < 0) {
if (buf.length() > 0) {
return syntaxError(RuleBasedTransliterator::MISPLACED_CURSOR_OFFSET, rule, start);
return syntaxError(U_MISPLACED_CURSOR_OFFSET, rule, start);
}
--cursorOffset;
} else if (cursorOffset > 0) {
if (buf.length() != cursorOffsetPos || cursor >= 0) {
return syntaxError(RuleBasedTransliterator::MISPLACED_CURSOR_OFFSET, rule, start);
return syntaxError(U_MISPLACED_CURSOR_OFFSET, rule, start);
}
++cursorOffset;
} else {
@ -641,7 +641,7 @@ int32_t RuleHalf::parse(const UnicodeString& rule, int32_t pos, int32_t limit) {
cursorOffsetPos = buf.length();
cursorOffset = 1;
} else {
return syntaxError(RuleBasedTransliterator::MISPLACED_CURSOR_OFFSET, rule, start);
return syntaxError(U_MISPLACED_CURSOR_OFFSET, rule, start);
}
}
break;
@ -662,10 +662,10 @@ int32_t RuleHalf::parse(const UnicodeString& rule, int32_t pos, int32_t limit) {
segments->getLastParenOffset(isOpenParen) == buf.length()) {
// The */+ immediately follows a segment
if (isOpenParen) {
return syntaxError(RuleBasedTransliterator::MISPLACED_QUANTIFIER, rule, start);
return syntaxError(U_MISPLACED_QUANTIFIER, rule, start);
}
if (!segments->extractLastParenSubstring(start, limit)) {
return syntaxError(RuleBasedTransliterator::MISMATCHED_SEGMENT_DELIMITERS, rule, start);
return syntaxError(U_MISMATCHED_SEGMENT_DELIMITERS, rule, start);
}
isSegment = TRUE;
} else {
@ -714,7 +714,7 @@ int32_t RuleHalf::parse(const UnicodeString& rule, int32_t pos, int32_t limit) {
!((c >= 0x0030/*'0'*/ && c <= 0x0039/*'9'*/) ||
(c >= 0x0041/*'A'*/ && c <= 0x005A/*'Z'*/) ||
(c >= 0x0061/*'a'*/ && c <= 0x007A/*'z'*/))) {
return syntaxError(RuleBasedTransliterator::UNQUOTED_SPECIAL, rule, start);
return syntaxError(U_UNQUOTED_SPECIAL, rule, start);
}
buf.append(c);
break;
@ -722,7 +722,7 @@ int32_t RuleHalf::parse(const UnicodeString& rule, int32_t pos, int32_t limit) {
}
if (cursorOffset > 0 && cursor != cursorOffsetPos) {
return syntaxError(RuleBasedTransliterator::MISPLACED_CURSOR_OFFSET, rule, start);
return syntaxError(U_MISPLACED_CURSOR_OFFSET, rule, start);
}
// text = buf.toString();
return pos;
@ -842,7 +842,7 @@ void TransliteratorParser::parseRules(UnicodeString& idBlockResult,
// Clear error struct
if (parseError != 0) {
parseError->code = parseError->line = 0;
//parseError->code = parseError->line = 0;
parseError->offset = 0;
parseError->preContext[0] = parseError->postContext[0] = (UChar)0;
}
@ -855,9 +855,10 @@ void TransliteratorParser::parseRules(UnicodeString& idBlockResult,
parseData->data = data;
variablesVector.removeAllElements();
if (parseError != 0) {
/* if (parseError != 0) {
parseError->code = 0;
}
*/
determineVariableRange();
UnicodeString str; // scratch
@ -985,7 +986,7 @@ int32_t TransliteratorParser::parseRule(int32_t pos, int32_t limit) {
}
if (pos == limit || u_strchr(gOPERATORS, (op = rule.charAt(pos++))) == NULL) {
return syntaxError(RuleBasedTransliterator::MISSING_OPERATOR, rule, start);
return syntaxError(U_MISSING_OPERATOR, rule, start);
}
// Found an operator char. Check for forward-reverse operator.
@ -1005,7 +1006,7 @@ int32_t TransliteratorParser::parseRule(int32_t pos, int32_t limit) {
++pos;
} else {
// RuleHalf parser must have terminated at an operator
return syntaxError(RuleBasedTransliterator::UNQUOTED_SPECIAL, rule, start);
return syntaxError(U_UNQUOTED_SPECIAL, rule, start);
}
}
@ -1019,15 +1020,15 @@ int32_t TransliteratorParser::parseRule(int32_t pos, int32_t limit) {
// defined).
if (undefinedVariableName.length() == 0) {
// "Missing '$' or duplicate definition"
return syntaxError(RuleBasedTransliterator::BAD_VARIABLE_DEFINITION, rule, start);
return syntaxError(U_BAD_VARIABLE_DEFINITION, rule, start);
}
if (left->text.length() != 1 || left->text.charAt(0) != variableLimit) {
// "Malformed LHS"
return syntaxError(RuleBasedTransliterator::MALFORMED_VARIABLE_DEFINITION, rule, start);
return syntaxError(U_MALFORMED_VARIABLE_DEFINITION, rule, start);
}
if (left->anchorStart || left->anchorEnd ||
right->anchorStart || right->anchorEnd) {
return syntaxError(RuleBasedTransliterator::MALFORMED_VARIABLE_DEFINITION, rule, start);
return syntaxError(U_MALFORMED_VARIABLE_DEFINITION, rule, start);
}
// We allow anything on the right, including an empty string.
UnicodeString* value = new UnicodeString(right->text);
@ -1041,7 +1042,7 @@ int32_t TransliteratorParser::parseRule(int32_t pos, int32_t limit) {
// any undefined variable names.
if (undefinedVariableName.length() != 0) {
syntaxError(// "Undefined variable $" + undefinedVariableName,
RuleBasedTransliterator::UNDEFINED_VARIABLE,
U_UNDEFINED_VARIABLE,
rule, start);
}
@ -1095,7 +1096,7 @@ int32_t TransliteratorParser::parseRule(int32_t pos, int32_t limit) {
//(-right->cursorOffset > left->ante) ||
right->anchorStart || right->anchorEnd) {
return syntaxError(RuleBasedTransliterator::MALFORMED_RULE, rule, start);
return syntaxError(U_MALFORMED_RULE, rule, start);
}
// Check integrity of segments and segment references. Each
@ -1103,11 +1104,11 @@ int32_t TransliteratorParser::parseRule(int32_t pos, int32_t limit) {
// references must not refer to segments that do not exist.
if (left->segments != NULL) {
if (!left->segments->validate()) {
return syntaxError(RuleBasedTransliterator::MISSING_SEGMENT_CLOSE, rule, start);
return syntaxError(U_MISSING_SEGMENT_CLOSE, rule, start);
}
int32_t n = left->segments->count();
if (right->maxRef > n) {
return syntaxError(RuleBasedTransliterator::UNDEFINED_SEGMENT_REFERENCE, rule, start);
return syntaxError(U_UNDEFINED_SEGMENT_REFERENCE, rule, start);
}
}
@ -1135,7 +1136,7 @@ int32_t TransliteratorParser::syntaxError(int32_t parseErrorCode,
const UnicodeString& rule,
int32_t start) {
if (parseError != 0) {
parseError->code = parseErrorCode;
// parseError->code = parseErrorCode;
parseError->line = 0; // We don't return a line #
parseError->offset = start; // Character offset from rule start
int32_t end = quotedIndexOf(rule, start, rule.length(), END_OF_RULE);
@ -1150,7 +1151,7 @@ int32_t TransliteratorParser::syntaxError(int32_t parseErrorCode,
parseError->preContext[len] = 0;
parseError->postContext[0] = 0;
}
status = U_ILLEGAL_ARGUMENT_ERROR;
status = (UErrorCode)parseErrorCode;
return start;
}

View file

@ -130,7 +130,7 @@ RuleBasedCollator::RuleBasedCollator(const UnicodeString& rules,
pucharrules[length] = 0;
ucollator = ucol_openRules(pucharrules, length, UCOL_DEFAULT_NORMALIZATION,
UCOL_DEFAULT_STRENGTH, &status);
UCOL_DEFAULT_STRENGTH, NULL, &status);
if (U_SUCCESS(status))
{
@ -169,7 +169,7 @@ RuleBasedCollator::RuleBasedCollator(const UnicodeString& rules,
UCollationStrength strength = getUCollationStrength(collationStrength);
ucollator = ucol_openRules(pucharrules, length, UCOL_DEFAULT_NORMALIZATION,
strength, &status);
strength, NULL,&status);
if (U_SUCCESS(status))
{
@ -209,7 +209,7 @@ RuleBasedCollator::RuleBasedCollator(const UnicodeString& rules,
UNormalizationMode mode = Normalizer::getUNormalizationMode(
decompositionMode, status);
ucollator = ucol_openRules(pucharrules, length, mode,
UCOL_DEFAULT_STRENGTH, &status);
UCOL_DEFAULT_STRENGTH, NULL, &status);
if (U_SUCCESS(status))
{
@ -249,7 +249,7 @@ RuleBasedCollator::RuleBasedCollator(const UnicodeString& rules,
UCollationStrength strength = getUCollationStrength(collationStrength);
UNormalizationMode mode = Normalizer::getUNormalizationMode(
decompositionMode, status);
ucollator = ucol_openRules(pucharrules, length, mode, strength, &status);
ucollator = ucol_openRules(pucharrules, length, mode, strength,NULL, &status);
if (U_SUCCESS(status))
{
const UChar *r = ucol_getRules(ucollator, &length);

View file

@ -1012,7 +1012,7 @@ Transliterator* Transliterator::parseID(const UnicodeString& ID,
else {
// Create the actual transliterator from the registry
if (parseError != 0) {
parseError->code = parseError->line = parseError->offset = 0;
parseError->line = parseError->offset = 0;
parseError->preContext[0] = parseError->postContext[0] = 0;
}
if (registry == 0) {

View file

@ -503,16 +503,22 @@ ucol_close(UCollator *coll)
}
U_CAPI UCollator*
ucol_openRules( const UChar *rules,
int32_t rulesLength,
UNormalizationMode mode,
UCollationStrength strength,
UErrorCode *status)
ucol_openRules( const UChar *rules,
int32_t rulesLength,
UNormalizationMode mode,
UCollationStrength strength,
UParseError *parseError,
UErrorCode *status)
{
uint32_t listLen = 0;
UColTokenParser src;
UColAttributeValue norm;
UParseError tErr;
if(parseError == NULL){
parseError = &tErr;
}
switch(mode) {
case UNORM_NONE:
norm = UCOL_OFF;
@ -531,10 +537,12 @@ ucol_openRules( const UChar *rules,
ucol_initUCA(status);
if(U_FAILURE(*status)) return 0;
if(U_FAILURE(*status)){
return 0;
}
ucol_tok_initTokenList(&src, rules, rulesLength, UCA, status);
listLen = ucol_tok_assembleTokenList(&src, status);
listLen = ucol_tok_assembleTokenList(&src,parseError, status);
if(U_FAILURE(*status)) {
/* if status is U_ILLEGAL_ARGUMENT_ERROR, src->current points at the offending option */
@ -593,7 +601,18 @@ ucol_openRules( const UChar *rules,
return result;
}
/*
U_CAPI UCollator*
ucol_openRules( const UChar *rules,
int32_t rulesLength,
UNormalizationMode mode,
UCollationStrength strength,
UErrorCode *status)
{
UParseError parseError;
return ucol_openRulesWithError(rules,rulesLength,mode,strength,&parseError,status);
}
*/
/* This one is currently used by genrb & tests. After constructing from rules (tailoring),*/
/* you should be able to get the binary chunk to write out... Doesn't look very full now */
U_CAPI uint8_t *
@ -4206,6 +4225,7 @@ ucol_safeClone(const UCollator *coll, void *stackBuffer, int32_t * pBufferSize,
length,
ucol_getNormalization(coll),
ucol_getStrength(coll),
NULL,
status);
if (U_SUCCESS(*status))
{
@ -5072,3 +5092,4 @@ ucol_equal( const UCollator *coll,
return (ucol_strcoll(coll, source, sourceLength, target, targetLength)
== UCOL_EQUAL);
}

View file

@ -26,7 +26,7 @@
#include "ucmp32.h"
#include "ucol_sol.h"
U_CFUNC const UChar *rulesToParse;
const UChar *rulesToParse;
void ucol_tok_initTokenList(UColTokenParser *src, const UChar *rules, const uint32_t rulesLength, UCollator *UCA, UErrorCode *status) {
uint32_t nSize = 0;
@ -63,6 +63,30 @@ void ucol_tok_initTokenList(UColTokenParser *src, const UChar *rules, const uint
src->resultLen = 0;
}
U_INLINE void syntaxError( const UChar* rules,
int32_t pos,
UParseError* parseError,
UErrorCode* status){
parseError->offset = pos;
// for pre-context
int32_t start = (pos <=U_PARSE_CONTEXT_LEN)? 0 : (pos - U_PARSE_CONTEXT_LEN);
int32_t stop = pos;
u_memcpy(parseError->preContext,rules+start,pos);
//null terminate the buffer
parseError->preContext[stop-start] = 0;
//for post-context
start = pos;
stop = ((pos+U_PARSE_CONTEXT_LEN)<=u_strlen(rules)) ? (pos+U_PARSE_CONTEXT_LEN) :
u_strlen(rules);
u_memcpy(parseError->postContext,rules+start,stop);
//null terminate the buffer
parseError->postContext[stop-start]= 0;
*status = U_PARSE_ERROR;
}
void ucol_uprv_tok_setOptionInImage(UColOptionSet *opts, UColAttribute attrib, UColAttributeValue value) {
switch(attrib) {
@ -278,6 +302,7 @@ const UChar *ucol_tok_parseNextToken(UColTokenParser *src,
uint32_t *exOffset, uint32_t *exLen,
uint8_t *specs,
UBool startOfRules,
UParseError *parseError,
UErrorCode *status) {
/* parsing part */
@ -608,7 +633,7 @@ Processing Description
handled.
*/
uint32_t ucol_tok_assembleTokenList(UColTokenParser *src, UErrorCode *status) {
uint32_t ucol_tok_assembleTokenList(UColTokenParser *src, UParseError *parseError,UErrorCode *status) {
UColToken *lastToken = NULL;
const UChar *parseEnd = NULL;
uint32_t expandNext = 0;
@ -633,6 +658,7 @@ uint32_t ucol_tok_assembleTokenList(UColTokenParser *src, UErrorCode *status) {
&extensionOffset, &newExtensionsLen,
&specs,
(UBool)(lastToken == NULL),
parseError,
status);
variableTop = ((specs & UCOL_TOK_VARIABLE_TOP) != 0);
@ -954,3 +980,58 @@ void ucol_tok_closeTokenList(UColTokenParser *src) {
}
}
int32_t
uhash_hashTokens(const UHashKey k) {
int32_t hash = 0;
uint32_t key = (uint32_t)k.integer;
if (key != 0) {
int32_t len = (key & 0xFF000000)>>24;
int32_t inc = ((len - 32) / 32) + 1;
const UChar *p = (key & 0x00FFFFFF) + rulesToParse;
const UChar *limit = p + len;
while (p<limit) {
hash = (hash * 37) + *p;
p += inc;
}
}
return hash;
}
UBool uhash_compareTokens(const UHashKey key1, const UHashKey key2) {
uint32_t p1 = (uint32_t) key1.integer;
uint32_t p2 = (uint32_t) key2.integer;
const UChar *s1 = (p1 & 0x00FFFFFF) + rulesToParse;
const UChar *s2 = (p2 & 0x00FFFFFF) + rulesToParse;
uint32_t s1L = ((p1 & 0xFF000000) >> 24);
uint32_t s2L = ((p2 & 0xFF000000) >> 24);
const UChar *end = s1+s1L-1;
if (p1 == p2) {
return TRUE;
}
if (p1 == 0 || p2 == 0) {
return FALSE;
}
if(s1L != s2L) {
return FALSE;
}
if(p1 == p2) {
return TRUE;
}
while((s1 < end) && *s1 == *s2) {
++s1;
++s2;
}
if(*s1 == *s2) {
return TRUE;
} else {
return FALSE;
}
}
void deleteToken(void *token) {
UColToken *tok = (UColToken *)token;
uprv_free(tok);
}

View file

@ -23,6 +23,7 @@
#include "ucol_imp.h"
#include "uhash.h"
#include "unicode\parseerr.h"
#define UCOL_TOK_UNSET 0xFFFFFFFF
#define UCOL_TOK_RESET 0xDEADBEEF
@ -112,22 +113,26 @@ typedef struct {
(((ch) <= 0x007E) && ((ch) >= 0x007B))))
U_CFUNC uint32_t ucol_tok_assembleTokenList(UColTokenParser *src, UErrorCode *status);
U_CFUNC uint32_t ucol_tok_assembleTokenList(UColTokenParser *src,UParseError *parseError, UErrorCode *status);
U_CFUNC void ucol_tok_closeTokenList(UColTokenParser *src);
void ucol_uprv_tok_setOptionInImage(UColOptionSet *opts, UColAttribute attrib, UColAttributeValue value);
UBool ucol_uprv_tok_readAndSetOption(UColOptionSet *opts, const UChar* start, const UChar *end, UBool *variableTop, UBool *top, UErrorCode *status);
void ucol_tok_initTokenList(UColTokenParser *src, const UChar *rules, const uint32_t rulesLength, UCollator *UCA, UErrorCode *status);
uint32_t ucol_uprv_tok_assembleTokenList(UColTokenParser *src, UErrorCode *status);
uint32_t ucol_uprv_tok_assembleTokenList(UColTokenParser *src, UParseError *parseError,UErrorCode *status);
U_CAPI const UChar U_EXPORT2 *ucol_tok_parseNextToken(UColTokenParser *src,
uint32_t *strength,
uint32_t *chOffset, uint32_t *chLen,
uint32_t *exOffset, uint32_t *exLen,
uint8_t *specs,
UBool startOfRules,
UParseError *parseError,
UErrorCode *status);
U_CFUNC int32_t uhash_hashTokens(const UHashKey k);
U_CFUNC UBool uhash_compareTokens(const UHashKey key1, const UHashKey key2);
U_CFUNC void deleteToken(void *token);
#endif

View file

@ -18,7 +18,7 @@
#include "unicode/numfmt.h"
#include "unicode/dtfmtsym.h"
#include "unicode/ustring.h"
/*
U_CAPI UDateFormat*
udat_open( UDateFormatStyle timeStyle,
UDateFormatStyle dateStyle,
@ -86,6 +86,75 @@ udat_openPattern( const UChar *pattern,
}
return retVal;
}
*/
U_CAPI UDateFormat*
udat_open(UDateFormatStyle timeStyle,
UDateFormatStyle dateStyle,
const char *locale,
const UChar *tzID,
int32_t tzIDLength,
const UChar *pattern,
int32_t patternLength,
UErrorCode *status)
{
if(U_FAILURE(*status))
{
return 0;
}
if(timeStyle != UDAT_IGNORE)
{
DateFormat *fmt;
if(locale == 0)
fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle,
(DateFormat::EStyle)timeStyle);
else
fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle,
(DateFormat::EStyle)timeStyle,
Locale(locale));
if(fmt == 0) {
*status = U_MEMORY_ALLOCATION_ERROR;
return 0;
}
if(tzID != 0) {
TimeZone *zone = 0;
int32_t length = (tzIDLength == -1 ? u_strlen(tzID) : tzIDLength);
zone = TimeZone::createTimeZone(UnicodeString((UChar*)tzID,
length, length));
if(zone == 0) {
*status = U_MEMORY_ALLOCATION_ERROR;
delete fmt;
return 0;
}
fmt->adoptTimeZone(zone);
}
return (UDateFormat*)fmt;
}
else
{
int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
UDateFormat *retVal = 0;
if(locale == 0)
retVal = (UDateFormat*)new SimpleDateFormat(UnicodeString((UChar*)pattern,
len, len),
*status);
else
retVal = (UDateFormat*)new SimpleDateFormat(UnicodeString((UChar*)pattern,
len, len),
Locale(locale),
*status);
if(retVal == 0) {
*status = U_MEMORY_ALLOCATION_ERROR;
return 0;
}
return retVal;
}
}
U_CAPI void
udat_close(UDateFormat* format)
@ -490,3 +559,5 @@ udat_setSymbols( UDateFormat *format,
((SimpleDateFormat*)format)->adoptDateFormatSymbols(syms);
delete [] array;
}

View file

@ -1,8 +1,22 @@
/*
*******************************************************************************
* Copyright (C) 1996-2001, International Business Machines
*
* Copyright (C) 2001, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
* file name: umsg.cpp
* encoding: US-ASCII
* tab size: 8 (not used)
* indentation:4
*
* This is a C wrapper to MessageFormat C++ API.
*
* Change history:
*
* 08/5/2001 Ram Added C wrappers for C++ API. Changed implementation of old API's
* Removed pattern parser.
*
*/
#include "unicode/umsg.h"
@ -13,10 +27,9 @@
#include "unicode/msgfmt.h"
#include "unicode/unistr.h"
#include "unicode/numfmt.h"
#include "umsg_imp.h"
#include "unicode/ustring.h"
/*
#define COMMA ((UChar)0x002C)
#define SINGLE_QUOTE ((UChar)0x0027)
#define LEFT_CURLY_BRACE ((UChar)0x007B)
@ -191,7 +204,7 @@ umsg_stoi(const UnicodeString& string,
return value;
}
/*
UnicodeString&
umsg_itos(int32_t i,
UnicodeString& string)
@ -207,58 +220,16 @@ umsg_itos(int32_t i,
return string;
}
*/
// ==========
#define MAX_ARGS 10
// Eventually, message format should be rewritten natively in C.
// For now, this is a hack that should work:
// 1. Parse the pattern, determining the argument types
// 2. Create a Formattable array with the varargs
// 3. Call through to the existing C++ code
//
// Right now this imposes the same limit as MessageFormat in C++
// Namely, only MAX_ARGS arguments are supported
U_CAPI int32_t
u_formatMessage( const char *locale,
const UChar *pattern,
int32_t patternLength,
UChar *result,
int32_t resultLength,
UErrorCode *status,
...)
void
umsg_parseFormattableArgs(const UChar* pattern,
int32_t patLen,
Formattable* args,
Formattable::Type *argTypes,
int32_t *count,
va_list ap,
UErrorCode* status)
{
va_list ap;
int32_t actLen;
if(U_FAILURE(*status)) return -1;
// start vararg processing
va_start(ap, status);
actLen = u_vformatMessage(locale,pattern,patternLength,result,resultLength,ap,status);
// end vararg processing
va_end(ap);
return actLen;
}
U_CAPI int32_t
u_vformatMessage( const char *locale,
const UChar *pattern,
int32_t patternLength,
UChar *result,
int32_t resultLength,
va_list ap,
UErrorCode *status)
{
if(U_FAILURE(*status)) return -1;
int32_t patLen = (patternLength == -1 ? u_strlen(pattern) : patternLength);
// ========================================
// Begin pseudo-parser
@ -271,16 +242,8 @@ u_vformatMessage( const char *locale,
const UChar *pat = pattern;
const UChar *patLimit = pattern + patLen;
int32_t bracePos = 0;
int32_t count = 0;
Formattable args [ MAX_ARGS ];
Formattable::Type argTypes [ MAX_ARGS ];
// set the types to a bogus value initially (no such type as kArray from C)
for(int32_t j = 0; j < MAX_ARGS; ++j)
argTypes[j] = Formattable::kArray;
// pseudo-parse the pattern
// pseudo-parse the pattern
while(pat < patLimit) {
if(part == 0) {
if(*pat == SINGLE_QUOTE) {
@ -302,16 +265,16 @@ u_vformatMessage( const char *locale,
else {
switch (*pat) {
case COMMA /*','*/:
case COMMA : //','
if(part < 3)
part += 1;
break;
case LEFT_CURLY_BRACE /*'{'*/:
case LEFT_CURLY_BRACE: //'{'
++braceStack;
break;
case RIGHT_CURLY_BRACE /*'}'*/:
case RIGHT_CURLY_BRACE //'}'
if(braceStack == 0) {
part = 0;
// found a close brace, determine the argument type enclosed
@ -327,20 +290,20 @@ u_vformatMessage( const char *locale,
if(argNum >= MAX_ARGS) {
*status = U_INTERNAL_PROGRAM_ERROR;
return -1;
// return -1;
}
// register the type of this argument in our list
argTypes[argNum] = type;
// adjust argument count
count = ( (argNum + 1) > count ? (argNum + 1) : count);
*count = ( (argNum + 1) > *count ? (argNum + 1) : *count);
}
else
--braceStack;
break;
case SINGLE_QUOTE /*'\''*/:
case SINGLE_QUOTE: //'\''
inQuote = TRUE;
break;
}
@ -353,11 +316,10 @@ u_vformatMessage( const char *locale,
// detect any unmatched braces in the pattern
if(braceStack == 0 && part != 0) {
*status = U_INVALID_FORMAT_ERROR;
return -1;
//return -1;
}
// iterate through the vararg list, and get the arguments out
for(int32_t i = 0; i < count; ++i) {
// iterate through the vararg list, and get the arguments out
for(int32_t i = 0; i < *count; ++i) {
UChar *stringVal;
@ -392,6 +354,38 @@ u_vformatMessage( const char *locale,
// End pseudo-parser
// ========================================
}
U_CAPI int32_t
u_vformatMessage( const char *locale,
const UChar *pattern,
int32_t patternLength,
UChar *result,
int32_t resultLength,
va_list ap,
UErrorCode *status)
{
if(U_FAILURE(*status)) return -1;
int32_t patLen = (patternLength == -1 ? u_strlen(pattern) : patternLength);
int32_t count = 0;
Formattable args [ MAX_ARGS ];
Formattable::Type argTypes [ MAX_ARGS ];
// set the types to a bogus value initially (no such type as kArray from C)
for(int32_t j = 0; j < MAX_ARGS; ++j)
argTypes[j] = Formattable::kArray;
umsg_parseFormattableArgs(pattern,patLen,args,argTypes,&count,ap,status);
if(U_FAILURE(*status))
{
return -1;
}
// just call through to the C++ implementation
UnicodeString patString((UChar*)pattern, patLen, patLen);
@ -402,42 +396,14 @@ u_vformatMessage( const char *locale,
return uprv_fillOutputString(res, result, resultLength, status);
}
// For parse, do the reverse of format:
// 1. Call through to the C++ APIs
// 2. Just assume the user passed in enough arguments.
// 3. Iterate through each formattable returned, and assign to the arguments
U_CAPI void
u_parseMessage( const char *locale,
const UChar *pattern,
int32_t patternLength,
const UChar *source,
int32_t sourceLength,
UErrorCode *status,
...)
{
va_list ap;
if(U_FAILURE(*status)) return;
// start vararg processing
va_start(ap, status);
u_vparseMessage(locale,pattern,patternLength,source,sourceLength,ap,status);
// end vararg processing
va_end(ap);
}
U_CAPI void
u_vparseMessage( const char *locale,
const UChar *pattern,
int32_t patternLength,
const UChar *source,
int32_t sourceLength,
va_list ap,
UErrorCode *status)
U_CAPI void
u_vparseMessage(const char *locale,
const UChar *pattern,
int32_t patternLength,
const UChar *source,
int32_t sourceLength,
va_list ap,
UErrorCode *status)
{
if(U_FAILURE(*status)) return;
@ -491,3 +457,458 @@ u_vparseMessage( const char *locale,
// clean up
delete [] args;
}
*/
// ==========
// Eventually, message format should be rewritten natively in C.
// For now, this is a hack that should work:
// 1. Parse the pattern, determining the argument types
// 2. Create a Formattable array with the varargs
// 3. Call through to the existing C++ code
//
// Right now this imposes the same limit as MessageFormat in C++
// Namely, only MAX_ARGS arguments are supported
U_CAPI int32_t
u_formatMessage(const char *locale,
const UChar *pattern,
int32_t patternLength,
UChar *result,
int32_t resultLength,
UErrorCode *status,
...)
{
va_list ap;
int32_t actLen;
if(U_FAILURE(*status)) return -1;
// start vararg processing
va_start(ap, status);
actLen = u_vformatMessage(locale,pattern,patternLength,result,resultLength,ap,status);
// end vararg processing
va_end(ap);
return actLen;
}
U_CAPI int32_t
u_vformatMessage( const char *locale,
const UChar *pattern,
int32_t patternLength,
UChar *result,
int32_t resultLength,
va_list ap,
UErrorCode *status)
{
UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,NULL,status);
int32_t fieldPos=0;
int32_t retVal = umsg_vformat(fmt,result,resultLength,ap,status);
umsg_close(fmt);
return retVal;
}
U_CAPI int32_t
u_formatMessageWithError(const char *locale,
const UChar *pattern,
int32_t patternLength,
UChar *result,
int32_t resultLength,
UParseError *parseError,
UErrorCode *status,
...)
{
va_list ap;
int32_t actLen;
if(U_FAILURE(*status)) return -1;
// start vararg processing
va_start(ap, status);
actLen = u_vformatMessageWithError(locale,pattern,patternLength,result,resultLength,parseError,ap,status);
// end vararg processing
va_end(ap);
return actLen;
}
U_CAPI int32_t
u_vformatMessageWithError( const char *locale,
const UChar *pattern,
int32_t patternLength,
UChar *result,
int32_t resultLength,
UParseError *parseError,
va_list ap,
UErrorCode *status)
{
UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,parseError,status);
int32_t retVal = umsg_vformat(fmt,result,resultLength,ap,status);
umsg_close(fmt);
return retVal;
}
// For parse, do the reverse of format:
// 1. Call through to the C++ APIs
// 2. Just assume the user passed in enough arguments.
// 3. Iterate through each formattable returned, and assign to the arguments
U_CAPI void
u_parseMessage( const char *locale,
const UChar *pattern,
int32_t patternLength,
const UChar *source,
int32_t sourceLength,
UErrorCode *status,
...)
{
va_list ap;
if(U_FAILURE(*status)) return;
// start vararg processing
va_start(ap, status);
u_vparseMessage(locale,pattern,patternLength,source,sourceLength,ap,status);
// end vararg processing
va_end(ap);
}
U_CAPI void
u_vparseMessage(const char *locale,
const UChar *pattern,
int32_t patternLength,
const UChar *source,
int32_t sourceLength,
va_list ap,
UErrorCode *status)
{
UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,NULL,status);
int32_t count = 0;
umsg_vparse(fmt,source,sourceLength,&count,ap,status);
umsg_close(fmt);
}
U_CAPI void
u_parseMessageWithError(const char *locale,
const UChar *pattern,
int32_t patternLength,
const UChar *source,
int32_t sourceLength,
UParseError *error,
UErrorCode *status,
...)
{
va_list ap;
if(U_FAILURE(*status)) return;
// start vararg processing
va_start(ap, status);
u_vparseMessageWithError(locale,pattern,patternLength,source,sourceLength,ap,error,status);
// end vararg processing
va_end(ap);
}
U_CAPI void
u_vparseMessageWithError(const char *locale,
const UChar *pattern,
int32_t patternLength,
const UChar *source,
int32_t sourceLength,
va_list ap,
UParseError *error,
UErrorCode* status)
{
UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,error,status);
int32_t count = 0;
umsg_vparse(fmt,source,sourceLength,&count,ap,status);
umsg_close(fmt);
}
//////////////////////////////////////////////////////////////////////////////////
//
// Message format C API
//
/////////////////////////////////////////////////////////////////////////////////
U_CAPI UMessageFormat*
umsg_open( const UChar *pattern,
int32_t patternLength,
const char *locale,
UParseError *parseError,
UErrorCode *status)
{
if(U_FAILURE(*status))
{
return 0;
}
UParseError tErr;
if(!parseError)
{
parseError = &tErr;
}
UMessageFormat* retVal = 0;
int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
UnicodeString patString((patternLength == -1 ? TRUE:FALSE), pattern,len);
retVal = (UMessageFormat*) new MessageFormat(pattern,Locale(locale),*parseError,*status);
if(retVal == 0) {
*status = U_MEMORY_ALLOCATION_ERROR;
return 0;
}
return retVal;
}
U_CAPI void
umsg_close(UMessageFormat* format)
{
delete (MessageFormat*) format;
}
U_CAPI UMessageFormat
umsg_clone(const UMessageFormat *fmt,
UErrorCode *status)
{
UMessageFormat retVal = (UMessageFormat)((MessageFormat*)fmt)->clone();
if(retVal == 0) {
*status = U_MEMORY_ALLOCATION_ERROR;
return 0;
}
return retVal;
}
U_CAPI void
umsg_setLocale(UMessageFormat *fmt, const char* locale)
{
((MessageFormat*)fmt)->setLocale(Locale(locale));
}
U_CAPI const char*
umsg_getLocale(UMessageFormat *fmt)
{
Locale loc = ((MessageFormat*)fmt)->getLocale();
return loc.getName();
}
U_CAPI void
umsg_applyPattern(UMessageFormat *fmt,
const UChar* pattern,
int32_t patternLength,
UParseError* parseError,
UErrorCode* status)
{
UParseError tErr;
if(!parseError)
{
parseError = &tErr;
}
((MessageFormat*)fmt)->applyPattern(UnicodeString(pattern,patternLength),*parseError,*status);
}
U_CAPI int32_t
umsg_toPattern(UMessageFormat *fmt,
UChar* result,
int32_t resultLength,
UErrorCode* status)
{
UnicodeString res(result, 0, resultLength);
((MessageFormat*)fmt)->toPattern(res);
return uprv_fillOutputString(res, result, resultLength, status);
}
U_CAPI int32_t
umsg_format( UMessageFormat *fmt,
UChar *result,
int32_t resultLength,
UErrorCode *status,
...)
{
va_list ap;
int32_t actLen;
if(U_FAILURE(*status))
{
return -1;
}
// start vararg processing
va_start(ap, status);
actLen = umsg_vformat(fmt,result,resultLength,ap,status);
// end vararg processing
va_end(ap);
return actLen;
}
U_CAPI int32_t
umsg_vformat( UMessageFormat *fmt,
UChar *result,
int32_t resultLength,
va_list ap,
UErrorCode *status)
{
if(U_FAILURE(*status))
{
return -1;
}
int32_t count =0;
const Formattable::Type* argTypes = ((MessageFormat*)fmt)->getFormatTypeList(count);
Formattable args[MessageFormat::kMaxFormat];
// iterate through the vararg list, and get the arguments out
for(int32_t i = 0; i < count; ++i) {
UChar *stringVal;
double tDouble=0;
int32_t tInt =0;
UDate tempDate = 0;
switch(argTypes[i]) {
case Formattable::kDate:
tempDate = va_arg(ap, UDate);
args[i].setDate(tempDate);
break;
case Formattable::kDouble:
tDouble =va_arg(ap, double);
args[i].setDouble(tDouble);
break;
case Formattable::kLong:
tInt = va_arg(ap, int32_t);
args[i].setLong(tInt);
break;
case Formattable::kString:
// For some reason, a temporary is needed
stringVal = va_arg(ap, UChar*);
args[i].setString(stringVal);
break;
case Formattable::kArray:
// throw away this argument
// this is highly platform-dependent, and probably won't work
// so, if you try to skip arguments in the list (and not use them)
// you'll probably crash
va_arg(ap, int);
break;
}
}
UnicodeString resultStr;
FieldPosition fieldPosition(0);
/* format the message */
((MessageFormat*)fmt)->format(args,count,resultStr,fieldPosition,*status);
if(U_FAILURE(*status)){
return -1;
}
if(result ==NULL || resultLength < resultStr.length()){
*status = U_BUFFER_OVERFLOW_ERROR;
}else{
/* copy the resultStr to target buffer */
u_strcpy(result, resultStr.getUChars());
}
return resultStr.length();
}
U_CAPI void
umsg_parse( UMessageFormat *fmt,
const UChar *source,
int32_t sourceLength,
int32_t *count,
UErrorCode *status,
...)
{
va_list ap;
if(U_FAILURE(*status))
{
return;
}
// start vararg processing
va_start(ap, status);
umsg_vparse(fmt,source,sourceLength,count,ap,status);
// end vararg processing
va_end(ap);
}
U_CAPI void
umsg_vparse(UMessageFormat *fmt,
const UChar *source,
int32_t sourceLength,
int32_t *count,
va_list ap,
UErrorCode *status)
{
UnicodeString srcString(source,sourceLength);
Formattable *args = ((MessageFormat*)fmt)->parse(source,*count,*status);
if(U_FAILURE(*status))
{
return;
}
UDate *aDate;
double *aDouble;
UChar *aString;
UnicodeString temp;
// assign formattables to varargs
for(int32_t i = 0; i < *count; i++) {
switch(args[i].getType()) {
case Formattable::kDate:
aDate = va_arg(ap, UDate*);
*aDate = args[i].getDate();
break;
case Formattable::kDouble:
aDouble = va_arg(ap, double*);
*aDouble = args[i].getDouble();
break;
case Formattable::kLong:
// always assume doubles for parsing
aDouble = va_arg(ap, double*);
*aDouble = (double) args[i].getLong();
break;
case Formattable::kString:
aString = va_arg(ap, UChar*);
args[i].getString(temp);
u_strcpy(aString, temp.getUChars());
break;
// better not happen!
case Formattable::kArray:
// DIE
break;
}
}
// clean up
delete [] args;
}

View file

@ -20,7 +20,7 @@
#include "cpputils.h"
#include "unicode/fmtable.h"
#include "unicode/dcfmtsym.h"
/*
U_CAPI UNumberFormat*
unum_open( UNumberFormatStyle style,
const char* locale,
@ -81,32 +81,100 @@ unum_openPattern( const UChar* pattern,
const char* locale,
UErrorCode* status)
{
if(U_FAILURE(*status)) return 0;
UParseError parseError;
return unum_openPatternWithError( pattern,patternLength,locale,&parseError,status);
}*/
int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
const UnicodeString pat((UChar*)pattern, len, len);
DecimalFormatSymbols *syms = 0;
if(locale == 0)
syms = new DecimalFormatSymbols(*status);
else
syms = new DecimalFormatSymbols(Locale(locale),
*status);
U_CAPI UNumberFormat*
unum_open( UNumberFormatStyle style,
const UChar* pattern,
int32_t patternLength,
const char* locale,
UParseError* parseErr,
UErrorCode* status)
{
if(U_FAILURE(*status))
{
return 0;
}
if(style!=0){
UNumberFormat *retVal = 0;
if(syms == 0) {
*status = U_MEMORY_ALLOCATION_ERROR;
return 0;
}
switch(style) {
case UNUM_DECIMAL:
if(locale == 0)
retVal = (UNumberFormat*)NumberFormat::createInstance(*status);
else
retVal = (UNumberFormat*)NumberFormat::createInstance(Locale(locale),
*status);
break;
DecimalFormat *fmt = 0;
fmt = new DecimalFormat(pat, syms, *status);
if(fmt == 0) {
*status = U_MEMORY_ALLOCATION_ERROR;
delete syms;
return 0;
}
case UNUM_CURRENCY:
if(locale == 0)
retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(*status);
else
retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(Locale(locale),
*status);
break;
return (UNumberFormat*) fmt;
case UNUM_PERCENT:
if(locale == 0)
retVal = (UNumberFormat*)NumberFormat::createPercentInstance(*status);
else
retVal = (UNumberFormat*)NumberFormat::createPercentInstance(Locale(locale),
*status);
break;
case UNUM_SPELLOUT:
// Todo: TBD: Add spellout support
//retVal = (UNumberFormat*)new NumberSpelloutFormat();
//break;
*status = U_UNSUPPORTED_ERROR;
return 0;
default:
*status = U_UNSUPPORTED_ERROR;
return 0;
}
if(retVal == 0) {
*status = U_MEMORY_ALLOCATION_ERROR;
return 0;
}
return retVal;
}else{
UParseError tErr;
int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
const UnicodeString pat((UChar*)pattern, len, len);
DecimalFormatSymbols *syms = 0;
if(parseErr==NULL){
parseErr = &tErr;
}
if(locale == 0)
syms = new DecimalFormatSymbols(*status);
else
syms = new DecimalFormatSymbols(Locale(locale),
*status);
if(syms == 0) {
*status = U_MEMORY_ALLOCATION_ERROR;
return 0;
}
DecimalFormat *fmt = 0;
fmt = new DecimalFormat(pat, syms, *parseErr, *status);
if(fmt == 0) {
*status = U_MEMORY_ALLOCATION_ERROR;
delete syms;
return 0;
}
return (UNumberFormat*) fmt;
}
}
U_CAPI void
@ -640,19 +708,45 @@ unum_setSymbol(UNumberFormat *fmt,
((DecimalFormat *)fmt)->setDecimalFormatSymbols(symbols);
}
/*
U_CAPI void
unum_applyPattern( UNumberFormat *format,
UBool localized,
const UChar *pattern,
int32_t patternLength)
int32_t patternLength
)
{
UErrorCode status = U_ZERO_ERROR;
UParseError parseError;
unum_applyPatternWithError(format,localized,pattern,patternLength,&parseError,&status);
}
*/
U_CAPI void
unum_applyPattern( UNumberFormat *format,
UBool localized,
const UChar *pattern,
int32_t patternLength,
UParseError *parseError,
UErrorCode* status)
{
UErrorCode tStatus = U_ZERO_ERROR;
UParseError tParseError;
if(parseError == NULL){
parseError = &tParseError;
}
if(status==NULL){
status = &tStatus;
}
int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
const UnicodeString pat((UChar*)pattern, len, len);
UErrorCode status = U_ZERO_ERROR;
if(localized)
((DecimalFormat*)format)->applyLocalizedPattern(pat, status);
((DecimalFormat*)format)->applyLocalizedPattern(pat,*parseError, *status);
else
((DecimalFormat*)format)->applyPattern(pat, status);
((DecimalFormat*)format)->applyPattern(pat,*parseError, *status);
}