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

LCOV - code coverage report
Current view: top level - ext/intl/converter - converter.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 356 531 67.0 %
Date: 2015-05-21 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_bool php_converter_do_convert(UConverter *dest_cnv, char **pdest, int32_t *pdest_len,
     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         dest_len,
     661             :                                 temp_len;
     662             :         char            *dest;
     663             :         UChar           *temp;
     664             : 
     665          18 :         if (!src_cnv || !dest_cnv) {
     666           0 :                 php_converter_throw_failure(objval, U_INVALID_STATE_ERROR,
     667             :                                             "Internal converters not initialized");
     668           0 :                 return 0;
     669             :         }
     670             : 
     671             :         /* Get necessary buffer size first */
     672          18 :         temp_len = 1 + ucnv_toUChars(src_cnv, NULL, 0, src, src_len, &error);
     673          18 :         if (U_FAILURE(error) && error != U_BUFFER_OVERFLOW_ERROR) {
     674           0 :                 THROW_UFAILURE(objval, "ucnv_toUChars", error);
     675           0 :                 return 0;
     676             :         }
     677          18 :         temp = safe_emalloc(sizeof(UChar), temp_len, sizeof(UChar));
     678             : 
     679             :         /* Convert to intermediate UChar* array */
     680          18 :         error = U_ZERO_ERROR;
     681          18 :         temp_len = ucnv_toUChars(src_cnv, temp, temp_len, src, src_len, &error);
     682          18 :         if (U_FAILURE(error)) {
     683           0 :                 THROW_UFAILURE(objval, "ucnv_toUChars", error);
     684           0 :                 efree(temp);
     685           0 :                 return 0;
     686             :         }
     687          18 :         temp[temp_len] = 0;
     688             : 
     689             :         /* Get necessary output buffer size */
     690          18 :         dest_len = 1 + ucnv_fromUChars(dest_cnv, NULL, 0, temp, temp_len, &error);
     691          18 :         if (U_FAILURE(error) && error != U_BUFFER_OVERFLOW_ERROR) {
     692           0 :                 THROW_UFAILURE(objval, "ucnv_fromUChars", error);
     693           0 :                 efree(temp);
     694           0 :                 return 0;
     695             :         }
     696             : 
     697          18 :         dest = safe_emalloc(sizeof(char), dest_len, sizeof(char));
     698             : 
     699             :         /* Convert to final encoding */
     700          18 :         error = U_ZERO_ERROR;
     701          18 :         dest_len = ucnv_fromUChars(dest_cnv, dest, dest_len, temp, temp_len, &error);
     702          18 :         efree(temp);
     703          18 :         if (U_FAILURE(error)) {
     704           0 :                 THROW_UFAILURE(objval, "ucnv_fromUChars", error);
     705           0 :                 efree(dest);
     706           0 :                 return 0;
     707             :         }
     708             : 
     709          18 :         *pdest = dest;
     710          18 :         if (pdest_len) {
     711          18 :                 *pdest_len = dest_len;
     712             :         }
     713             : 
     714          18 :         return 1;
     715             : }
     716             : /* }}} */
     717             : 
     718             : /* {{{ proto string UConverter::reasonText(long reason) */
     719             : #define UCNV_REASON_CASE(v) case (UCNV_ ## v) : RETURN_STRINGL( "REASON_" #v , sizeof( "REASON_" #v ) - 1);
     720             : ZEND_BEGIN_ARG_INFO_EX(php_converter_reasontext_arginfo, 0, ZEND_RETURN_VALUE, 0)
     721             :         ZEND_ARG_INFO(0, reason)
     722             : ZEND_END_ARG_INFO();
     723          22 : static PHP_METHOD(UConverter, reasonText) {
     724             :         zend_long reason;
     725             : 
     726          22 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &reason) == FAILURE) {
     727           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     728             :                         "UConverter::reasonText(): bad arguments", 0);
     729           0 :                 RETURN_FALSE;
     730             :         }
     731          22 :         intl_error_reset(NULL);
     732             : 
     733          22 :         switch (reason) {
     734           8 :                 UCNV_REASON_CASE(UNASSIGNED)
     735           4 :                 UCNV_REASON_CASE(ILLEGAL)
     736           0 :                 UCNV_REASON_CASE(IRREGULAR)
     737          24 :                 UCNV_REASON_CASE(RESET)
     738           8 :                 UCNV_REASON_CASE(CLOSE)
     739           0 :                 UCNV_REASON_CASE(CLONE)
     740             :                 default:
     741           0 :                         php_error_docref(NULL, E_WARNING, "Unknown UConverterCallbackReason: %pd", reason);
     742           0 :                         RETURN_FALSE;
     743             :         }
     744             : }
     745             : /* }}} */
     746             : 
     747             : /* {{{ proto string UConverter::convert(string str[, bool reverse]) */
     748             : ZEND_BEGIN_ARG_INFO_EX(php_converter_convert_arginfo, 0, ZEND_RETURN_VALUE, 1)
     749             :         ZEND_ARG_INFO(0, str)
     750             :         ZEND_ARG_INFO(0, reverse)
     751             : ZEND_END_ARG_INFO();
     752             : 
     753          12 : static PHP_METHOD(UConverter, convert) {
     754          12 :         php_converter_object *objval = CONV_GET(getThis());
     755             :         char *str, *dest;
     756             :         size_t str_len;
     757             :         int32_t dest_len;
     758          12 :         zend_bool reverse = 0;
     759             : 
     760          12 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b",
     761             :                                   &str, &str_len, &reverse) == FAILURE) {
     762           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     763             :                         "UConverter::convert(): bad arguments", 0);
     764           0 :                 RETURN_FALSE;
     765             :         }
     766          12 :         intl_errors_reset(&objval->error);
     767             : 
     768          24 :         if (php_converter_do_convert(reverse ? objval->src : objval->dest,
     769             :                                      &dest, &dest_len,
     770          12 :                                  reverse ? objval->dest : objval->src,
     771             :                                      str,   str_len,
     772             :                                      objval)) {
     773          24 :                 RETVAL_STRINGL(dest, dest_len);
     774             :                 //???
     775          12 :                 efree(dest);
     776          12 :                 return;
     777             :         } else {
     778           0 :                 RETURN_FALSE;
     779             :         }
     780             : }
     781             : /* }}} */
     782             : 
     783             : /* {{{ proto string UConverter::transcode(string $str, string $toEncoding, string $fromEncoding[, Array $options = array()]) */
     784             : ZEND_BEGIN_ARG_INFO_EX(php_converter_transcode_arginfo, 0, ZEND_RETURN_VALUE, 3)
     785             :         ZEND_ARG_INFO(0, str)
     786             :         ZEND_ARG_INFO(0, toEncoding)
     787             :         ZEND_ARG_INFO(0, fromEncoding)
     788             :         ZEND_ARG_ARRAY_INFO(0, options, 1)
     789             : ZEND_END_ARG_INFO();
     790             : 
     791          10 : static PHP_METHOD(UConverter, transcode) {
     792             :         char *str, *src, *dest;
     793             :         size_t str_len, src_len, dest_len;
     794          10 :         zval *options = NULL;
     795          10 :         UConverter *src_cnv = NULL, *dest_cnv = NULL;
     796             : 
     797          10 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|a!",
     798             :                         &str, &str_len, &dest, &dest_len, &src, &src_len, &options) == FAILURE) {
     799           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     800             :                         "UConverter::transcode(): bad arguments", 0);
     801           0 :                 RETURN_FALSE;
     802             :         }
     803          10 :         intl_error_reset(NULL);
     804             : 
     805          24 :         if (php_converter_set_encoding(NULL, &src_cnv,  src,  src_len) &&
     806          10 :             php_converter_set_encoding(NULL, &dest_cnv, dest, dest_len)) {
     807          10 :                 char *out = NULL;
     808          10 :                 int out_len = 0;
     809          10 :                 UErrorCode error = U_ZERO_ERROR;
     810             : 
     811          10 :                 if (options && zend_hash_num_elements(Z_ARRVAL_P(options))) {
     812             :                         zval *tmpzval;
     813             : 
     814          12 :                         if (U_SUCCESS(error) &&
     815           6 :                                 (tmpzval = zend_hash_str_find(Z_ARRVAL_P(options), "from_subst", sizeof("from_subst") - 1)) != NULL &&
     816             :                                 Z_TYPE_P(tmpzval) == IS_STRING) {
     817           0 :                                 error = U_ZERO_ERROR;
     818           0 :                                 ucnv_setSubstChars(src_cnv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval) & 0x7F, &error);
     819             :                         }
     820          18 :                         if (U_SUCCESS(error) &&
     821           6 :                                 (tmpzval = zend_hash_str_find(Z_ARRVAL_P(options), "to_subst", sizeof("to_subst") - 1)) != NULL &&
     822             :                                 Z_TYPE_P(tmpzval) == IS_STRING) {
     823           6 :                                 error = U_ZERO_ERROR;
     824           6 :                                 ucnv_setSubstChars(dest_cnv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval) & 0x7F, &error);
     825             :                         }
     826             :                 }
     827             : 
     828          16 :                 if (U_SUCCESS(error) &&
     829           6 :                         php_converter_do_convert(dest_cnv, &out, &out_len, src_cnv, str, str_len, NULL)) {
     830          12 :                         RETVAL_STRINGL(out, out_len);
     831             :                         //???
     832           6 :                         efree(out);
     833           6 :                         return;
     834             :                 }
     835             : 
     836           4 :                 if (U_FAILURE(error)) {
     837           4 :                         THROW_UFAILURE(NULL, "transcode", error);
     838           4 :                         RETVAL_FALSE;
     839             :                 }
     840             :         } else {
     841           0 :                 RETVAL_FALSE;
     842             :         }
     843             : 
     844           4 :         if (src_cnv) {
     845           4 :                 ucnv_close(src_cnv);
     846             :         }
     847           4 :         if (dest_cnv) {
     848           4 :                 ucnv_close(dest_cnv);
     849             :         }
     850             : }
     851             : /* }}} */
     852             : 
     853             : /* {{{ proto int UConverter::getErrorCode() */
     854             : ZEND_BEGIN_ARG_INFO_EX(php_converter_geterrorcode_arginfo, 0, ZEND_RETURN_VALUE, 0)
     855             : ZEND_END_ARG_INFO();
     856           1 : static PHP_METHOD(UConverter, getErrorCode) {
     857           1 :         php_converter_object *objval = CONV_GET(getThis());
     858             : 
     859           1 :         if (zend_parse_parameters_none() == FAILURE) {
     860           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     861             :                         "UConverter::getErrorCode(): expected no arguments", 0);
     862           0 :                 RETURN_FALSE;
     863             :         }
     864             : 
     865           1 :         RETURN_LONG(intl_error_get_code(&(objval->error)));
     866             : }
     867             : /* }}} */
     868             : 
     869             : /* {{{ proto string UConverter::getErrorMessage() */
     870             : ZEND_BEGIN_ARG_INFO_EX(php_converter_geterrormsg_arginfo, 0, ZEND_RETURN_VALUE, 0)
     871             : ZEND_END_ARG_INFO();
     872           0 : static PHP_METHOD(UConverter, getErrorMessage) {
     873           0 :         php_converter_object *objval = CONV_GET(getThis());
     874           0 :         zend_string *message = intl_error_get_message(&(objval->error));
     875             : 
     876           0 :         if (zend_parse_parameters_none() == FAILURE) {
     877           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     878             :                         "UConverter::getErrorMessage(): expected no arguments", 0);
     879           0 :                 RETURN_FALSE;
     880             :         }
     881             : 
     882           0 :         if (message) {
     883           0 :                 RETURN_STR(message);
     884             :         } else {
     885           0 :                 RETURN_NULL();
     886             :         }
     887             : }
     888             : /* }}} */
     889             : 
     890             : /* {{{ proto array UConverter::getAvailable() */
     891             : ZEND_BEGIN_ARG_INFO_EX(php_converter_getavailable_arginfo, 0, ZEND_RETURN_VALUE, 0)
     892             : ZEND_END_ARG_INFO();
     893           1 : static PHP_METHOD(UConverter, getAvailable) {
     894             :         int32_t i,
     895           1 :                         count = ucnv_countAvailable();
     896             : 
     897           1 :         if (zend_parse_parameters_none() == FAILURE) {
     898           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     899             :                         "UConverter::getErrorMessage(): expected no arguments", 0);
     900           0 :                 RETURN_FALSE;
     901             :         }
     902           1 :         intl_error_reset(NULL);
     903             : 
     904           1 :         array_init(return_value);
     905         226 :         for(i = 0; i < count; i++) {
     906         225 :                 const char *name = ucnv_getAvailableName(i);
     907         225 :                 add_next_index_string(return_value, name);
     908             :         }
     909             : }
     910             : /* }}} */
     911             : 
     912             : /* {{{ proto array UConverter::getAliases(string name) */
     913             : ZEND_BEGIN_ARG_INFO_EX(php_converter_getaliases_arginfo, 0, ZEND_RETURN_VALUE, 0)
     914             :         ZEND_ARG_INFO(0, name)
     915             : ZEND_END_ARG_INFO();
     916           1 : static PHP_METHOD(UConverter, getAliases) {
     917             :         char *name;
     918             :         size_t name_len;
     919           1 :         UErrorCode error = U_ZERO_ERROR;
     920             :         uint16_t i, count;
     921             : 
     922           1 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
     923           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     924             :                         "UConverter::getAliases(): bad arguments", 0);
     925           0 :                 RETURN_FALSE;
     926             :         }
     927           1 :         intl_error_reset(NULL);
     928             : 
     929           1 :         count = ucnv_countAliases(name, &error);
     930           1 :         if (U_FAILURE(error)) {
     931           0 :                 THROW_UFAILURE(NULL, "ucnv_countAliases", error);
     932           0 :                 RETURN_FALSE;
     933             :         }
     934             : 
     935           1 :         array_init(return_value);
     936          12 :         for(i = 0; i < count; i++) {
     937             :                 const char *alias;
     938             : 
     939          11 :                 error = U_ZERO_ERROR;
     940          11 :                 alias = ucnv_getAlias(name, i, &error);
     941          11 :                 if (U_FAILURE(error)) {
     942           0 :                         THROW_UFAILURE(NULL, "ucnv_getAlias", error);
     943             :                         zval_dtor(return_value);
     944           0 :                         RETURN_NULL();
     945             :                 }
     946          11 :                 add_next_index_string(return_value, alias);
     947             :         }
     948             : }
     949             : /* }}} */
     950             : 
     951             : /* {{{ proto array UConverter::getStandards() */
     952             : ZEND_BEGIN_ARG_INFO_EX(php_converter_getstandards_arginfo, 0, ZEND_RETURN_VALUE, 0)
     953             : ZEND_END_ARG_INFO();
     954           0 : static PHP_METHOD(UConverter, getStandards) {
     955             :         uint16_t i, count;
     956             : 
     957           0 :         if (zend_parse_parameters_none() == FAILURE) {
     958           0 :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     959             :                         "UConverter::getStandards(): expected no arguments", 0);
     960           0 :                 RETURN_FALSE;
     961             :         }
     962           0 :         intl_error_reset(NULL);
     963             : 
     964           0 :         array_init(return_value);
     965           0 :         count = ucnv_countStandards();
     966           0 :         for(i = 0; i < count; i++) {
     967           0 :                 UErrorCode error = U_ZERO_ERROR;
     968           0 :                 const char *name = ucnv_getStandard(i, &error);
     969           0 :                 if (U_FAILURE(error)) {
     970           0 :                         THROW_UFAILURE(NULL, "ucnv_getStandard", error);
     971             :                         zval_dtor(return_value);
     972           0 :                         RETURN_NULL();
     973             :                 }
     974           0 :                 add_next_index_string(return_value, name);
     975             :         }
     976             : }
     977             : /* }}} */
     978             : 
     979             : static zend_function_entry php_converter_methods[] = {
     980             :         PHP_ME(UConverter, __construct,            php_converter_arginfo,                   ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
     981             : 
     982             :         /* Encoding selection */
     983             :         PHP_ME(UConverter, setSourceEncoding,      php_converter_set_encoding_arginfo,      ZEND_ACC_PUBLIC)
     984             :         PHP_ME(UConverter, setDestinationEncoding, php_converter_set_encoding_arginfo,      ZEND_ACC_PUBLIC)
     985             :         PHP_ME(UConverter, getSourceEncoding,      php_converter_get_encoding_arginfo,      ZEND_ACC_PUBLIC)
     986             :         PHP_ME(UConverter, getDestinationEncoding, php_converter_get_encoding_arginfo,      ZEND_ACC_PUBLIC)
     987             : 
     988             :         /* Introspection for algorithmic converters */
     989             :         PHP_ME(UConverter, getSourceType,          php_converter_get_type_arginfo,          ZEND_ACC_PUBLIC)
     990             :         PHP_ME(UConverter, getDestinationType,     php_converter_get_type_arginfo,          ZEND_ACC_PUBLIC)
     991             : 
     992             :         /* Basic codeunit error handling */
     993             :         PHP_ME(UConverter, getSubstChars,          php_converter_getSubstChars_arginfo,     ZEND_ACC_PUBLIC)
     994             :         PHP_ME(UConverter, setSubstChars,          php_converter_setSubstChars_arginfo,     ZEND_ACC_PUBLIC)
     995             : 
     996             :         /* Default callback handlers */
     997             :         PHP_ME(UConverter, toUCallback,            php_converter_toUCallback_arginfo,       ZEND_ACC_PUBLIC)
     998             :         PHP_ME(UConverter, fromUCallback,          php_converter_fromUCallback_arginfo,     ZEND_ACC_PUBLIC)
     999             : 
    1000             :         /* Core conversion workhorses */
    1001             :         PHP_ME(UConverter, convert,                php_converter_convert_arginfo,           ZEND_ACC_PUBLIC)
    1002             :         PHP_ME(UConverter, transcode,              php_converter_transcode_arginfo,         ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    1003             : 
    1004             :         /* Error inspection */
    1005             :         PHP_ME(UConverter, getErrorCode,           php_converter_geterrorcode_arginfo,      ZEND_ACC_PUBLIC)
    1006             :         PHP_ME(UConverter, getErrorMessage,        php_converter_geterrormsg_arginfo,       ZEND_ACC_PUBLIC)
    1007             : 
    1008             :         /* Ennumeration and lookup */
    1009             :         PHP_ME(UConverter, reasonText,             php_converter_reasontext_arginfo,        ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    1010             :         PHP_ME(UConverter, getAvailable,           php_converter_getavailable_arginfo,      ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    1011             :         PHP_ME(UConverter, getAliases,             php_converter_getaliases_arginfo,        ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    1012             :         PHP_ME(UConverter, getStandards,           php_converter_getstandards_arginfo,      ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    1013             :         { NULL, NULL, NULL }
    1014             : };
    1015             : 
    1016             : /* {{{ Converter create/clone/destroy */
    1017           9 : static void php_converter_dtor_object(zend_object *obj) {
    1018           9 :         php_converter_object *objval = php_converter_fetch_object(obj);
    1019             : 
    1020           9 :         if (objval->src) {
    1021           7 :                 ucnv_close(objval->src);
    1022             :         }
    1023             : 
    1024           9 :         if (objval->dest) {
    1025           8 :                 ucnv_close(objval->dest);
    1026             :         }
    1027             : 
    1028           9 :         intl_error_reset(&(objval->error));
    1029           9 : }
    1030             : 
    1031           9 : static zend_object *php_converter_object_ctor(zend_class_entry *ce, php_converter_object **pobjval) {
    1032             :         php_converter_object *objval;
    1033             : 
    1034           9 :         objval = ecalloc(1, sizeof(php_converter_object) + zend_object_properties_size(ce));
    1035             : 
    1036           9 :         zend_object_std_init(&objval->obj, ce );
    1037           9 :         intl_error_init(&(objval->error));
    1038             : 
    1039           9 :         objval->obj.handlers = &php_converter_object_handlers;
    1040           9 :         *pobjval = objval;
    1041             : 
    1042           9 :         return &objval->obj;
    1043             : }
    1044             : 
    1045           9 : static zend_object *php_converter_create_object(zend_class_entry *ce) {
    1046           9 :         php_converter_object *objval = NULL;
    1047           9 :         zend_object *retval = php_converter_object_ctor(ce, &objval);
    1048             : 
    1049           9 :         object_properties_init(&(objval->obj), ce);
    1050             : 
    1051           9 :         return retval;
    1052             : }
    1053             : 
    1054           0 : static zend_object *php_converter_clone_object(zval *object) {
    1055           0 :         php_converter_object *objval, *oldobj = Z_INTL_CONVERTER_P(object);
    1056           0 :         zend_object *retval = php_converter_object_ctor(Z_OBJCE_P(object), &objval);
    1057           0 :         UErrorCode error = U_ZERO_ERROR;
    1058             : 
    1059           0 :         intl_errors_reset(&oldobj->error);
    1060             : 
    1061           0 :         objval->src = ucnv_safeClone(oldobj->src, NULL, NULL, &error);
    1062           0 :         if (U_SUCCESS(error)) {
    1063           0 :                 error = U_ZERO_ERROR;
    1064           0 :                 objval->dest = ucnv_safeClone(oldobj->dest, NULL, NULL, &error);
    1065             :         }
    1066           0 :         if (U_FAILURE(error)) {
    1067             :                 zend_string *err_msg;
    1068           0 :                 THROW_UFAILURE(oldobj, "ucnv_safeClone", error);
    1069             : 
    1070           0 :                 err_msg = intl_error_get_message(&oldobj->error);
    1071           0 :                 zend_throw_exception(NULL, err_msg->val, 0);
    1072             :                 zend_string_release(err_msg);
    1073             : 
    1074           0 :                 return retval;
    1075             :         }
    1076             : 
    1077             :         /* Update contexts for converter error handlers */
    1078           0 :         php_converter_set_callbacks(objval, objval->src );
    1079           0 :         php_converter_set_callbacks(objval, objval->dest);
    1080             : 
    1081           0 :         zend_objects_clone_members(&(objval->obj), &(oldobj->obj));
    1082             : 
    1083             :         /* Newly cloned object deliberately does not inherit error state from original object */
    1084             : 
    1085           0 :         return retval;
    1086             : }
    1087             : /* }}} */
    1088             : 
    1089             : #define CONV_REASON_CONST(v) zend_declare_class_constant_long(php_converter_ce, "REASON_" #v, sizeof("REASON_" #v) - 1, UCNV_ ## v)
    1090             : #define CONV_TYPE_CONST(v)   zend_declare_class_constant_long(php_converter_ce, #v ,          sizeof(#v) - 1,           UCNV_ ## v)
    1091             : 
    1092             : /* {{{ php_converter_minit */
    1093       20916 : int php_converter_minit(INIT_FUNC_ARGS) {
    1094             :         zend_class_entry ce;
    1095             : 
    1096       20916 :         INIT_CLASS_ENTRY(ce, "UConverter", php_converter_methods);
    1097       20916 :         php_converter_ce = zend_register_internal_class(&ce);
    1098       20916 :         php_converter_ce->create_object = php_converter_create_object;
    1099       20916 :         memcpy(&php_converter_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
    1100       20916 :         php_converter_object_handlers.offset = XtOffsetOf(php_converter_object, obj);
    1101       20916 :         php_converter_object_handlers.clone_obj = php_converter_clone_object;
    1102       20916 :         php_converter_object_handlers.dtor_obj = php_converter_dtor_object;
    1103             : 
    1104             :         /* enum UConverterCallbackReason */
    1105       20916 :         CONV_REASON_CONST(UNASSIGNED);
    1106       20916 :         CONV_REASON_CONST(ILLEGAL);
    1107       20916 :         CONV_REASON_CONST(IRREGULAR);
    1108       20916 :         CONV_REASON_CONST(RESET);
    1109       20916 :         CONV_REASON_CONST(CLOSE);
    1110       20916 :         CONV_REASON_CONST(CLONE);
    1111             : 
    1112             :         /* enum UConverterType */
    1113       20916 :         CONV_TYPE_CONST(UNSUPPORTED_CONVERTER);
    1114       20916 :         CONV_TYPE_CONST(SBCS);
    1115       20916 :         CONV_TYPE_CONST(DBCS);
    1116       20916 :         CONV_TYPE_CONST(MBCS);
    1117       20916 :         CONV_TYPE_CONST(LATIN_1);
    1118       20916 :         CONV_TYPE_CONST(UTF8);
    1119       20916 :         CONV_TYPE_CONST(UTF16_BigEndian);
    1120       20916 :         CONV_TYPE_CONST(UTF16_LittleEndian);
    1121       20916 :         CONV_TYPE_CONST(UTF32_BigEndian);
    1122       20916 :         CONV_TYPE_CONST(UTF32_LittleEndian);
    1123       20916 :         CONV_TYPE_CONST(EBCDIC_STATEFUL);
    1124       20916 :         CONV_TYPE_CONST(ISO_2022);
    1125       20916 :         CONV_TYPE_CONST(LMBCS_1);
    1126       20916 :         CONV_TYPE_CONST(LMBCS_2);
    1127       20916 :         CONV_TYPE_CONST(LMBCS_3);
    1128       20916 :         CONV_TYPE_CONST(LMBCS_4);
    1129       20916 :         CONV_TYPE_CONST(LMBCS_5);
    1130       20916 :         CONV_TYPE_CONST(LMBCS_6);
    1131       20916 :         CONV_TYPE_CONST(LMBCS_8);
    1132       20916 :         CONV_TYPE_CONST(LMBCS_11);
    1133       20916 :         CONV_TYPE_CONST(LMBCS_16);
    1134       20916 :         CONV_TYPE_CONST(LMBCS_17);
    1135       20916 :         CONV_TYPE_CONST(LMBCS_18);
    1136       20916 :         CONV_TYPE_CONST(LMBCS_19);
    1137       20916 :         CONV_TYPE_CONST(LMBCS_LAST);
    1138       20916 :         CONV_TYPE_CONST(HZ);
    1139       20916 :         CONV_TYPE_CONST(SCSU);
    1140       20916 :         CONV_TYPE_CONST(ISCII);
    1141       20916 :         CONV_TYPE_CONST(US_ASCII);
    1142       20916 :         CONV_TYPE_CONST(UTF7);
    1143       20916 :         CONV_TYPE_CONST(BOCU1);
    1144       20916 :         CONV_TYPE_CONST(UTF16);
    1145       20916 :         CONV_TYPE_CONST(UTF32);
    1146       20916 :         CONV_TYPE_CONST(CESU8);
    1147       20916 :         CONV_TYPE_CONST(IMAP_MAILBOX);
    1148             : 
    1149       20916 :         return SUCCESS;
    1150             : }
    1151             : /* }}} */
    1152             : 
    1153             : /*
    1154             :  * Local variables:
    1155             :  * tab-width: 4
    1156             :  * c-basic-offset: 4
    1157             :  * End:
    1158             :  * vim600: noet sw=4 ts=4 fdm=marker
    1159             :  * vim<600: noet sw=4 ts=4
    1160             :  */

Generated by: LCOV version 1.10

Generated at Thu, 21 May 2015 19:58:56 +0000 (4 days ago)

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