Index: icu46/source/i18n/umsg.cpp |
=================================================================== |
--- icu46/source/i18n/umsg.cpp (revision 0) |
+++ icu46/source/i18n/umsg.cpp (revision 0) |
@@ -0,0 +1,706 @@ |
+/* |
+******************************************************************************* |
+* |
+* Copyright (C) 1999-2006, 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/utypes.h" |
+ |
+#if !UCONFIG_NO_FORMATTING |
+ |
+#include "unicode/umsg.h" |
+#include "unicode/ustring.h" |
+#include "unicode/fmtable.h" |
+#include "unicode/msgfmt.h" |
+#include "unicode/unistr.h" |
+#include "cpputils.h" |
+#include "uassert.h" |
+#include "ustr_imp.h" |
+ |
+U_NAMESPACE_USE |
+ |
+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; |
+ //argument checking defered to subsequent method calls |
+ // 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_EXPORT2 |
+u_vformatMessage( const char *locale, |
+ const UChar *pattern, |
+ int32_t patternLength, |
+ UChar *result, |
+ int32_t resultLength, |
+ va_list ap, |
+ UErrorCode *status) |
+ |
+{ |
+ //argument checking defered to subsequent method calls |
+ UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,NULL,status); |
+ 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; |
+ //argument checking defered to subsequent method calls |
+ // 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_EXPORT2 |
+u_vformatMessageWithError( const char *locale, |
+ const UChar *pattern, |
+ int32_t patternLength, |
+ UChar *result, |
+ int32_t resultLength, |
+ UParseError *parseError, |
+ va_list ap, |
+ UErrorCode *status) |
+ |
+{ |
+ //argument checking defered to subsequent method calls |
+ 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; |
+ //argument checking defered to subsequent method calls |
+ |
+ // 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_EXPORT2 |
+u_vparseMessage(const char *locale, |
+ const UChar *pattern, |
+ int32_t patternLength, |
+ const UChar *source, |
+ int32_t sourceLength, |
+ va_list ap, |
+ UErrorCode *status) |
+{ |
+ //argument checking defered to subsequent method calls |
+ 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; |
+ |
+ //argument checking defered to subsequent method calls |
+ |
+ // 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_EXPORT2 |
+u_vparseMessageWithError(const char *locale, |
+ const UChar *pattern, |
+ int32_t patternLength, |
+ const UChar *source, |
+ int32_t sourceLength, |
+ va_list ap, |
+ UParseError *error, |
+ UErrorCode* status) |
+{ |
+ //argument checking defered to subsequent method calls |
+ 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* U_EXPORT2 |
+umsg_open( const UChar *pattern, |
+ int32_t patternLength, |
+ const char *locale, |
+ UParseError *parseError, |
+ UErrorCode *status) |
+{ |
+ //check arguments |
+ if(status==NULL || U_FAILURE(*status)) |
+ { |
+ return 0; |
+ } |
+ if(pattern==NULL||patternLength<-1){ |
+ *status=U_ILLEGAL_ARGUMENT_ERROR; |
+ return 0; |
+ } |
+ |
+ 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); |
+ |
+ retVal = (UMessageFormat*) new MessageFormat(patString,Locale(locale),*parseError,*status); |
+ |
+ if(retVal == 0) { |
+ *status = U_MEMORY_ALLOCATION_ERROR; |
+ return 0; |
+ } |
+ return retVal; |
+} |
+ |
+U_CAPI void U_EXPORT2 |
+umsg_close(UMessageFormat* format) |
+{ |
+ //check arguments |
+ if(format==NULL){ |
+ return; |
+ } |
+ delete (MessageFormat*) format; |
+} |
+ |
+U_CAPI UMessageFormat U_EXPORT2 |
+umsg_clone(const UMessageFormat *fmt, |
+ UErrorCode *status) |
+{ |
+ //check arguments |
+ if(status==NULL || U_FAILURE(*status)){ |
+ return NULL; |
+ } |
+ if(fmt==NULL){ |
+ *status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return NULL; |
+ } |
+ UMessageFormat retVal = (UMessageFormat)((MessageFormat*)fmt)->clone(); |
+ if(retVal == 0) { |
+ *status = U_MEMORY_ALLOCATION_ERROR; |
+ return 0; |
+ } |
+ return retVal; |
+} |
+ |
+U_CAPI void U_EXPORT2 |
+umsg_setLocale(UMessageFormat *fmt, const char* locale) |
+{ |
+ //check arguments |
+ if(fmt==NULL){ |
+ return; |
+ } |
+ ((MessageFormat*)fmt)->setLocale(Locale(locale)); |
+} |
+ |
+U_CAPI const char* U_EXPORT2 |
+umsg_getLocale(const UMessageFormat *fmt) |
+{ |
+ //check arguments |
+ if(fmt==NULL){ |
+ return ""; |
+ } |
+ return ((const MessageFormat*)fmt)->getLocale().getName(); |
+} |
+ |
+U_CAPI void U_EXPORT2 |
+umsg_applyPattern(UMessageFormat *fmt, |
+ const UChar* pattern, |
+ int32_t patternLength, |
+ UParseError* parseError, |
+ UErrorCode* status) |
+{ |
+ //check arguments |
+ UParseError tErr; |
+ if(status ==NULL||U_FAILURE(*status)){ |
+ return ; |
+ } |
+ if(fmt==NULL||pattern==NULL||patternLength<-1){ |
+ *status=U_ILLEGAL_ARGUMENT_ERROR; |
+ return ; |
+ } |
+ |
+ if(parseError==NULL){ |
+ parseError = &tErr; |
+ } |
+ if(patternLength<-1){ |
+ patternLength=u_strlen(pattern); |
+ } |
+ |
+ ((MessageFormat*)fmt)->applyPattern(UnicodeString(pattern,patternLength),*parseError,*status); |
+} |
+ |
+U_CAPI int32_t U_EXPORT2 |
+umsg_toPattern(const UMessageFormat *fmt, |
+ UChar* result, |
+ int32_t resultLength, |
+ UErrorCode* status) |
+{ |
+ //check arguments |
+ if(status ==NULL||U_FAILURE(*status)){ |
+ return -1; |
+ } |
+ if(fmt==NULL||resultLength<0 || (resultLength>0 && result==0)){ |
+ *status=U_ILLEGAL_ARGUMENT_ERROR; |
+ return -1; |
+ } |
+ |
+ |
+ UnicodeString res; |
+ if(!(result==NULL && resultLength==0)) { |
+ // NULL destination for pure preflighting: empty dummy string |
+ // otherwise, alias the destination buffer |
+ res.setTo(result, 0, resultLength); |
+ } |
+ ((const MessageFormat*)fmt)->toPattern(res); |
+ return res.extract(result, resultLength, *status); |
+} |
+ |
+U_CAPI int32_t |
+umsg_format( const UMessageFormat *fmt, |
+ UChar *result, |
+ int32_t resultLength, |
+ UErrorCode *status, |
+ ...) |
+{ |
+ va_list ap; |
+ int32_t actLen; |
+ //argument checking defered to last method call umsg_vformat which |
+ //saves time when arguments are valid and we dont care when arguments are not |
+ //since we return an error anyway |
+ |
+ |
+ // start vararg processing |
+ va_start(ap, status); |
+ |
+ actLen = umsg_vformat(fmt,result,resultLength,ap,status); |
+ |
+ // end vararg processing |
+ va_end(ap); |
+ |
+ 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, |
+ int32_t resultLength, |
+ va_list ap, |
+ UErrorCode *status) |
+{ |
+ //check arguments |
+ if(status==0 || U_FAILURE(*status)) |
+ { |
+ return -1; |
+ } |
+ if(fmt==NULL||resultLength<0 || (resultLength>0 && result==0)) { |
+ *status=U_ILLEGAL_ARGUMENT_ERROR; |
+ return -1; |
+ } |
+ |
+ int32_t count =0; |
+ const Formattable::Type* argTypes = |
+ 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]; |
+ |
+ // 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; |
+ int64_t tInt64 = 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::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); |
+ }else{ |
+ *status=U_ILLEGAL_ARGUMENT_ERROR; |
+ } |
+ 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; |
+ |
+ 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; |
+ } |
+ } |
+ UnicodeString resultStr; |
+ FieldPosition fieldPosition(0); |
+ |
+ /* format the message */ |
+ ((const MessageFormat*)fmt)->format(args,count,resultStr,fieldPosition,*status); |
+ |
+ delete[] args; |
+ |
+ if(U_FAILURE(*status)){ |
+ return -1; |
+ } |
+ |
+ return resultStr.extract(result, resultLength, *status); |
+} |
+ |
+U_CAPI void |
+umsg_parse( const UMessageFormat *fmt, |
+ const UChar *source, |
+ int32_t sourceLength, |
+ int32_t *count, |
+ UErrorCode *status, |
+ ...) |
+{ |
+ va_list ap; |
+ //argument checking defered to last method call umsg_vparse which |
+ //saves time when arguments are valid and we dont care when arguments are not |
+ //since we return an error anyway |
+ |
+ // start vararg processing |
+ va_start(ap, status); |
+ |
+ umsg_vparse(fmt,source,sourceLength,count,ap,status); |
+ |
+ // end vararg processing |
+ va_end(ap); |
+} |
+ |
+U_CAPI void U_EXPORT2 |
+umsg_vparse(const UMessageFormat *fmt, |
+ const UChar *source, |
+ int32_t sourceLength, |
+ int32_t *count, |
+ va_list ap, |
+ UErrorCode *status) |
+{ |
+ //check arguments |
+ if(status==NULL||U_FAILURE(*status)) |
+ { |
+ return; |
+ } |
+ if(fmt==NULL||source==NULL || sourceLength<-1 || count==NULL){ |
+ *status=U_ILLEGAL_ARGUMENT_ERROR; |
+ return; |
+ } |
+ if(sourceLength==-1){ |
+ sourceLength=u_strlen(source); |
+ } |
+ |
+ UnicodeString srcString(source,sourceLength); |
+ Formattable *args = ((const MessageFormat*)fmt)->parse(source,*count,*status); |
+ UDate *aDate; |
+ double *aDouble; |
+ UChar *aString; |
+ int32_t* aInt; |
+ int64_t* aInt64; |
+ UnicodeString temp; |
+ int len =0; |
+ // assign formattables to varargs |
+ for(int32_t i = 0; i < *count; i++) { |
+ switch(args[i].getType()) { |
+ |
+ case Formattable::kDate: |
+ aDate = va_arg(ap, UDate*); |
+ if(aDate){ |
+ *aDate = args[i].getDate(); |
+ }else{ |
+ *status=U_ILLEGAL_ARGUMENT_ERROR; |
+ } |
+ break; |
+ |
+ case Formattable::kDouble: |
+ aDouble = va_arg(ap, double*); |
+ if(aDouble){ |
+ *aDouble = args[i].getDouble(); |
+ }else{ |
+ *status=U_ILLEGAL_ARGUMENT_ERROR; |
+ } |
+ break; |
+ |
+ case Formattable::kLong: |
+ aInt = va_arg(ap, int32_t*); |
+ if(aInt){ |
+ *aInt = (int32_t) args[i].getLong(); |
+ }else{ |
+ *status=U_ILLEGAL_ARGUMENT_ERROR; |
+ } |
+ 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){ |
+ args[i].getString(temp); |
+ len = temp.length(); |
+ temp.extract(0,len,aString); |
+ aString[len]=0; |
+ }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); |
+ break; |
+ |
+ // better not happen! |
+ case Formattable::kArray: |
+ U_ASSERT(FALSE); |
+ break; |
+ } |
+ } |
+ |
+ // clean up |
+ 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; |
+ } |
+ |
+ 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; |
+ } |
+ |
+ 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 */ |
Property changes on: icu46/source/i18n/umsg.cpp |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |