PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/intl/converter - converter.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 356 532 66.9 %
Date: 2014-10-22 Functions: 29 39 74.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | This source file is subject to version 3.01 of the PHP license,      |
       6             :    | that is bundled with this package in the file LICENSE, and is        |
       7             :    | available through the world-wide-web at the following url:           |
       8             :    | http://www.php.net/license/3_01.txt                                  |
       9             :    | If you did not receive a copy of the PHP license and are unable to   |
      10             :    | obtain it through the world-wide-web, please send a note to          |
      11             :    | license@php.net so we can mail you a copy immediately.               |
      12             :    +----------------------------------------------------------------------+
      13             :    | Authors: Sara Golemon <pollita@php.net>                              |
      14             :    +----------------------------------------------------------------------+
      15             :  */
      16             : 
      17             : #include "converter.h"
      18             : #include "zend_exceptions.h"
      19             : 
      20             : #include <unicode/utypes.h>
      21             : #include <unicode/ucnv.h>
      22             : #include <unicode/ustring.h>
      23             : 
      24             : #include "../intl_error.h"
      25             : 
      26             : typedef struct _php_converter_object {
      27             : #ifdef ZTS
      28             :         void ***tsrm_ls;
      29             : #endif
      30             :         UConverter *src, *dest;
      31             :         zend_fcall_info to_cb, from_cb;
      32             :         zend_fcall_info_cache to_cache, from_cache;
      33             :         intl_error error;
      34             :         zend_object obj;
      35             : } php_converter_object;
      36             : 
      37             : 
      38          45 : static inline php_converter_object *php_converter_fetch_object(zend_object *obj) {
      39          45 :         return (php_converter_object *)((char*)(obj) - XtOffsetOf(php_converter_object, obj));
      40             : }
      41             : #define Z_INTL_CONVERTER_P(zv) php_converter_fetch_object(Z_OBJ_P(zv))
      42             : 
      43             : static zend_class_entry     *php_converter_ce;
      44             : static zend_object_handlers  php_converter_object_handlers;
      45             : 
      46             : #define CONV_GET(pzv)  (Z_INTL_CONVERTER_P((pzv)))
      47             : #define THROW_UFAILURE(obj, fname, error) php_converter_throw_failure(obj, error TSRMLS_CC, \
      48             :                                           fname "() returned error " ZEND_LONG_FMT ": %s", (zend_long)error, u_errorName(error))
      49             : 
      50             : /* {{{ php_converter_throw_failure */
      51          12 : static inline void php_converter_throw_failure(php_converter_object *objval, UErrorCode error TSRMLS_DC, const char *format, ...) {
      52          12 :         intl_error *err = objval ? &(objval->error) : NULL;
      53             :         char message[1024];
      54             :         va_list vargs;
      55             : 
      56          12 :         va_start(vargs, format);
      57          12 :         vsnprintf(message, sizeof(message), format, vargs);
      58          12 :         va_end(vargs);
      59             : 
      60          12 :         intl_errors_set(err, error, message, 1 TSRMLS_CC);
      61          12 : }
      62             : /* }}} */
      63             : 
      64             : /* {{{ php_converter_default_callback */
      65          23 : static void php_converter_default_callback(zval *return_value, zval *zobj, zend_long reason, zval *error TSRMLS_DC) {
      66          23 :         ZVAL_DEREF(error);
      67             :         zval_dtor(error);
      68          23 :         ZVAL_LONG(error, U_ZERO_ERROR);
      69             :         /* Basic functionality so children can call parent::toUCallback() */
      70          23 :         switch (reason) {
      71             :                 case UCNV_UNASSIGNED:
      72             :                 case UCNV_ILLEGAL:
      73             :                 case UCNV_IRREGULAR:
      74             :                 {
      75           7 :                         php_converter_object *objval = (php_converter_object*)CONV_GET(zobj);
      76             :                         char chars[127];
      77           7 :                         int8_t chars_len = sizeof(chars);
      78           7 :                         UErrorCode uerror = U_ZERO_ERROR;
      79           7 :             if(!objval->src) {
      80           1 :                 php_converter_throw_failure(objval, U_INVALID_STATE_ERROR TSRMLS_CC, "Source Converter has not been initialized yet");
      81           1 :                                 chars[0] = 0x1A;
      82           1 :                                 chars[1] = 0;
      83           1 :                                 chars_len = 1;
      84           1 :                 ZVAL_LONG(error, U_INVALID_STATE_ERROR);
      85           2 :                 RETVAL_STRINGL(chars, chars_len);
      86           1 :                 return;
      87             :             }
      88             : 
      89             :                         /* Yes, this is fairly wasteful at first glance,
      90             :                          * but considering that the alternative is to store
      91             :                          * what's sent into setSubstChars() and the fact
      92             :                          * that this is an extremely unlikely codepath
      93             :                          * I'd rather take the CPU hit here, than waste time
      94             :                          * storing a value I'm unlikely to use.
      95             :                          */
      96           6 :                         ucnv_getSubstChars(objval->src, chars, &chars_len, &uerror);
      97           6 :                         if (U_FAILURE(uerror)) {
      98           0 :                                 THROW_UFAILURE(objval, "ucnv_getSubstChars", uerror);
      99           0 :                                 chars[0] = 0x1A;
     100           0 :                                 chars[1] = 0;
     101           0 :                                 chars_len = 1;
     102           0 :                 ZVAL_LONG(error, uerror);
     103             :                         }
     104          12 :                         RETVAL_STRINGL(chars, chars_len);
     105             :                 }
     106             :         }
     107             : }
     108             : /* }}} */
     109             : 
     110             : /* {{{ proto void UConverter::toUCallback(long $reason,
     111             :                                           string $source, string $codeUnits,
     112             :                                           long &$error) */
     113             : ZEND_BEGIN_ARG_INFO_EX(php_converter_toUCallback_arginfo, 0, ZEND_RETURN_VALUE, 4)
     114             :         ZEND_ARG_INFO(0, reason)
     115             :         ZEND_ARG_INFO(0, source)
     116             :         ZEND_ARG_INFO(0, codeUnits)
     117             :         ZEND_ARG_INFO(1, error)
     118             : ZEND_END_ARG_INFO();
     119          11 : static PHP_METHOD(UConverter, toUCallback) {
     120             :         zend_long reason;
     121             :         zval *source, *codeUnits, *error;
     122             : 
     123          11 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lzzz",
     124             :                 &reason, &source, &codeUnits, &error) == FAILURE) {
     125           0 :                 return;
     126             :         }
     127             : 
     128          11 :         php_converter_default_callback(return_value, getThis(), reason, error TSRMLS_CC);
     129             : }
     130             : /* }}} */
     131             : 
     132             : /* {{{ proto void UConverter::fromUCallback(long $reason,
     133             :                                             Array $source, long $codePoint,
     134             :                                             long &$error) */
     135             : ZEND_BEGIN_ARG_INFO_EX(php_converter_fromUCallback_arginfo, 0, ZEND_RETURN_VALUE, 4)
     136             :         ZEND_ARG_INFO(0, reason)
     137             :         ZEND_ARG_INFO(0, source)
     138             :         ZEND_ARG_INFO(0, codePoint)
     139             :         ZEND_ARG_INFO(1, error)
     140             : ZEND_END_ARG_INFO();
     141          12 : static PHP_METHOD(UConverter, fromUCallback) {
     142             :         zend_long reason;
     143             :         zval *source, *codePoint, *error;
     144             : 
     145          12 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lzzz",
     146             :                 &reason, &source, &codePoint, &error) == FAILURE) {
     147           0 :                 return;
     148             :         }
     149             : 
     150          12 :         php_converter_default_callback(return_value, getThis(), reason, error TSRMLS_CC);
     151             : }
     152             : /* }}} */
     153             : 
     154             : /* {{{ php_converter_check_limits */
     155          18 : static inline zend_bool php_converter_check_limits(php_converter_object *objval, zend_long available, zend_long needed TSRMLS_DC) {
     156          18 :         if (available < needed) {
     157           0 :                 php_converter_throw_failure(objval, U_BUFFER_OVERFLOW_ERROR TSRMLS_CC, "Buffer overrun %pd bytes needed, %pd available", needed, available);
     158           0 :                 return 0;
     159             :         }
     160          18 :         return 1;
     161             : }
     162             : /* }}} */
     163             : 
     164             : #define TARGET_CHECK(cnvargs, needed) php_converter_check_limits(objval, cnvargs->targetLimit - cnvargs->target, needed TSRMLS_CC)
     165             : 
     166             : /* {{{ php_converter_append_toUnicode_target */
     167          26 : static void php_converter_append_toUnicode_target(zval *val, UConverterToUnicodeArgs *args, php_converter_object *objval TSRMLS_DC) {
     168          26 :         switch (Z_TYPE_P(val)) {
     169             :                 case IS_NULL:
     170             :                         /* Code unit is being skipped */
     171          16 :                         return;
     172             :                 case IS_LONG:
     173             :                 {
     174           2 :                         zend_long lval = Z_LVAL_P(val);
     175           2 :                         if ((lval < 0) || (lval > 0x10FFFF)) {
     176           0 :                                 php_converter_throw_failure(objval, U_ILLEGAL_ARGUMENT_ERROR TSRMLS_CC, "Invalid codepoint U+%04lx", lval);
     177           0 :                                 return;
     178             :                         }
     179           2 :                         if (lval > 0xFFFF) {
     180             :                                 /* Supplemental planes U+010000 - U+10FFFF */
     181           0 :                                 if (TARGET_CHECK(args, 2)) {
     182             :                                         /* TODO: Find the ICU call which does this properly */
     183           0 :                                         *(args->target++) = (UChar)(((lval - 0x10000) >> 10)   | 0xD800);
     184           0 :                                         *(args->target++) = (UChar)(((lval - 0x10000) & 0x3FF) | 0xDC00);
     185             :                                 }
     186           0 :                                 return;
     187             :                         }
     188             :                         /* Non-suggogate BMP codepoint */
     189           2 :                         if (TARGET_CHECK(args, 1)) {
     190           2 :                                 *(args->target++) = (UChar)lval;
     191             :                         }
     192           2 :                         return;
     193             :                 }
     194             :                 case IS_STRING:
     195             :                 {
     196           6 :                         const char *strval = Z_STRVAL_P(val);
     197           6 :                         int i = 0, strlen = Z_STRLEN_P(val);
     198             : 
     199          18 :                         while((i != strlen) && TARGET_CHECK(args, 1)) {
     200             :                                 UChar c;
     201           6 :                                 U8_NEXT(strval, i, strlen, c);
     202           6 :                                 *(args->target++) = c;
     203             :                         }
     204           6 :                         return;
     205             :                 }
     206             :                 case IS_ARRAY:
     207             :                 {
     208           2 :                         HashTable *ht = Z_ARRVAL_P(val);
     209             :                         zval *tmpzval;
     210             : 
     211           6 :                         ZEND_HASH_FOREACH_VAL(ht, tmpzval) {
     212           2 :                                 php_converter_append_toUnicode_target(tmpzval, args, objval TSRMLS_CC);
     213             :                         } ZEND_HASH_FOREACH_END();
     214           2 :                         return;
     215             :                 }
     216             :                 default:
     217           0 :                         php_converter_throw_failure(objval, U_ILLEGAL_ARGUMENT_ERROR TSRMLS_CC,
     218             :                                                     "toUCallback() specified illegal type for substitution character");
     219             :         }
     220             : }
     221             : /* }}} */
     222             : 
     223             : /* {{{ php_converter_to_u_callback */
     224          24 : static void php_converter_to_u_callback(const void *context,
     225             :                                         UConverterToUnicodeArgs *args,
     226             :                                         const char *codeUnits, int32_t length,
     227             :                                         UConverterCallbackReason reason,
     228             :                                         UErrorCode *pErrorCode) {
     229          24 :         php_converter_object *objval = (php_converter_object*)context;
     230             :         zval retval;
     231             :         zval zargs[4];
     232             : #ifdef ZTS
     233             :         TSRMLS_D = objval->tsrm_ls;
     234             : #endif
     235             : 
     236          24 :         ZVAL_LONG(&zargs[0], reason);
     237          48 :         ZVAL_STRINGL(&zargs[1], args->source, args->sourceLimit - args->source);
     238          48 :         ZVAL_STRINGL(&zargs[2], codeUnits, length);
     239          24 :         ZVAL_LONG(&zargs[3], *pErrorCode);
     240             : 
     241          24 :         objval->to_cb.param_count    = 4;
     242          24 :         objval->to_cb.params = zargs;
     243          24 :         objval->to_cb.retval = &retval;
     244          24 :         objval->to_cb.no_separation  = 0;
     245          24 :         if (zend_call_function(&(objval->to_cb), &(objval->to_cache) TSRMLS_CC) == FAILURE) {
     246             :                 /* Unlikely */
     247           0 :                 php_converter_throw_failure(objval, U_INTERNAL_PROGRAM_ERROR TSRMLS_CC, "Unexpected failure calling toUCallback()");
     248          24 :         } else if (!Z_ISUNDEF(retval)) {
     249          24 :                 php_converter_append_toUnicode_target(&retval, args, objval TSRMLS_CC);
     250          24 :                 zval_ptr_dtor(&retval);
     251             :         }
     252             : 
     253          24 :         if (Z_TYPE(zargs[3]) == IS_LONG) {
     254           0 :                 *pErrorCode = Z_LVAL(zargs[3]);
     255          48 :         } else if (Z_ISREF(zargs[3]) && Z_TYPE_P(Z_REFVAL(zargs[3])) == IS_LONG) {
     256          24 :                 *pErrorCode = Z_LVAL_P(Z_REFVAL(zargs[3]));
     257             :         }
     258             : 
     259          24 :         zval_ptr_dtor(&zargs[0]);
     260          24 :         zval_ptr_dtor(&zargs[1]);
     261          24 :         zval_ptr_dtor(&zargs[2]);
     262          24 :         zval_ptr_dtor(&zargs[3]);
     263          24 : }
     264             : /* }}} */
     265             : 
     266             : /* {{{ php_converter_append_fromUnicode_target */
     267          28 : static void php_converter_append_fromUnicode_target(zval *val, UConverterFromUnicodeArgs *args, php_converter_object *objval TSRMLS_DC) {
     268          28 :         switch (Z_TYPE_P(val)) {
     269             :                 case IS_NULL:
     270             :                         /* Ignore */
     271          16 :                         return;
     272             :                 case IS_LONG:
     273           2 :                         if (TARGET_CHECK(args, 1)) {
     274           2 :                                 *(args->target++) = Z_LVAL_P(val);
     275             :                         }
     276           2 :                         return;
     277             :                 case IS_STRING:
     278             :                 {
     279           8 :                         int vallen = Z_STRLEN_P(val);
     280           8 :                         if (TARGET_CHECK(args, vallen)) {
     281           8 :                                 memcpy(args->target, Z_STRVAL_P(val), vallen);
     282           8 :                                 args->target += vallen;
     283             :                         }
     284           8 :                         return;
     285             :                 }
     286             :                 case IS_ARRAY:
     287             :                 {
     288           2 :                         HashTable *ht = Z_ARRVAL_P(val);
     289             :                         zval *tmpzval;
     290           6 :                         ZEND_HASH_FOREACH_VAL(ht, tmpzval) {
     291           2 :                                 php_converter_append_fromUnicode_target(tmpzval, args, objval TSRMLS_CC);
     292             :                         } ZEND_HASH_FOREACH_END();
     293           2 :                         return;
     294             :                 }
     295             :                 default:
     296           0 :                         php_converter_throw_failure(objval, U_ILLEGAL_ARGUMENT_ERROR TSRMLS_CC, "fromUCallback() specified illegal type for substitution character");
     297             :         }
     298             : }
     299             : /* }}} */
     300             : 
     301             : /* {{{ php_converter_from_u_callback */
     302          26 : static void php_converter_from_u_callback(const void *context,
     303             :                                           UConverterFromUnicodeArgs *args,
     304             :                                           const UChar *codeUnits, int32_t length, UChar32 codePoint,
     305             :                                           UConverterCallbackReason reason,
     306             :                                           UErrorCode *pErrorCode) {
     307          26 :         php_converter_object *objval = (php_converter_object*)context;
     308             :         zval retval;
     309             :         zval zargs[4];
     310             :         int i;
     311             : #ifdef ZTS
     312             :         TSRMLS_D = objval->tsrm_ls;
     313             : #endif
     314             : 
     315          26 :         ZVAL_LONG(&zargs[0], reason);
     316          26 :         array_init(&zargs[1]);
     317          26 :         i = 0;
     318          64 :         while (i < length) {
     319             :                 UChar32 c;
     320          12 :                 U16_NEXT(codeUnits, i, length, c);
     321          12 :                 add_next_index_long(&zargs[1], c);
     322             :         }
     323          26 :         ZVAL_LONG(&zargs[2], codePoint);
     324          26 :         ZVAL_LONG(&zargs[3], *pErrorCode);
     325             : 
     326          26 :         objval->from_cb.param_count = 4;
     327          26 :         objval->from_cb.params = zargs;
     328          26 :         objval->from_cb.retval = &retval;
     329          26 :         objval->from_cb.no_separation  = 0;
     330          26 :         if (zend_call_function(&(objval->from_cb), &(objval->from_cache) TSRMLS_CC) == FAILURE) {
     331             :                 /* Unlikely */
     332           0 :                 php_converter_throw_failure(objval, U_INTERNAL_PROGRAM_ERROR TSRMLS_CC, "Unexpected failure calling fromUCallback()");
     333          26 :         } else if (!Z_ISUNDEF(retval)) {
     334          26 :                 php_converter_append_fromUnicode_target(&retval, args, objval TSRMLS_CC);
     335          26 :                 zval_ptr_dtor(&retval);
     336             :         }
     337             : 
     338          26 :         if (Z_TYPE(zargs[3]) == IS_LONG) {
     339           0 :                 *pErrorCode = Z_LVAL(zargs[3]);
     340          52 :         } else if (Z_ISREF(zargs[3]) && Z_TYPE_P(Z_REFVAL(zargs[3])) == IS_LONG) {
     341          26 :                 *pErrorCode = Z_LVAL_P(Z_REFVAL(zargs[3]));
     342             :         }
     343             : 
     344          26 :         zval_ptr_dtor(&zargs[0]);
     345          26 :         zval_ptr_dtor(&zargs[1]);
     346          26 :         zval_ptr_dtor(&zargs[2]);
     347          26 :         zval_ptr_dtor(&zargs[3]);
     348          26 : }
     349             : /* }}} */
     350             : 
     351             : /* {{{ php_converter_set_callbacks */
     352          15 : static inline zend_bool php_converter_set_callbacks(php_converter_object *objval, UConverter *cnv TSRMLS_DC) {
     353          15 :         zend_bool ret = 1;
     354          15 :         UErrorCode error = U_ZERO_ERROR;
     355             : 
     356          15 :         if (objval->obj.ce == php_converter_ce) {
     357             :                 /* Short-circuit having to go through method calls and data marshalling
     358             :                  * when we're using default behavior
     359             :                  */
     360          11 :                 return 1;
     361             :         }
     362             : 
     363           4 :         ucnv_setToUCallBack(cnv, (UConverterToUCallback)php_converter_to_u_callback, (const void*)objval,
     364             :                                  NULL, NULL, &error);
     365           4 :         if (U_FAILURE(error)) {
     366           0 :                 THROW_UFAILURE(objval, "ucnv_setToUCallBack", error);
     367           0 :                 ret = 0;
     368             :         }
     369             : 
     370           4 :         error = U_ZERO_ERROR;
     371           4 :         ucnv_setFromUCallBack(cnv, (UConverterFromUCallback)php_converter_from_u_callback, (const void*)objval,
     372             :                                     NULL, NULL, &error);
     373           4 :         if (U_FAILURE(error)) {
     374           0 :                 THROW_UFAILURE(objval, "ucnv_setFromUCallBack", error);
     375           0 :                 ret = 0;
     376             :         }
     377           4 :         return ret;
     378             : }
     379             : /* }}} */
     380             : 
     381             : /* {{{ php_converter_set_encoding */
     382          38 : static zend_bool php_converter_set_encoding(php_converter_object *objval,
     383             :                                             UConverter **pcnv,
     384             :                                             const char *enc, int enc_len
     385             :                                             TSRMLS_DC) {
     386          38 :         UErrorCode error = U_ZERO_ERROR;
     387          38 :         UConverter *cnv = ucnv_open(enc, &error);
     388             : 
     389          38 :         if (error == U_AMBIGUOUS_ALIAS_WARNING) {
     390           0 :                 UErrorCode getname_error = U_ZERO_ERROR;
     391           0 :                 const char *actual_encoding = ucnv_getName(cnv, &getname_error);
     392           0 :                 if (U_FAILURE(getname_error)) {
     393             :                         /* Should never happen */
     394           0 :                         actual_encoding = "(unknown)";
     395             :                 }
     396           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ambiguous encoding specified, using %s", actual_encoding);
     397          38 :         } else if (U_FAILURE(error)) {
     398           3 :                 if (objval) {
     399           3 :                         THROW_UFAILURE(objval, "ucnv_open", error);
     400             :                 } else {
     401           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error setting encoding: %d - %s", (int)error, u_errorName(error));
     402             :                 }
     403           3 :                 return 0;
     404             :         }
     405             : 
     406          35 :         if (objval && !php_converter_set_callbacks(objval, cnv TSRMLS_CC)) {
     407           0 :                 return 0;
     408             :         }
     409             : 
     410          35 :         if (*pcnv) {
     411           0 :                 ucnv_close(*pcnv);
     412             :         }
     413          35 :         *pcnv = cnv;
     414          35 :         return 1;
     415             : }
     416             : /* }}} */
     417             : 
     418             : /* {{{ php_converter_do_set_encoding */
     419             : ZEND_BEGIN_ARG_INFO_EX(php_converter_set_encoding_arginfo, 0, ZEND_RETURN_VALUE, 1)
     420             :         ZEND_ARG_INFO(0, encoding)
     421             : ZEND_END_ARG_INFO();
     422           0 : static void php_converter_do_set_encoding(UConverter *cnv, INTERNAL_FUNCTION_PARAMETERS) {
     423           0 :         php_converter_object *objval = CONV_GET(getThis());
     424             :         char *enc;
     425             :         size_t enc_len;
     426             : 
     427           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &enc, &enc_len) == FAILURE) {
     428           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "Bad arguments, "
     429             :                                 "expected one string argument", 0 TSRMLS_CC);
     430           0 :                 RETURN_FALSE;
     431             :         }
     432           0 :         intl_errors_reset(&objval->error TSRMLS_CC);
     433             : 
     434           0 :         RETURN_BOOL(php_converter_set_encoding(objval, &(objval->src), enc, enc_len TSRMLS_CC));
     435             : }
     436             : /* }}} */
     437             : 
     438             : /* {{{ proto bool UConverter::setSourceEncoding(string encoding) */
     439           0 : static PHP_METHOD(UConverter, setSourceEncoding) {
     440           0 :         php_converter_object *objval = CONV_GET(getThis());
     441           0 :         php_converter_do_set_encoding(objval->src, INTERNAL_FUNCTION_PARAM_PASSTHRU);
     442           0 : }
     443             : /* }}} */
     444             : 
     445             : /* {{{ proto bool UConverter::setDestinationEncoding(string encoding) */
     446           0 : static PHP_METHOD(UConverter, setDestinationEncoding) {
     447           0 :         php_converter_object *objval = CONV_GET(getThis());
     448           0 :         php_converter_do_set_encoding(objval->dest, INTERNAL_FUNCTION_PARAM_PASSTHRU);
     449           0 : }
     450             : /* }}} */
     451             : 
     452             : /* {{{ php_converter_do_get_encoding */
     453             : ZEND_BEGIN_ARG_INFO_EX(php_converter_get_encoding_arginfo, 0, ZEND_RETURN_VALUE, 0)
     454             : ZEND_END_ARG_INFO();
     455           0 : static void php_converter_do_get_encoding(php_converter_object *objval, UConverter *cnv, INTERNAL_FUNCTION_PARAMETERS) {
     456             :         const char *name;
     457             : 
     458           0 :         if (zend_parse_parameters_none() == FAILURE) {
     459           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "Expected no arguments", 0 TSRMLS_CC);
     460           0 :                 RETURN_FALSE;
     461             :         }
     462             : 
     463           0 :         intl_errors_reset(&objval->error TSRMLS_CC);
     464             : 
     465           0 :         if (!cnv) {
     466           0 :                 RETURN_NULL();
     467             :         }
     468             : 
     469           0 :         name = ucnv_getName(cnv, &objval->error.code);
     470           0 :         if (U_FAILURE(objval->error.code)) {
     471           0 :                 THROW_UFAILURE(objval, "ucnv_getName()", objval->error.code);
     472           0 :                 RETURN_FALSE;
     473             :         }
     474             : 
     475           0 :         RETURN_STRING(name);
     476             : }
     477             : /* }}} */
     478             : 
     479             : /* {{{ proto string UConverter::getSourceEncoding() */
     480           0 : static PHP_METHOD(UConverter, getSourceEncoding) {
     481           0 :         php_converter_object *objval = CONV_GET(getThis());
     482           0 :         php_converter_do_get_encoding(objval, objval->src, INTERNAL_FUNCTION_PARAM_PASSTHRU);
     483           0 : }
     484             : /* }}} */
     485             : 
     486             : /* {{{ proto string UConverter::getDestinationEncoding() */
     487           0 : static PHP_METHOD(UConverter, getDestinationEncoding) {
     488           0 :         php_converter_object *objval = CONV_GET(getThis());
     489           0 :         php_converter_do_get_encoding(objval, objval->dest, INTERNAL_FUNCTION_PARAM_PASSTHRU);
     490           0 : }
     491             : /* }}} */
     492             : 
     493             : /* {{{ php_converter_do_get_type */
     494             : ZEND_BEGIN_ARG_INFO_EX(php_converter_get_type_arginfo, 0, ZEND_RETURN_VALUE, 0)
     495             : ZEND_END_ARG_INFO();
     496           4 : static void php_converter_do_get_type(php_converter_object *objval, UConverter *cnv, INTERNAL_FUNCTION_PARAMETERS) {
     497             :         UConverterType t;
     498             : 
     499           4 :         if (zend_parse_parameters_none() == FAILURE) {
     500           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "Expected no arguments", 0 TSRMLS_CC);
     501           0 :                 RETURN_FALSE;
     502             :         }
     503           4 :         intl_errors_reset(&objval->error TSRMLS_CC);
     504             : 
     505           4 :         if (!cnv) {
     506           0 :                 RETURN_NULL();
     507             :         }
     508             : 
     509           4 :         t = ucnv_getType(cnv);
     510           4 :         if (U_FAILURE(objval->error.code)) {
     511           0 :                 THROW_UFAILURE(objval, "ucnv_getType", objval->error.code);
     512           0 :                 RETURN_FALSE;
     513             :         }
     514             : 
     515           4 :         RETURN_LONG(t);
     516             : }
     517             : /* }}} */
     518             : 
     519             : /* {{{ proto long UConverter::getSourceType() */
     520           2 : static PHP_METHOD(UConverter, getSourceType) {
     521           2 :         php_converter_object *objval = CONV_GET(getThis());
     522           2 :         php_converter_do_get_type(objval, objval->src, INTERNAL_FUNCTION_PARAM_PASSTHRU);
     523           2 : }
     524             : /* }}} */
     525             : 
     526             : /* {{{ proto long UConverter::getDestinationType() */
     527           2 : static PHP_METHOD(UConverter, getDestinationType) {
     528           2 :         php_converter_object *objval = CONV_GET(getThis());
     529           2 :         php_converter_do_get_type(objval, objval->dest, INTERNAL_FUNCTION_PARAM_PASSTHRU);
     530           2 : }
     531             : /* }}} */
     532             : 
     533             : /* {{{ php_converter_resolve_callback */
     534          18 : static void php_converter_resolve_callback(zval *zobj,
     535             :                                            php_converter_object *objval,
     536             :                                            const char *callback_name,
     537             :                                            zend_fcall_info *finfo,
     538             :                                            zend_fcall_info_cache *fcache TSRMLS_DC) {
     539          18 :         char *errstr = NULL;
     540             :         zval caller;
     541             : 
     542          18 :         array_init(&caller);
     543             :         Z_ADDREF_P(zobj);
     544          18 :         add_index_zval(&caller, 0, zobj);
     545          18 :         add_index_string(&caller, 1, callback_name);
     546          18 :         if (zend_fcall_info_init(&caller, 0, finfo, fcache, NULL, &errstr TSRMLS_CC) == FAILURE) {
     547           0 :                 php_converter_throw_failure(objval, U_INTERNAL_PROGRAM_ERROR TSRMLS_CC, "Error setting converter callback: %s", errstr);
     548             :         }
     549             :         zval_dtor(&caller);
     550          18 :         if (errstr) {
     551           0 :                 efree(errstr);
     552             :         }
     553          18 : }
     554             : /* }}} */
     555             : 
     556             : /* {{{ proto void UConverter::__construct([string dest = 'utf-8',[string src = 'utf-8']]) */
     557             : ZEND_BEGIN_ARG_INFO_EX(php_converter_arginfo, 0, ZEND_RETURN_VALUE, 0)
     558             :         ZEND_ARG_INFO(0, destination_encoding)
     559             :         ZEND_ARG_INFO(0, source_encoding)
     560             : ZEND_END_ARG_INFO();
     561             : 
     562           9 : static PHP_METHOD(UConverter, __construct) {
     563           9 :         php_converter_object *objval = CONV_GET(getThis());
     564           9 :         char *src = "utf-8";
     565           9 :         size_t src_len = sizeof("utf-8") - 1;
     566           9 :         char *dest = src;
     567           9 :         size_t dest_len = src_len;
     568             : 
     569           9 :         intl_error_reset(NULL TSRMLS_CC);
     570             : 
     571           9 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s!",
     572             :                                   &dest, &dest_len, &src, &src_len) == FAILURE) {
     573           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     574             :                         "UConverter::__construct(): bad arguments", 0 TSRMLS_CC);
     575           0 :                 return;
     576             :         }
     577             : 
     578           9 :         php_converter_set_encoding(objval, &(objval->src),  src,  src_len  TSRMLS_CC);
     579           9 :         php_converter_set_encoding(objval, &(objval->dest), dest, dest_len TSRMLS_CC);
     580           9 :         php_converter_resolve_callback(getThis(), objval, "toUCallback",   &(objval->to_cb),   &(objval->to_cache) TSRMLS_CC);
     581           9 :         php_converter_resolve_callback(getThis(), objval, "fromUCallback", &(objval->from_cb), &(objval->from_cache) TSRMLS_CC);
     582             : }
     583             : /* }}} */
     584             : 
     585             : /* {{{ proto bool UConverter::setSubstChars(string $chars) */
     586             : ZEND_BEGIN_ARG_INFO_EX(php_converter_setSubstChars_arginfo, 0, ZEND_RETURN_VALUE, 1)
     587             :         ZEND_ARG_INFO(0, chars)
     588             : ZEND_END_ARG_INFO();
     589             : 
     590           3 : static PHP_METHOD(UConverter, setSubstChars) {
     591           3 :         php_converter_object *objval = CONV_GET(getThis());
     592             :         char *chars;
     593             :         size_t chars_len;
     594           3 :         int ret = 1;
     595             : 
     596           3 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &chars, &chars_len) == FAILURE) {
     597           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     598             :                         "UConverter::setSubstChars(): bad arguments", 0 TSRMLS_CC);
     599           0 :                 RETURN_FALSE;
     600             :         }
     601           3 :         intl_errors_reset(&objval->error TSRMLS_CC);
     602             : 
     603           3 :         if (objval->src) {
     604           3 :                 UErrorCode error = U_ZERO_ERROR;
     605           3 :                 ucnv_setSubstChars(objval->src, chars, chars_len, &error);
     606           3 :                 if (U_FAILURE(error)) {
     607           2 :                         THROW_UFAILURE(objval, "ucnv_setSubstChars", error);
     608           2 :                         ret = 0;
     609             :                 }
     610             :         } else {
     611           0 :                 php_converter_throw_failure(objval, U_INVALID_STATE_ERROR TSRMLS_CC, "Source Converter has not been initialized yet");
     612           0 :                 ret = 0;
     613             :         }
     614             : 
     615           3 :         if (objval->dest) {
     616           3 :                 UErrorCode error = U_ZERO_ERROR;
     617           3 :                 ucnv_setSubstChars(objval->dest, chars, chars_len, &error);
     618           3 :                 if (U_FAILURE(error)) {
     619           2 :                         THROW_UFAILURE(objval, "ucnv_setSubstChars", error);
     620           2 :                         ret = 0;
     621             :                 }
     622             :         } else {
     623           0 :                 php_converter_throw_failure(objval, U_INVALID_STATE_ERROR TSRMLS_CC, "Destination Converter has not been initialized yet");
     624           0 :                 ret = 0;
     625             :         }
     626             : 
     627           3 :         RETURN_BOOL(ret);
     628             : }
     629             : /* }}} */
     630             : 
     631             : /* {{{ proto string UConverter::getSubstChars() */
     632             : ZEND_BEGIN_ARG_INFO_EX(php_converter_getSubstChars_arginfo, 0, ZEND_RETURN_VALUE, 0)
     633             : ZEND_END_ARG_INFO();
     634             : 
     635           0 : static PHP_METHOD(UConverter, getSubstChars) {
     636           0 :         php_converter_object *objval = CONV_GET(getThis());
     637             :         char chars[127];
     638           0 :         int8_t chars_len = sizeof(chars);
     639           0 :         UErrorCode error = U_ZERO_ERROR;
     640             : 
     641           0 :         if (zend_parse_parameters_none() == FAILURE) {
     642           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     643             :                         "UConverter::getSubstChars(): expected no arguments", 0 TSRMLS_CC);
     644           0 :                 RETURN_FALSE;
     645             :         }
     646           0 :         intl_errors_reset(&objval->error TSRMLS_CC);
     647             : 
     648           0 :         if (!objval->src) {
     649           0 :                 RETURN_NULL();
     650             :         }
     651             : 
     652             :         /* src and dest get the same subst chars set,
     653             :          * so it doesn't really matter which one we read from
     654             :          */
     655           0 :         ucnv_getSubstChars(objval->src, chars, &chars_len, &error);
     656           0 :         if (U_FAILURE(error)) {
     657           0 :                 THROW_UFAILURE(objval, "ucnv_getSubstChars", error);
     658           0 :                 RETURN_FALSE;
     659             :         }
     660             : 
     661           0 :         RETURN_STRINGL(chars, chars_len);
     662             : }
     663             : /* }}} */
     664             : 
     665             : /* {{{ php_converter_do_convert */
     666          18 : static zend_bool php_converter_do_convert(UConverter *dest_cnv, char **pdest, int32_t *pdest_len,
     667             :                                           UConverter *src_cnv,  const char *src, int32_t src_len,
     668             :                                           php_converter_object *objval
     669             :                                           TSRMLS_DC) {
     670          18 :         UErrorCode      error = U_ZERO_ERROR;
     671             :         int32_t         dest_len,
     672             :                                 temp_len;
     673             :         char            *dest;
     674             :         UChar           *temp;
     675             : 
     676          18 :         if (!src_cnv || !dest_cnv) {
     677           0 :                 php_converter_throw_failure(objval, U_INVALID_STATE_ERROR TSRMLS_CC,
     678             :                                             "Internal converters not initialized");
     679           0 :                 return 0;
     680             :         }
     681             : 
     682             :         /* Get necessary buffer size first */
     683          18 :         temp_len = 1 + ucnv_toUChars(src_cnv, NULL, 0, src, src_len, &error);
     684          18 :         if (U_FAILURE(error) && error != U_BUFFER_OVERFLOW_ERROR) {
     685           0 :                 THROW_UFAILURE(objval, "ucnv_toUChars", error);
     686           0 :                 return 0;
     687             :         }
     688          18 :         temp = safe_emalloc(sizeof(UChar), temp_len, sizeof(UChar));
     689             : 
     690             :         /* Convert to intermediate UChar* array */
     691          18 :         error = U_ZERO_ERROR;
     692          18 :         temp_len = ucnv_toUChars(src_cnv, temp, temp_len, src, src_len, &error);
     693          18 :         if (U_FAILURE(error)) {
     694           0 :                 THROW_UFAILURE(objval, "ucnv_toUChars", error);
     695           0 :                 efree(temp);
     696           0 :                 return 0;
     697             :         }
     698          18 :         temp[temp_len] = 0;
     699             : 
     700             :         /* Get necessary output buffer size */
     701          18 :         dest_len = 1 + ucnv_fromUChars(dest_cnv, NULL, 0, temp, temp_len, &error);
     702          18 :         if (U_FAILURE(error) && error != U_BUFFER_OVERFLOW_ERROR) {
     703           0 :                 THROW_UFAILURE(objval, "ucnv_fromUChars", error);
     704           0 :                 efree(temp);
     705           0 :                 return 0;
     706             :         }
     707             : 
     708          18 :         dest = safe_emalloc(sizeof(char), dest_len, sizeof(char));
     709             : 
     710             :         /* Convert to final encoding */
     711          18 :         error = U_ZERO_ERROR;
     712          18 :         dest_len = ucnv_fromUChars(dest_cnv, dest, dest_len, temp, temp_len, &error);
     713          18 :         efree(temp);
     714          18 :         if (U_FAILURE(error)) {
     715           0 :                 THROW_UFAILURE(objval, "ucnv_fromUChars", error);
     716           0 :                 efree(dest);
     717           0 :                 return 0;
     718             :         }
     719             : 
     720          18 :         *pdest = dest;
     721          18 :         if (pdest_len) {
     722          18 :                 *pdest_len = dest_len;
     723             :         }
     724             : 
     725          18 :         return 1;
     726             : }
     727             : /* }}} */
     728             : 
     729             : /* {{{ proto string UConverter::reasonText(long reason) */
     730             : #define UCNV_REASON_CASE(v) case (UCNV_ ## v) : RETURN_STRINGL( "REASON_" #v , sizeof( "REASON_" #v ) - 1);
     731             : ZEND_BEGIN_ARG_INFO_EX(php_converter_reasontext_arginfo, 0, ZEND_RETURN_VALUE, 0)
     732             :         ZEND_ARG_INFO(0, reason)
     733             : ZEND_END_ARG_INFO();
     734          22 : static PHP_METHOD(UConverter, reasonText) {
     735             :         zend_long reason;
     736             : 
     737          22 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &reason) == FAILURE) {
     738           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     739             :                         "UConverter::reasonText(): bad arguments", 0 TSRMLS_CC);
     740           0 :                 RETURN_FALSE;
     741             :         }
     742          22 :         intl_error_reset(NULL TSRMLS_CC);
     743             : 
     744          22 :         switch (reason) {
     745           8 :                 UCNV_REASON_CASE(UNASSIGNED)
     746           4 :                 UCNV_REASON_CASE(ILLEGAL)
     747           0 :                 UCNV_REASON_CASE(IRREGULAR)
     748          24 :                 UCNV_REASON_CASE(RESET)
     749           8 :                 UCNV_REASON_CASE(CLOSE)
     750           0 :                 UCNV_REASON_CASE(CLONE)
     751             :                 default:
     752           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown UConverterCallbackReason: %pd", reason);
     753           0 :                         RETURN_FALSE;
     754             :         }
     755             : }
     756             : /* }}} */
     757             : 
     758             : /* {{{ proto string UConverter::convert(string str[, bool reverse]) */
     759             : ZEND_BEGIN_ARG_INFO_EX(php_converter_convert_arginfo, 0, ZEND_RETURN_VALUE, 1)
     760             :         ZEND_ARG_INFO(0, str)
     761             :         ZEND_ARG_INFO(0, reverse)
     762             : ZEND_END_ARG_INFO();
     763             : 
     764          12 : static PHP_METHOD(UConverter, convert) {
     765          12 :         php_converter_object *objval = CONV_GET(getThis());
     766             :         char *str, *dest;
     767             :         size_t str_len;
     768             :         int32_t dest_len;
     769          12 :         zend_bool reverse = 0;
     770             : 
     771          12 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b",
     772             :                                   &str, &str_len, &reverse) == FAILURE) {
     773           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     774             :                         "UConverter::convert(): bad arguments", 0 TSRMLS_CC);
     775           0 :                 RETURN_FALSE;
     776             :         }
     777          12 :         intl_errors_reset(&objval->error TSRMLS_CC);
     778             : 
     779          24 :         if (php_converter_do_convert(reverse ? objval->src : objval->dest,
     780             :                                      &dest, &dest_len,
     781          12 :                                  reverse ? objval->dest : objval->src,
     782             :                                      str,   str_len,
     783             :                                      objval TSRMLS_CC)) {
     784          24 :                 RETVAL_STRINGL(dest, dest_len);
     785             :                 //???
     786          12 :                 efree(dest);
     787          12 :                 return;
     788             :         } else {
     789           0 :                 RETURN_FALSE;
     790             :         }
     791             : }
     792             : /* }}} */
     793             : 
     794             : /* {{{ proto string UConverter::transcode(string $str, string $toEncoding, string $fromEncoding[, Array $options = array()]) */
     795             : ZEND_BEGIN_ARG_INFO_EX(php_converter_transcode_arginfo, 0, ZEND_RETURN_VALUE, 3)
     796             :         ZEND_ARG_INFO(0, str)
     797             :         ZEND_ARG_INFO(0, toEncoding)
     798             :         ZEND_ARG_INFO(0, fromEncoding)
     799             :         ZEND_ARG_ARRAY_INFO(0, options, 1)
     800             : ZEND_END_ARG_INFO();
     801             : 
     802          10 : static PHP_METHOD(UConverter, transcode) {
     803             :         char *str, *src, *dest;
     804             :         size_t str_len, src_len, dest_len;
     805          10 :         zval *options = NULL;
     806          10 :         UConverter *src_cnv = NULL, *dest_cnv = NULL;
     807             : 
     808          10 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|a!",
     809             :                         &str, &str_len, &dest, &dest_len, &src, &src_len, &options) == FAILURE) {
     810           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     811             :                         "UConverter::transcode(): bad arguments", 0 TSRMLS_CC);
     812           0 :                 RETURN_FALSE;
     813             :         }
     814          10 :         intl_error_reset(NULL TSRMLS_CC);
     815             : 
     816          24 :         if (php_converter_set_encoding(NULL, &src_cnv,  src,  src_len TSRMLS_CC) &&
     817          10 :             php_converter_set_encoding(NULL, &dest_cnv, dest, dest_len TSRMLS_CC)) {
     818          10 :                 char *out = NULL;
     819          10 :                 int out_len = 0;
     820          10 :                 UErrorCode error = U_ZERO_ERROR;
     821             : 
     822          10 :                 if (options && zend_hash_num_elements(Z_ARRVAL_P(options))) {
     823             :                         zval *tmpzval;
     824             : 
     825          12 :                         if (U_SUCCESS(error) &&
     826           6 :                                 (tmpzval = zend_hash_str_find(Z_ARRVAL_P(options), "from_subst", sizeof("from_subst") - 1)) != NULL &&
     827             :                                 Z_TYPE_P(tmpzval) == IS_STRING) {
     828           0 :                                 error = U_ZERO_ERROR;
     829           0 :                                 ucnv_setSubstChars(src_cnv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval) & 0x7F, &error);
     830             :                         }
     831          18 :                         if (U_SUCCESS(error) &&
     832           6 :                                 (tmpzval = zend_hash_str_find(Z_ARRVAL_P(options), "to_subst", sizeof("to_subst") - 1)) != NULL &&
     833             :                                 Z_TYPE_P(tmpzval) == IS_STRING) {
     834           6 :                                 error = U_ZERO_ERROR;
     835           6 :                                 ucnv_setSubstChars(dest_cnv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval) & 0x7F, &error);
     836             :                         }
     837             :                 }
     838             : 
     839          16 :                 if (U_SUCCESS(error) &&
     840           6 :                         php_converter_do_convert(dest_cnv, &out, &out_len, src_cnv, str, str_len, NULL TSRMLS_CC)) {
     841          12 :                         RETVAL_STRINGL(out, out_len);
     842             :                         //???
     843           6 :                         efree(out);
     844           6 :                         return;
     845             :                 }
     846             : 
     847           4 :                 if (U_FAILURE(error)) {
     848           4 :                         THROW_UFAILURE(NULL, "transcode", error);
     849           4 :                         RETVAL_FALSE;
     850             :                 }
     851             :         } else {
     852           0 :                 RETVAL_FALSE;
     853             :         }
     854             :         
     855           4 :         if (src_cnv) {
     856           4 :                 ucnv_close(src_cnv);
     857             :         }
     858           4 :         if (dest_cnv) {
     859           4 :                 ucnv_close(dest_cnv);
     860             :         }
     861             : }
     862             : /* }}} */
     863             : 
     864             : /* {{{ proto int UConverter::getErrorCode() */
     865             : ZEND_BEGIN_ARG_INFO_EX(php_converter_geterrorcode_arginfo, 0, ZEND_RETURN_VALUE, 0)
     866             : ZEND_END_ARG_INFO();
     867           1 : static PHP_METHOD(UConverter, getErrorCode) {
     868           1 :         php_converter_object *objval = CONV_GET(getThis());
     869             : 
     870           1 :         if (zend_parse_parameters_none() == FAILURE) {
     871           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     872             :                         "UConverter::getErrorCode(): expected no arguments", 0 TSRMLS_CC);
     873           0 :                 RETURN_FALSE;
     874             :         }
     875             : 
     876           1 :         RETURN_LONG(intl_error_get_code(&(objval->error) TSRMLS_CC));    
     877             : }
     878             : /* }}} */
     879             : 
     880             : /* {{{ proto string UConverter::getErrorMessage() */
     881             : ZEND_BEGIN_ARG_INFO_EX(php_converter_geterrormsg_arginfo, 0, ZEND_RETURN_VALUE, 0)
     882             : ZEND_END_ARG_INFO();
     883           0 : static PHP_METHOD(UConverter, getErrorMessage) {
     884           0 :         php_converter_object *objval = CONV_GET(getThis());
     885           0 :         zend_string *message = intl_error_get_message(&(objval->error) TSRMLS_CC);
     886             : 
     887           0 :         if (zend_parse_parameters_none() == FAILURE) {
     888           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     889             :                         "UConverter::getErrorMessage(): expected no arguments", 0 TSRMLS_CC);
     890           0 :                 RETURN_FALSE;
     891             :         }
     892             : 
     893           0 :         if (message) {
     894           0 :                 RETURN_STR(message);
     895             :         } else {
     896           0 :                 RETURN_NULL();
     897             :         }
     898             : }
     899             : /* }}} */
     900             : 
     901             : /* {{{ proto array UConverter::getAvailable() */
     902             : ZEND_BEGIN_ARG_INFO_EX(php_converter_getavailable_arginfo, 0, ZEND_RETURN_VALUE, 0)
     903             : ZEND_END_ARG_INFO();
     904           1 : static PHP_METHOD(UConverter, getAvailable) {
     905             :         int32_t i,
     906           1 :                         count = ucnv_countAvailable();
     907             : 
     908           1 :         if (zend_parse_parameters_none() == FAILURE) {
     909           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     910             :                         "UConverter::getErrorMessage(): expected no arguments", 0 TSRMLS_CC);
     911           0 :                 RETURN_FALSE;
     912             :         }
     913           1 :         intl_error_reset(NULL TSRMLS_CC);
     914             : 
     915           1 :         array_init(return_value);
     916         226 :         for(i = 0; i < count; i++) {
     917         225 :                 const char *name = ucnv_getAvailableName(i);
     918         225 :                 add_next_index_string(return_value, name);
     919             :         }
     920             : }
     921             : /* }}} */
     922             : 
     923             : /* {{{ proto array UConverter::getAliases(string name) */
     924             : ZEND_BEGIN_ARG_INFO_EX(php_converter_getaliases_arginfo, 0, ZEND_RETURN_VALUE, 0)
     925             :         ZEND_ARG_INFO(0, name)
     926             : ZEND_END_ARG_INFO();
     927           1 : static PHP_METHOD(UConverter, getAliases) {
     928             :         char *name;
     929             :         size_t name_len;
     930           1 :         UErrorCode error = U_ZERO_ERROR;
     931             :         uint16_t i, count;
     932             : 
     933           1 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
     934           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     935             :                         "UConverter::getAliases(): bad arguments", 0 TSRMLS_CC);
     936           0 :                 RETURN_FALSE;
     937             :         }
     938           1 :         intl_error_reset(NULL TSRMLS_CC);
     939             : 
     940           1 :         count = ucnv_countAliases(name, &error);
     941           1 :         if (U_FAILURE(error)) {
     942           0 :                 THROW_UFAILURE(NULL, "ucnv_countAliases", error);
     943           0 :                 RETURN_FALSE;
     944             :         }
     945             : 
     946           1 :         array_init(return_value);
     947          12 :         for(i = 0; i < count; i++) {
     948             :                 const char *alias;
     949             : 
     950          11 :                 error = U_ZERO_ERROR;
     951          11 :                 alias = ucnv_getAlias(name, i, &error);
     952          11 :                 if (U_FAILURE(error)) {
     953           0 :                         THROW_UFAILURE(NULL, "ucnv_getAlias", error);
     954             :                         zval_dtor(return_value);
     955           0 :                         RETURN_NULL();
     956             :                 }
     957          11 :                 add_next_index_string(return_value, alias);
     958             :         }
     959             : }
     960             : /* }}} */
     961             : 
     962             : /* {{{ proto array UConverter::getStandards() */
     963             : ZEND_BEGIN_ARG_INFO_EX(php_converter_getstandards_arginfo, 0, ZEND_RETURN_VALUE, 0)
     964             : ZEND_END_ARG_INFO();
     965           0 : static PHP_METHOD(UConverter, getStandards) {
     966             :         uint16_t i, count;
     967             : 
     968           0 :         if (zend_parse_parameters_none() == FAILURE) {
     969           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     970             :                         "UConverter::getStandards(): expected no arguments", 0 TSRMLS_CC);
     971           0 :                 RETURN_FALSE;
     972             :         }
     973           0 :         intl_error_reset(NULL TSRMLS_CC);
     974             : 
     975           0 :         array_init(return_value);
     976           0 :         count = ucnv_countStandards();
     977           0 :         for(i = 0; i < count; i++) {
     978           0 :                 UErrorCode error = U_ZERO_ERROR;
     979           0 :                 const char *name = ucnv_getStandard(i, &error);
     980           0 :                 if (U_FAILURE(error)) {
     981           0 :                         THROW_UFAILURE(NULL, "ucnv_getStandard", error);
     982             :                         zval_dtor(return_value);
     983           0 :                         RETURN_NULL();
     984             :                 }
     985           0 :                 add_next_index_string(return_value, name);
     986             :         }
     987             : }
     988             : /* }}} */
     989             : 
     990             : static zend_function_entry php_converter_methods[] = {
     991             :         PHP_ME(UConverter, __construct,            php_converter_arginfo,                   ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
     992             : 
     993             :         /* Encoding selection */
     994             :         PHP_ME(UConverter, setSourceEncoding,      php_converter_set_encoding_arginfo,      ZEND_ACC_PUBLIC)
     995             :         PHP_ME(UConverter, setDestinationEncoding, php_converter_set_encoding_arginfo,      ZEND_ACC_PUBLIC)
     996             :         PHP_ME(UConverter, getSourceEncoding,      php_converter_get_encoding_arginfo,      ZEND_ACC_PUBLIC)
     997             :         PHP_ME(UConverter, getDestinationEncoding, php_converter_get_encoding_arginfo,      ZEND_ACC_PUBLIC)
     998             : 
     999             :         /* Introspection for algorithmic converters */
    1000             :         PHP_ME(UConverter, getSourceType,          php_converter_get_type_arginfo,          ZEND_ACC_PUBLIC)
    1001             :         PHP_ME(UConverter, getDestinationType,     php_converter_get_type_arginfo,          ZEND_ACC_PUBLIC)
    1002             : 
    1003             :         /* Basic codeunit error handling */
    1004             :         PHP_ME(UConverter, getSubstChars,          php_converter_getSubstChars_arginfo,     ZEND_ACC_PUBLIC)
    1005             :         PHP_ME(UConverter, setSubstChars,          php_converter_setSubstChars_arginfo,     ZEND_ACC_PUBLIC)
    1006             : 
    1007             :         /* Default callback handlers */
    1008             :         PHP_ME(UConverter, toUCallback,            php_converter_toUCallback_arginfo,       ZEND_ACC_PUBLIC)
    1009             :         PHP_ME(UConverter, fromUCallback,          php_converter_fromUCallback_arginfo,     ZEND_ACC_PUBLIC)
    1010             : 
    1011             :         /* Core conversion workhorses */
    1012             :         PHP_ME(UConverter, convert,                php_converter_convert_arginfo,           ZEND_ACC_PUBLIC)
    1013             :         PHP_ME(UConverter, transcode,              php_converter_transcode_arginfo,         ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    1014             : 
    1015             :         /* Error inspection */
    1016             :         PHP_ME(UConverter, getErrorCode,           php_converter_geterrorcode_arginfo,      ZEND_ACC_PUBLIC)
    1017             :         PHP_ME(UConverter, getErrorMessage,        php_converter_geterrormsg_arginfo,       ZEND_ACC_PUBLIC)
    1018             : 
    1019             :         /* Ennumeration and lookup */
    1020             :         PHP_ME(UConverter, reasonText,             php_converter_reasontext_arginfo,        ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    1021             :         PHP_ME(UConverter, getAvailable,           php_converter_getavailable_arginfo,      ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    1022             :         PHP_ME(UConverter, getAliases,             php_converter_getaliases_arginfo,        ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    1023             :         PHP_ME(UConverter, getStandards,           php_converter_getstandards_arginfo,      ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    1024             :         { NULL, NULL, NULL }
    1025             : };
    1026             : 
    1027             : /* {{{ Converter create/clone/destroy */
    1028           9 : static void php_converter_dtor_object(zend_object *obj TSRMLS_DC) {
    1029           9 :         php_converter_object *objval = php_converter_fetch_object(obj);
    1030             : 
    1031           9 :         if (objval->src) {
    1032           7 :                 ucnv_close(objval->src);
    1033             :         }
    1034             : 
    1035           9 :         if (objval->dest) {
    1036           8 :                 ucnv_close(objval->dest);
    1037             :         }
    1038             : 
    1039           9 :         intl_error_reset(&(objval->error) TSRMLS_CC);
    1040           9 : }
    1041             : 
    1042           9 : static zend_object *php_converter_object_ctor(zend_class_entry *ce, php_converter_object **pobjval TSRMLS_DC) {
    1043             :         php_converter_object *objval;
    1044             : 
    1045           9 :         objval = ecalloc(1, sizeof(php_converter_object) + sizeof(zval) * (ce->default_properties_count - 1));
    1046             : 
    1047           9 :         zend_object_std_init(&objval->obj, ce TSRMLS_CC );
    1048             : #ifdef ZTS
    1049             :         objval->tsrm_ls = TSRMLS_C;
    1050             : #endif
    1051           9 :         intl_error_init(&(objval->error) TSRMLS_CC);
    1052             : 
    1053           9 :         objval->obj.handlers = &php_converter_object_handlers;
    1054           9 :         *pobjval = objval;
    1055             : 
    1056           9 :         return &objval->obj;
    1057             : }
    1058             : 
    1059           9 : static zend_object *php_converter_create_object(zend_class_entry *ce TSRMLS_DC) {
    1060           9 :         php_converter_object *objval = NULL;
    1061           9 :         zend_object *retval = php_converter_object_ctor(ce, &objval TSRMLS_CC);
    1062             : 
    1063           9 :         object_properties_init(&(objval->obj), ce);
    1064             : 
    1065           9 :         return retval;
    1066             : }
    1067             : 
    1068           0 : static zend_object *php_converter_clone_object(zval *object TSRMLS_DC) {
    1069           0 :         php_converter_object *objval, *oldobj = Z_INTL_CONVERTER_P(object);
    1070           0 :         zend_object *retval = php_converter_object_ctor(Z_OBJCE_P(object), &objval TSRMLS_CC);
    1071           0 :         UErrorCode error = U_ZERO_ERROR;
    1072             : 
    1073           0 :         intl_errors_reset(&oldobj->error TSRMLS_CC);
    1074             : 
    1075           0 :         objval->src = ucnv_safeClone(oldobj->src, NULL, NULL, &error);
    1076           0 :         if (U_SUCCESS(error)) {
    1077           0 :                 error = U_ZERO_ERROR;
    1078           0 :                 objval->dest = ucnv_safeClone(oldobj->dest, NULL, NULL, &error);
    1079             :         }
    1080           0 :         if (U_FAILURE(error)) {
    1081             :                 zend_string *err_msg;
    1082           0 :                 THROW_UFAILURE(oldobj, "ucnv_safeClone", error);
    1083             : 
    1084           0 :                 err_msg = intl_error_get_message(&oldobj->error TSRMLS_CC);
    1085           0 :                 zend_throw_exception(NULL, err_msg->val, 0 TSRMLS_CC);
    1086             :                 zend_string_release(err_msg);
    1087             : 
    1088           0 :                 return retval;
    1089             :         }
    1090             : 
    1091             :         /* Update contexts for converter error handlers */
    1092           0 :         php_converter_set_callbacks(objval, objval->src  TSRMLS_CC);
    1093           0 :         php_converter_set_callbacks(objval, objval->dest TSRMLS_CC);
    1094             : 
    1095           0 :         zend_objects_clone_members(&(objval->obj), &(oldobj->obj) TSRMLS_CC);
    1096             : 
    1097             :         /* Newly cloned object deliberately does not inherit error state from original object */
    1098             : 
    1099           0 :         return retval;
    1100             : }
    1101             : /* }}} */
    1102             : 
    1103             : #define CONV_REASON_CONST(v) zend_declare_class_constant_long(php_converter_ce, "REASON_" #v, sizeof("REASON_" #v) - 1, UCNV_ ## v TSRMLS_CC)
    1104             : #define CONV_TYPE_CONST(v)   zend_declare_class_constant_long(php_converter_ce, #v ,          sizeof(#v) - 1,           UCNV_ ## v TSRMLS_CC)
    1105             : 
    1106             : /* {{{ php_converter_minit */
    1107       20423 : int php_converter_minit(INIT_FUNC_ARGS) {
    1108             :         zend_class_entry ce;
    1109             : 
    1110       20423 :         INIT_CLASS_ENTRY(ce, "UConverter", php_converter_methods);
    1111       20423 :         php_converter_ce = zend_register_internal_class(&ce TSRMLS_CC);
    1112       20423 :         php_converter_ce->create_object = php_converter_create_object;
    1113       20423 :         memcpy(&php_converter_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
    1114       20423 :         php_converter_object_handlers.offset = XtOffsetOf(php_converter_object, obj);
    1115       20423 :         php_converter_object_handlers.clone_obj = php_converter_clone_object;
    1116       20423 :         php_converter_object_handlers.dtor_obj = php_converter_dtor_object;
    1117             : 
    1118             :         /* enum UConverterCallbackReason */
    1119       20423 :         CONV_REASON_CONST(UNASSIGNED);
    1120       20423 :         CONV_REASON_CONST(ILLEGAL);
    1121       20423 :         CONV_REASON_CONST(IRREGULAR);
    1122       20423 :         CONV_REASON_CONST(RESET);
    1123       20423 :         CONV_REASON_CONST(CLOSE);
    1124       20423 :         CONV_REASON_CONST(CLONE);
    1125             : 
    1126             :         /* enum UConverterType */
    1127       20423 :         CONV_TYPE_CONST(UNSUPPORTED_CONVERTER);
    1128       20423 :         CONV_TYPE_CONST(SBCS);
    1129       20423 :         CONV_TYPE_CONST(DBCS);
    1130       20423 :         CONV_TYPE_CONST(MBCS);
    1131       20423 :         CONV_TYPE_CONST(LATIN_1);
    1132       20423 :         CONV_TYPE_CONST(UTF8);
    1133       20423 :         CONV_TYPE_CONST(UTF16_BigEndian);
    1134       20423 :         CONV_TYPE_CONST(UTF16_LittleEndian);
    1135       20423 :         CONV_TYPE_CONST(UTF32_BigEndian);
    1136       20423 :         CONV_TYPE_CONST(UTF32_LittleEndian);
    1137       20423 :         CONV_TYPE_CONST(EBCDIC_STATEFUL);
    1138       20423 :         CONV_TYPE_CONST(ISO_2022);
    1139       20423 :         CONV_TYPE_CONST(LMBCS_1);
    1140       20423 :         CONV_TYPE_CONST(LMBCS_2);
    1141       20423 :         CONV_TYPE_CONST(LMBCS_3);
    1142       20423 :         CONV_TYPE_CONST(LMBCS_4);
    1143       20423 :         CONV_TYPE_CONST(LMBCS_5);
    1144       20423 :         CONV_TYPE_CONST(LMBCS_6);
    1145       20423 :         CONV_TYPE_CONST(LMBCS_8);
    1146       20423 :         CONV_TYPE_CONST(LMBCS_11);
    1147       20423 :         CONV_TYPE_CONST(LMBCS_16);
    1148       20423 :         CONV_TYPE_CONST(LMBCS_17);
    1149       20423 :         CONV_TYPE_CONST(LMBCS_18);
    1150       20423 :         CONV_TYPE_CONST(LMBCS_19);
    1151       20423 :         CONV_TYPE_CONST(LMBCS_LAST);
    1152       20423 :         CONV_TYPE_CONST(HZ);
    1153       20423 :         CONV_TYPE_CONST(SCSU);
    1154       20423 :         CONV_TYPE_CONST(ISCII);
    1155       20423 :         CONV_TYPE_CONST(US_ASCII);
    1156       20423 :         CONV_TYPE_CONST(UTF7);
    1157       20423 :         CONV_TYPE_CONST(BOCU1);
    1158       20423 :         CONV_TYPE_CONST(UTF16);
    1159       20423 :         CONV_TYPE_CONST(UTF32);
    1160       20423 :         CONV_TYPE_CONST(CESU8);
    1161       20423 :         CONV_TYPE_CONST(IMAP_MAILBOX);
    1162             : 
    1163       20423 :         return SUCCESS;
    1164             : }
    1165             : /* }}} */
    1166             : 
    1167             : /*
    1168             :  * Local variables:
    1169             :  * tab-width: 4
    1170             :  * c-basic-offset: 4
    1171             :  * End:
    1172             :  * vim600: noet sw=4 ts=4 fdm=marker
    1173             :  * vim<600: noet sw=4 ts=4
    1174             :  */

Generated by: LCOV version 1.10

Generated at Wed, 22 Oct 2014 07:24:50 +0000 (3 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.