Back to index

php5  5.3.10
msgformat_helpers.cpp
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | This source file is subject to version 3.01 of the PHP license,      |
00006    | that is bundled with this package in the file LICENSE, and is        |
00007    | available through the world-wide-web at the following url:           |
00008    | http://www.php.net/license/3_01.txt                                  |
00009    | If you did not receive a copy of the PHP license and are unable to   |
00010    | obtain it through the world-wide-web, please send a note to          |
00011    | license@php.net so we can mail you a copy immediately.               |
00012    +----------------------------------------------------------------------+
00013    | Authors: Stanislav Malyshev <stas@zend.com>                          |
00014    +----------------------------------------------------------------------+
00015  */
00016 
00017 #ifdef HAVE_CONFIG_H
00018 #include "config.h"
00019 #endif
00020 
00021 #include <math.h>
00022 #include <unicode/msgfmt.h>
00023 #include <unicode/chariter.h>
00024 
00025 extern "C" {
00026 #include "php_intl.h"
00027 #include "msgformat_class.h"
00028 #include "msgformat_format.h"
00029 #include "msgformat_helpers.h"
00030 #include "intl_convert.h"
00031 }
00032 
00033 U_NAMESPACE_BEGIN
00039 class MessageFormatAdapter {
00040 public:
00041     static const Formattable::Type* getArgTypeList(const MessageFormat& m,
00042                                                    int32_t& count);
00043 };
00044 const Formattable::Type*
00045 MessageFormatAdapter::getArgTypeList(const MessageFormat& m,
00046                                      int32_t& count) {
00047     return m.getArgTypeList(count);
00048 }
00049 U_NAMESPACE_END
00050 
00051 U_CFUNC int32_t umsg_format_arg_count(UMessageFormat *fmt) 
00052 {
00053        int32_t fmt_count = 0;
00054        MessageFormatAdapter::getArgTypeList(*(const MessageFormat*)fmt, fmt_count);
00055        return fmt_count;
00056 }
00057 
00058 U_CFUNC void umsg_format_helper(UMessageFormat *fmt, int arg_count, zval **args, UChar **formatted, int *formatted_len, UErrorCode *status TSRMLS_DC)
00059 {
00060        int fmt_count = 0;
00061     const Formattable::Type* argTypes =
00062               MessageFormatAdapter::getArgTypeList(*(const MessageFormat*)fmt, fmt_count);
00063        Formattable* fargs = new Formattable[fmt_count ? fmt_count : 1];
00064 
00065        for(int32_t i = 0; i < fmt_count; ++i) {
00066         UChar  *stringVal = NULL;
00067               int     stringLen = 0;
00068               int64_t tInt64 = 0;
00069 
00070               switch(argTypes[i]) {
00071                      case Formattable::kDate:
00072                             convert_to_long_ex(&args[i]);
00073                             fargs[i].setDate(U_MILLIS_PER_SECOND * (double)Z_LVAL_P(args[i]));
00074                             break;
00075 
00076                      case Formattable::kDouble:
00077                             convert_to_double_ex(&args[i]);
00078                          fargs[i].setDouble(Z_DVAL_P(args[i]));
00079                             break;
00080             
00081                case Formattable::kLong:
00082                             convert_to_long_ex(&args[i]);
00083                          fargs[i].setLong(Z_LVAL_P(args[i]));
00084                             break;
00085 
00086                case Formattable::kInt64:
00087                             if(Z_TYPE_P(args[i]) == IS_DOUBLE) {
00088                                    tInt64 = (int64_t)Z_DVAL_P(args[i]);
00089                             } else if(Z_TYPE_P(args[i]) == IS_LONG) {
00090                                    tInt64 = (int64_t)Z_LVAL_P(args[i]);
00091                             } else {
00092                                    SEPARATE_ZVAL_IF_NOT_REF(&args[i]);
00093                                    convert_scalar_to_number( args[i] TSRMLS_CC );
00094                                    tInt64 = (Z_TYPE_P(args[i]) == IS_DOUBLE)?(int64_t)Z_DVAL_P(args[i]):Z_LVAL_P(args[i]);
00095                             }
00096                          fargs[i].setInt64(tInt64);
00097                             break;
00098             
00099                case Formattable::kString:
00100                       convert_to_string_ex(&args[i]);
00101                             intl_convert_utf8_to_utf16(&stringVal, &stringLen, Z_STRVAL_P(args[i]), Z_STRLEN_P(args[i]), status);
00102                             if(U_FAILURE(*status)){
00103                                    delete[] fargs;
00104                                    return;
00105                             }
00106                             fargs[i].setString(stringVal);
00107                             efree(stringVal);
00108                          break;
00109             
00110                      case Formattable::kArray:
00111                      case Formattable::kObject:
00112                             *status = U_UNSUPPORTED_ERROR;
00113                             delete[] fargs;
00114                             return;
00115         }            
00116        }
00117 
00118     UnicodeString resultStr;
00119     FieldPosition fieldPosition(0);
00120     
00121     /* format the message */
00122     ((const MessageFormat*)fmt)->format(fargs, fmt_count, resultStr, fieldPosition, *status);
00123 
00124     delete[] fargs;
00125 
00126     if(U_FAILURE(*status)){
00127         return;
00128     }
00129 
00130        *formatted_len = resultStr.length();
00131        *formatted = eumalloc(*formatted_len+1);
00132        resultStr.extract(*formatted, *formatted_len+1, *status);
00133 }
00134 
00135 #define cleanup_zvals() for(int j=i;j>=0;j--) { zval_ptr_dtor((*args)+i); }
00136 
00137 U_CFUNC void umsg_parse_helper(UMessageFormat *fmt, int *count, zval ***args, UChar *source, int source_len, UErrorCode *status)
00138 {
00139     UnicodeString srcString(source, source_len);
00140     Formattable *fargs = ((const MessageFormat*)fmt)->parse(srcString, *count, *status);
00141 
00142        if(U_FAILURE(*status)) {
00143               return;
00144        }
00145 
00146        *args = (zval **)safe_emalloc(*count, sizeof(zval *), 0);
00147 
00148     // assign formattables to varargs
00149     for(int32_t i = 0; i < *count; i++) {
00150            int64_t aInt64;
00151               double aDate;
00152               UnicodeString temp;
00153               char *stmp;
00154               int stmp_len;
00155 
00156               ALLOC_INIT_ZVAL((*args)[i]);
00157               
00158               switch(fargs[i].getType()) {
00159         case Formattable::kDate:
00160                      aDate = ((double)fargs[i].getDate())/U_MILLIS_PER_SECOND;
00161                      if(aDate > LONG_MAX || aDate < -LONG_MAX) {
00162                             ZVAL_DOUBLE((*args)[i], aDate<0?ceil(aDate):floor(aDate));
00163                      } else {
00164                             ZVAL_LONG((*args)[i], (long)aDate);
00165                      }
00166             break;
00167 
00168         case Formattable::kDouble:
00169                      ZVAL_DOUBLE((*args)[i], (double)fargs[i].getDouble());
00170             break;
00171 
00172         case Formattable::kLong:
00173                      ZVAL_LONG((*args)[i], fargs[i].getLong());
00174             break;
00175 
00176         case Formattable::kInt64:
00177             aInt64 = fargs[i].getInt64();
00178                      if(aInt64 > LONG_MAX || aInt64 < -LONG_MAX) {
00179                             ZVAL_DOUBLE((*args)[i], (double)aInt64);
00180                      } else {
00181                             ZVAL_LONG((*args)[i], (long)aInt64);
00182                      }
00183             break;
00184 
00185         case Formattable::kString:
00186             fargs[i].getString(temp);
00187                      intl_convert_utf16_to_utf8(&stmp, &stmp_len, temp.getBuffer(), temp.length(), status);
00188                      if(U_FAILURE(*status)) {
00189                             cleanup_zvals();
00190                             return;
00191                      }
00192                      ZVAL_STRINGL((*args)[i], stmp, stmp_len, 0);
00193             break;
00194 
00195         case Formattable::kObject:
00196         case Formattable::kArray:
00197             *status = U_ILLEGAL_ARGUMENT_ERROR;
00198                      cleanup_zvals();
00199             break;
00200         }
00201     }
00202        delete[] fargs;
00203 }
00204 
00205 /*
00206  * Local variables:
00207  * tab-width: 4
00208  * c-basic-offset: 4
00209  * End:
00210  * vim600: noet sw=4 ts=4 fdm=marker
00211  * vim<600: noet sw=4 ts=4
00212  */