+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
*
-* Copyright (C) 1999-2004, 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/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(patString,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
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);
}
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( const UMessageFormat *fmt,
UChar *result,
// 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;
}
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);
+ // Unused argument number. Read and ignore a pointer argument.
+ va_arg(ap, void*);
break;
+
+ default:
+ // Unknown/unsupported argument type.
+ UPRV_UNREACHABLE;
}
}
UnicodeString resultStr;
- FieldPosition fieldPosition(0);
+ FieldPosition fieldPosition(FieldPosition::DONT_CARE);
/* format the message */
((const MessageFormat*)fmt)->format(args,count,resultStr,fieldPosition,*status);
}
UnicodeString srcString(source,sourceLength);
- Formattable *args = ((const MessageFormat*)fmt)->parse(source,*count,*status);
+ Formattable *args = ((const MessageFormat*)fmt)->parse(srcString,*count,*status);
UDate *aDate;
double *aDouble;
UChar *aString;
// support kObject. When MessageFormat is changed to
// understand MeasureFormats, modify this code to do the
// right thing. [alan]
- U_ASSERT(FALSE);
- break;
+ UPRV_UNREACHABLE;
// better not happen!
case Formattable::kArray:
- U_ASSERT(FALSE);
- break;
+ UPRV_UNREACHABLE;
}
}
delete [] args;
}
-U_CAPI const char* U_EXPORT2
-umsg_getLocaleByType(const UMessageFormat *fmt,
- ULocDataLocaleType type,
- UErrorCode* status)
+#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)
{
- if (fmt == NULL) {
- if (U_SUCCESS(*status)) {
- *status = U_ILLEGAL_ARGUMENT_ERROR;
+ 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;
}
- return NULL;
+
+ U_ASSERT(len >= 0);
+ MAppend(c);
}
- return ((Format*)fmt)->getLocaleID(type, *status);
+
+ // 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 */