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

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

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

Generated by: LCOV version 1.10

Generated at Tue, 14 Apr 2015 11:48:43 +0000 (12 days ago)

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