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: 370 546 67.8 %
Date: 2014-07-21 Functions: 28 38 73.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 22 Jul 2014 01:33:11 +0000 (8 days ago)

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