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

Generated by: LCOV version 1.10

Generated at Wed, 02 Sep 2015 17:19:11 +0000 (36 hours ago)

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