mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-21 12:40:02 +00:00
ICU-329 First take on add better error reporting with UParseError struct.
X-SVN-Rev: 5472
This commit is contained in:
parent
ae8bfdff08
commit
d7d6c296e2
14 changed files with 1412 additions and 329 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue