+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
*
-* Copyright (C) 1999-2003, International Business Machines
+* Copyright (C) 1999-2012, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
* file name: umsg.cpp
-* encoding: US-ASCII
+* encoding: UTF-8
* tab size: 8 (not used)
* indentation:4
*
#include "unicode/msgfmt.h"
#include "unicode/unistr.h"
#include "cpputils.h"
+#include "uassert.h"
+#include "ustr_imp.h"
+
+U_NAMESPACE_BEGIN
+/**
+ * This class isolates our access to private internal methods of
+ * MessageFormat. It is never instantiated; it exists only for C++
+ * access management.
+ */
+class MessageFormatAdapter {
+public:
+ static const Formattable::Type* getArgTypeList(const MessageFormat& m,
+ int32_t& count);
+ static UBool hasArgTypeConflicts(const MessageFormat& m) {
+ return m.hasArgTypeConflicts;
+ }
+};
+const Formattable::Type*
+MessageFormatAdapter::getArgTypeList(const MessageFormat& m,
+ int32_t& count) {
+ return m.getArgTypeList(count);
+}
+U_NAMESPACE_END
U_NAMESPACE_USE
}
UParseError tErr;
-
if(parseError==NULL)
{
parseError = &tErr;
}
-
- UMessageFormat* retVal = 0;
int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
-
- UnicodeString patString((patternLength == -1 ? TRUE:FALSE), pattern,len);
+ UnicodeString patString(patternLength == -1, pattern, len);
- retVal = (UMessageFormat*) new MessageFormat(pattern,Locale(locale),*parseError,*status);
-
- if(retVal == 0) {
+ MessageFormat* retVal = new MessageFormat(patString,Locale(locale),*parseError,*status);
+ if(retVal == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
- return 0;
+ return NULL;
}
- return retVal;
+ if (U_SUCCESS(*status) && MessageFormatAdapter::hasArgTypeConflicts(*retVal)) {
+ *status = U_ARGUMENT_TYPE_MISMATCH;
+ }
+ return (UMessageFormat*)retVal;
}
U_CAPI void U_EXPORT2
}
U_CAPI const char* U_EXPORT2
-umsg_getLocale(UMessageFormat *fmt)
+umsg_getLocale(const UMessageFormat *fmt)
{
//check arguments
if(fmt==NULL){
return "";
}
- return ((MessageFormat*)fmt)->getLocale().getName();
+ return ((const MessageFormat*)fmt)->getLocale().getName();
}
U_CAPI void U_EXPORT2
if(status ==NULL||U_FAILURE(*status)){
return ;
}
- if(fmt==NULL||pattern==NULL||patternLength<-1){
+ if(fmt==NULL || (pattern==NULL && patternLength!=0) || patternLength<-1) {
*status=U_ILLEGAL_ARGUMENT_ERROR;
return ;
}
if(parseError==NULL){
parseError = &tErr;
}
- if(patternLength<-1){
- patternLength=u_strlen(pattern);
- }
+ // UnicodeString(pattern, -1) calls u_strlen().
((MessageFormat*)fmt)->applyPattern(UnicodeString(pattern,patternLength),*parseError,*status);
}
U_CAPI int32_t U_EXPORT2
-umsg_toPattern(UMessageFormat *fmt,
+umsg_toPattern(const UMessageFormat *fmt,
UChar* result,
int32_t resultLength,
UErrorCode* status)
// otherwise, alias the destination buffer
res.setTo(result, 0, resultLength);
}
- ((MessageFormat*)fmt)->toPattern(res);
+ ((const MessageFormat*)fmt)->toPattern(res);
return res.extract(result, resultLength, *status);
}
U_CAPI int32_t
-umsg_format( UMessageFormat *fmt,
+umsg_format( const UMessageFormat *fmt,
UChar *result,
int32_t resultLength,
UErrorCode *status,
return actLen;
}
-U_NAMESPACE_BEGIN
-/**
- * This class isolates our access to private internal methods of
- * MessageFormat. It is never instantiated; it exists only for C++
- * access management.
- */
-class MessageFormatAdapter {
-public:
- static const Formattable::Type* getArgTypeList(const MessageFormat& m,
- int32_t& count);
-};
-const Formattable::Type*
-MessageFormatAdapter::getArgTypeList(const MessageFormat& m,
- int32_t& count) {
- return m.getArgTypeList(count);
-}
-U_NAMESPACE_END
-
U_CAPI int32_t U_EXPORT2
-umsg_vformat( UMessageFormat *fmt,
+umsg_vformat( const UMessageFormat *fmt,
UChar *result,
int32_t resultLength,
va_list ap,
int32_t count =0;
const Formattable::Type* argTypes =
- MessageFormatAdapter::getArgTypeList(*(MessageFormat*)fmt, count);
+ MessageFormatAdapter::getArgTypeList(*(const MessageFormat*)fmt, count);
// Allocate at least one element. Allocating an array of length
// zero causes problems on some platforms (e.g. Win32).
Formattable* args = new Formattable[count ? count : 1];
UChar *stringVal;
double tDouble=0;
int32_t tInt =0;
+ int64_t tInt64 = 0;
UDate tempDate = 0;
switch(argTypes[i]) {
case Formattable::kDate:
tInt = va_arg(ap, int32_t);
args[i].setLong(tInt);
break;
+
+ case Formattable::kInt64:
+ tInt64 = va_arg(ap, int64_t);
+ args[i].setInt64(tInt64);
+ break;
case Formattable::kString:
// For some reason, a temporary is needed
stringVal = va_arg(ap, UChar*);
if(stringVal){
- args[i].setString(stringVal);
+ args[i].setString(UnicodeString(stringVal));
}else{
*status=U_ILLEGAL_ARGUMENT_ERROR;
}
va_arg(ap, int);
break;
+ case Formattable::kObject:
+ // Unused argument number. Read and ignore a pointer argument.
+ va_arg(ap, void*);
+ break;
+
+ default:
+ // Unknown/unsupported argument type.
+ U_ASSERT(FALSE);
+ *status=U_ILLEGAL_ARGUMENT_ERROR;
+ break;
}
}
UnicodeString resultStr;
- FieldPosition fieldPosition(0);
+ FieldPosition fieldPosition(FieldPosition::DONT_CARE);
/* format the message */
- ((MessageFormat*)fmt)->format(args,count,resultStr,fieldPosition,*status);
+ ((const MessageFormat*)fmt)->format(args,count,resultStr,fieldPosition,*status);
delete[] args;
}
U_CAPI void
-umsg_parse( UMessageFormat *fmt,
+umsg_parse( const UMessageFormat *fmt,
const UChar *source,
int32_t sourceLength,
int32_t *count,
}
U_CAPI void U_EXPORT2
-umsg_vparse(UMessageFormat *fmt,
+umsg_vparse(const UMessageFormat *fmt,
const UChar *source,
int32_t sourceLength,
int32_t *count,
}
UnicodeString srcString(source,sourceLength);
- Formattable *args = ((MessageFormat*)fmt)->parse(source,*count,*status);
+ Formattable *args = ((const MessageFormat*)fmt)->parse(srcString,*count,*status);
UDate *aDate;
double *aDouble;
UChar *aString;
int32_t* aInt;
+ int64_t* aInt64;
UnicodeString temp;
int len =0;
// assign formattables to varargs
break;
case Formattable::kLong:
-
aInt = va_arg(ap, int32_t*);
if(aInt){
*aInt = (int32_t) args[i].getLong();
}
break;
+ case Formattable::kInt64:
+ aInt64 = va_arg(ap, int64_t*);
+ if(aInt64){
+ *aInt64 = args[i].getInt64();
+ }else{
+ *status=U_ILLEGAL_ARGUMENT_ERROR;
+ }
+ break;
+
case Formattable::kString:
aString = va_arg(ap, UChar*);
if(aString){
}
break;
+ case Formattable::kObject:
+ // This will never happen because MessageFormat doesn't
+ // support kObject. When MessageFormat is changed to
+ // understand MeasureFormats, modify this code to do the
+ // right thing. [alan]
+ U_ASSERT(FALSE);
+ break;
+
// better not happen!
case Formattable::kArray:
- // DIE
+ U_ASSERT(FALSE);
break;
}
}
delete [] args;
}
+#define SINGLE_QUOTE ((UChar)0x0027)
+#define CURLY_BRACE_LEFT ((UChar)0x007B)
+#define CURLY_BRACE_RIGHT ((UChar)0x007D)
+
+#define STATE_INITIAL 0
+#define STATE_SINGLE_QUOTE 1
+#define STATE_IN_QUOTE 2
+#define STATE_MSG_ELEMENT 3
+
+#define MAppend(c) if (len < destCapacity) dest[len++] = c; else len++
+
+int32_t umsg_autoQuoteApostrophe(const UChar* pattern,
+ int32_t patternLength,
+ UChar* dest,
+ int32_t destCapacity,
+ UErrorCode* ec)
+{
+ int32_t state = STATE_INITIAL;
+ int32_t braceCount = 0;
+ int32_t len = 0;
+
+ if (ec == NULL || U_FAILURE(*ec)) {
+ return -1;
+ }
+
+ if (pattern == NULL || patternLength < -1 || (dest == NULL && destCapacity > 0)) {
+ *ec = U_ILLEGAL_ARGUMENT_ERROR;
+ return -1;
+ }
+ U_ASSERT(destCapacity >= 0);
+
+ if (patternLength == -1) {
+ patternLength = u_strlen(pattern);
+ }
+
+ for (int i = 0; i < patternLength; ++i) {
+ UChar c = pattern[i];
+ switch (state) {
+ case STATE_INITIAL:
+ switch (c) {
+ case SINGLE_QUOTE:
+ state = STATE_SINGLE_QUOTE;
+ break;
+ case CURLY_BRACE_LEFT:
+ state = STATE_MSG_ELEMENT;
+ ++braceCount;
+ break;
+ }
+ break;
+
+ case STATE_SINGLE_QUOTE:
+ switch (c) {
+ case SINGLE_QUOTE:
+ state = STATE_INITIAL;
+ break;
+ case CURLY_BRACE_LEFT:
+ case CURLY_BRACE_RIGHT:
+ state = STATE_IN_QUOTE;
+ break;
+ default:
+ MAppend(SINGLE_QUOTE);
+ state = STATE_INITIAL;
+ break;
+ }
+ break;
+
+ case STATE_IN_QUOTE:
+ switch (c) {
+ case SINGLE_QUOTE:
+ state = STATE_INITIAL;
+ break;
+ }
+ break;
+
+ case STATE_MSG_ELEMENT:
+ switch (c) {
+ case CURLY_BRACE_LEFT:
+ ++braceCount;
+ break;
+ case CURLY_BRACE_RIGHT:
+ if (--braceCount == 0) {
+ state = STATE_INITIAL;
+ }
+ break;
+ }
+ break;
+
+ default: // Never happens.
+ break;
+ }
+
+ U_ASSERT(len >= 0);
+ MAppend(c);
+ }
+
+ // End of scan
+ if (state == STATE_SINGLE_QUOTE || state == STATE_IN_QUOTE) {
+ MAppend(SINGLE_QUOTE);
+ }
+
+ return u_terminateUChars(dest, destCapacity, len, ec);
+}
+
#endif /* #if !UCONFIG_NO_FORMATTING */