U_CFUNC PHP_FUNCTION(intltz_get_region) { char *str_id; size_t str_id_len; char outbuf[3]; intl_error_reset(NULL); if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str_id, &str_id_len) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "intltz_get_region: bad arguments", 0); RETURN_FALSE; } UErrorCode status = UErrorCode(); UnicodeString id; if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) { intl_error_set(NULL, status, "intltz_get_region: could not convert time zone id to UTF-16", 0); RETURN_FALSE; } int32_t region_len = TimeZone::getRegion(id, outbuf, sizeof(outbuf), status); INTL_CHECK_STATUS(status, "intltz_get_region: Error obtaining region"); RETURN_STRINGL(outbuf, region_len); }
U_CFUNC PHP_FUNCTION(intltz_get_equivalent_id) { char *str_id; size_t str_id_len; zend_long index; intl_error_reset(NULL); if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl", &str_id, &str_id_len, &index) == FAILURE || index < (zend_long)INT32_MIN || index > (zend_long)INT32_MAX) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "intltz_get_equivalent_id: bad arguments", 0); RETURN_FALSE; } UErrorCode status = UErrorCode(); UnicodeString id; if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) { intl_error_set(NULL, status, "intltz_get_equivalent_id: could not convert time zone id to UTF-16", 0); RETURN_FALSE; } const UnicodeString result = TimeZone::getEquivalentID(id, (int32_t)index); zend_string *u8str; u8str = intl_convert_utf16_to_utf8(result.getBuffer(), result.length(), &status); INTL_CHECK_STATUS(status, "intltz_get_equivalent_id: " "could not convert resulting time zone id to UTF-16"); RETVAL_NEW_STR(u8str); }
U_CFUNC PHP_FUNCTION(intltz_get_equivalent_id) { char *str_id; int str_id_len; long index; intl_error_reset(NULL TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &str_id, &str_id_len, &index) == FAILURE || index < (long)INT32_MIN || index > (long)INT32_MAX) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "intltz_get_equivalent_id: bad arguments", 0 TSRMLS_CC); RETURN_FALSE; } UErrorCode status = UErrorCode(); UnicodeString id; if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) { intl_error_set(NULL, status, "intltz_get_equivalent_id: could not convert time zone id to UTF-16", 0 TSRMLS_CC); RETURN_FALSE; } const UnicodeString result = TimeZone::getEquivalentID(id, (int32_t)index); intl_convert_utf16_to_utf8(&Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value), result.getBuffer(), result.length(), &status); INTL_CHECK_STATUS(status, "intltz_get_equivalent_id: " "could not convert resulting time zone id to UTF-16"); Z_TYPE_P(return_value) = IS_STRING; }
U_CFUNC PHP_FUNCTION(intltz_create_time_zone) { char *str_id; int str_id_len; intl_error_reset(NULL TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str_id, &str_id_len) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "intltz_create_time_zone: bad arguments", 0 TSRMLS_CC); RETURN_NULL(); } UErrorCode status = UErrorCode(); UnicodeString id = UnicodeString(); if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) { intl_error_set(NULL, status, "intltz_create_time_zone: could not convert time zone id to UTF-16", 0 TSRMLS_CC); RETURN_NULL(); } //guaranteed non-null; GMT if timezone cannot be understood TimeZone *tz = TimeZone::createTimeZone(id); timezone_object_construct(tz, return_value, 1 TSRMLS_CC); }
U_CFUNC PHP_FUNCTION(intltz_get_canonical_id) { char *str_id; size_t str_id_len; zval *is_systemid = NULL; intl_error_reset(NULL); if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|z", &str_id, &str_id_len, &is_systemid) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "intltz_get_canonical_id: bad arguments", 0); RETURN_FALSE; } UErrorCode status = UErrorCode(); UnicodeString id; if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) { intl_error_set(NULL, status, "intltz_get_canonical_id: could not convert time zone id to UTF-16", 0); RETURN_FALSE; } UnicodeString result; UBool isSystemID; TimeZone::getCanonicalID(id, result, isSystemID, status); INTL_CHECK_STATUS(status, "intltz_get_canonical_id: error obtaining canonical ID"); char *str; int str_len; intl_convert_utf16_to_utf8(&str, &str_len, result.getBuffer(), result.length(), &status); INTL_CHECK_STATUS(status, "intltz_get_canonical_id: could not convert time zone id to UTF-16"); RETVAL_STRINGL(str, str_len); //???? efree(str); if (is_systemid) { /* by-ref argument passed */ ZVAL_DEREF(is_systemid); zval_dtor(is_systemid); ZVAL_BOOL(is_systemid, isSystemID); } }
U_CFUNC PHP_FUNCTION(intltz_count_equivalent_ids) { char *str_id; size_t str_id_len; intl_error_reset(NULL); if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str_id, &str_id_len) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "intltz_count_equivalent_ids: bad arguments", 0); RETURN_FALSE; } UErrorCode status = UErrorCode(); UnicodeString id = UnicodeString(); if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) { intl_error_set(NULL, status, "intltz_count_equivalent_ids: could not convert time zone id to UTF-16", 0); RETURN_FALSE; } int32_t result = TimeZone::countEquivalentIDs(id); RETURN_LONG((zend_long)result); }
U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, HashTable *args, UChar **formatted, int32_t *formatted_len) { int arg_count = zend_hash_num_elements(args); std::vector<Formattable> fargs; std::vector<UnicodeString> farg_names; MessageFormat *mf = (MessageFormat *)mfo->mf_data.umsgf; HashTable *types; intl_error& err = INTL_DATA_ERROR(mfo); if (U_FAILURE(err.code)) { return; } types = umsg_get_types(mfo, err); umsg_set_timezone(mfo, err); fargs.resize(arg_count); farg_names.resize(arg_count); int argNum = 0; zval *elem; // Key related variables zend_string *str_index; zend_ulong num_index; ZEND_HASH_FOREACH_KEY_VAL(args, num_index, str_index, elem) { Formattable& formattable = fargs[argNum]; UnicodeString& key = farg_names[argNum]; Formattable::Type argType = Formattable::kObject, //unknown *storedArgType = NULL; if (!U_SUCCESS(err.code)) { break; } /* Process key and retrieve type */ if (str_index == NULL) { /* includes case where index < 0 because it's exposed as unsigned */ if (num_index > (zend_ulong)INT32_MAX) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found negative or too large array key", 0); continue; } UChar temp[16]; int32_t len = u_sprintf(temp, "%u", (uint32_t)num_index); key.append(temp, len); storedArgType = (Formattable::Type*)zend_hash_index_find_ptr(types, (zend_ulong)num_index); } else { //string; assumed to be in UTF-8 intl_stringFromChar(key, ZSTR_VAL(str_index), ZSTR_LEN(str_index), &err.code); if (U_FAILURE(err.code)) { char *message; spprintf(&message, 0, "Invalid UTF-8 data in argument key: '%s'", ZSTR_VAL(str_index)); intl_errors_set(&err, err.code, message, 1); efree(message); continue; } storedArgType = (Formattable::Type*)zend_hash_str_find_ptr(types, (char*)key.getBuffer(), key.length()); } if (storedArgType != NULL) { argType = *storedArgType; } /* Convert zval to formattable according to message format type * or (as a fallback) the zval type */ if (argType != Formattable::kObject) { switch (argType) { case Formattable::kString: { string_arg: /* This implicitly converts objects * Note that our vectors will leak if object conversion fails * and PHP ends up with a fatal error and calls longjmp * as a result of that. */ convert_to_string_ex(elem); UnicodeString *text = new UnicodeString(); intl_stringFromChar(*text, Z_STRVAL_P(elem), Z_STRLEN_P(elem), &err.code); if (U_FAILURE(err.code)) { char *message; spprintf(&message, 0, "Invalid UTF-8 data in string argument: " "'%s'", Z_STRVAL_P(elem)); intl_errors_set(&err, err.code, message, 1); efree(message); delete text; continue; } formattable.adoptString(text); break; } case Formattable::kDouble: { double d; if (Z_TYPE_P(elem) == IS_DOUBLE) { d = Z_DVAL_P(elem); } else if (Z_TYPE_P(elem) == IS_LONG) { d = (double)Z_LVAL_P(elem); } else { SEPARATE_ZVAL_IF_NOT_REF(elem); convert_scalar_to_number(elem); d = (Z_TYPE_P(elem) == IS_DOUBLE) ? Z_DVAL_P(elem) : (double)Z_LVAL_P(elem); } formattable.setDouble(d); break; } case Formattable::kLong: { int32_t tInt32 = 0; retry_klong: if (Z_TYPE_P(elem) == IS_DOUBLE) { if (Z_DVAL_P(elem) > (double)INT32_MAX || Z_DVAL_P(elem) < (double)INT32_MIN) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found PHP float with absolute value too large for " "32 bit integer argument", 0); } else { tInt32 = (int32_t)Z_DVAL_P(elem); } } else if (Z_TYPE_P(elem) == IS_LONG) { if (Z_LVAL_P(elem) > INT32_MAX || Z_LVAL_P(elem) < INT32_MIN) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found PHP integer with absolute value too large " "for 32 bit integer argument", 0); } else { tInt32 = (int32_t)Z_LVAL_P(elem); } } else { SEPARATE_ZVAL_IF_NOT_REF(elem); convert_scalar_to_number(elem); goto retry_klong; } formattable.setLong(tInt32); break; } case Formattable::kInt64: { int64_t tInt64 = 0; retry_kint64: if (Z_TYPE_P(elem) == IS_DOUBLE) { if (Z_DVAL_P(elem) > (double)U_INT64_MAX || Z_DVAL_P(elem) < (double)U_INT64_MIN) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found PHP float with absolute value too large for " "64 bit integer argument", 0); } else { tInt64 = (int64_t)Z_DVAL_P(elem); } } else if (Z_TYPE_P(elem) == IS_LONG) { /* assume long is not wider than 64 bits */ tInt64 = (int64_t)Z_LVAL_P(elem); } else { SEPARATE_ZVAL_IF_NOT_REF(elem); convert_scalar_to_number(elem); goto retry_kint64; } formattable.setInt64(tInt64); break; } case Formattable::kDate: { double dd = intl_zval_to_millis(elem, &err, "msgfmt_format"); if (U_FAILURE(err.code)) { char *message; zend_string *u8key; UErrorCode status = UErrorCode(); u8key = intl_charFromString(key, &status); if (u8key) { spprintf(&message, 0, "The argument for key '%s' " "cannot be used as a date or time", ZSTR_VAL(u8key)); intl_errors_set(&err, err.code, message, 1); zend_string_release(u8key); efree(message); } continue; } formattable.setDate(dd); break; } default: intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found unsupported argument type", 0); break; } } else { /* We couldn't find any information about the argument in the pattern, this * means it's an extra argument. So convert it to a number if it's a number or * bool or null and to a string if it's anything else except arrays . */ switch (Z_TYPE_P(elem)) { case IS_DOUBLE: formattable.setDouble(Z_DVAL_P(elem)); break; case IS_TRUE: case IS_FALSE: convert_to_long_ex(elem); /* Intentional fallthrough */ case IS_LONG: formattable.setInt64((int64_t)Z_LVAL_P(elem)); break; case IS_NULL: formattable.setInt64((int64_t)0); break; case IS_STRING: case IS_OBJECT: goto string_arg; default: { char *message; zend_string *u8key; UErrorCode status = UErrorCode(); u8key = intl_charFromString(key, &status); if (u8key) { spprintf(&message, 0, "No strategy to convert the " "value given for the argument with key '%s' " "is available", ZSTR_VAL(u8key)); intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, message, 1); zend_string_release(u8key); efree(message); } } } } argNum++; } ZEND_HASH_FOREACH_END(); // visiting each argument
/* {{{ timezone_process_timezone_argument * TimeZone argument processor. outside_error may be NULL (for static functions/constructors) */ U_CFUNC TimeZone *timezone_process_timezone_argument(zval *zv_timezone, intl_error *outside_error, const char *func) { zval local_zv_tz; char *message = NULL; TimeZone *timeZone; if (zv_timezone == NULL || Z_TYPE_P(zv_timezone) == IS_NULL) { timelib_tzinfo *tzinfo = get_timezone_info(); ZVAL_STRING(&local_zv_tz, tzinfo->name); zv_timezone = &local_zv_tz; } else { ZVAL_NULL(&local_zv_tz); } if (Z_TYPE_P(zv_timezone) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zv_timezone), TimeZone_ce_ptr)) { TimeZone_object *to = Z_INTL_TIMEZONE_P(zv_timezone); if (to->utimezone == NULL) { spprintf(&message, 0, "%s: passed IntlTimeZone is not " "properly constructed", func); if (message) { intl_errors_set(outside_error, U_ILLEGAL_ARGUMENT_ERROR, message, 1); efree(message); } zval_dtor(&local_zv_tz); return NULL; } timeZone = to->utimezone->clone(); if (timeZone == NULL) { spprintf(&message, 0, "%s: could not clone TimeZone", func); if (message) { intl_errors_set(outside_error, U_MEMORY_ALLOCATION_ERROR, message, 1); efree(message); } zval_dtor(&local_zv_tz); return NULL; } } else if (Z_TYPE_P(zv_timezone) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zv_timezone), php_date_get_timezone_ce())) { php_timezone_obj *tzobj = Z_PHPTIMEZONE_P(zv_timezone); zval_dtor(&local_zv_tz); return timezone_convert_datetimezone(tzobj->type, tzobj, 0, outside_error, func); } else { UnicodeString id, gottenId; UErrorCode status = U_ZERO_ERROR; /* outside_error may be NULL */ convert_to_string_ex(zv_timezone); if (intl_stringFromChar(id, Z_STRVAL_P(zv_timezone), Z_STRLEN_P(zv_timezone), &status) == FAILURE) { spprintf(&message, 0, "%s: Time zone identifier given is not a " "valid UTF-8 string", func); if (message) { intl_errors_set(outside_error, status, message, 1); efree(message); } zval_dtor(&local_zv_tz); return NULL; } timeZone = TimeZone::createTimeZone(id); if (timeZone == NULL) { spprintf(&message, 0, "%s: could not create time zone", func); if (message) { intl_errors_set(outside_error, U_MEMORY_ALLOCATION_ERROR, message, 1); efree(message); } zval_dtor(&local_zv_tz); return NULL; } if (timeZone->getID(gottenId) != id) { spprintf(&message, 0, "%s: no such time zone: '%s'", func, Z_STRVAL_P(zv_timezone)); if (message) { intl_errors_set(outside_error, U_ILLEGAL_ARGUMENT_ERROR, message, 1); efree(message); } zval_dtor(&local_zv_tz); delete timeZone; return NULL; } } zval_dtor(&local_zv_tz); return timeZone; }
static void _php_intlrbbi_constructor_body(INTERNAL_FUNCTION_PARAMETERS) { zval *object = getThis(); char *rules; int rules_len; zend_bool compiled = 0; UErrorCode status = U_ZERO_ERROR; intl_error_reset(NULL TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &rules, &rules_len, &compiled) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "rbbi_create_instance: bad arguments", 0 TSRMLS_CC); RETURN_NULL(); } // instantiation of ICU object RuleBasedBreakIterator *rbbi; if (!compiled) { UnicodeString rulesStr; UParseError parseError = UParseError(); if (intl_stringFromChar(rulesStr, rules, rules_len, &status) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "rbbi_create_instance: rules were not a valid UTF-8 string", 0 TSRMLS_CC); RETURN_NULL(); } rbbi = new RuleBasedBreakIterator(rulesStr, parseError, status); intl_error_set_code(NULL, status TSRMLS_CC); if (U_FAILURE(status)) { char *msg; smart_str parse_error_str; parse_error_str = intl_parse_error_to_string(&parseError); spprintf(&msg, 0, "rbbi_create_instance: unable to create " "RuleBasedBreakIterator from rules (%s)", parse_error_str.c); smart_str_free(&parse_error_str); intl_error_set_custom_msg(NULL, msg, 1 TSRMLS_CC); efree(msg); delete rbbi; RETURN_NULL(); } } else { // compiled #if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 48 rbbi = new RuleBasedBreakIterator((uint8_t*)rules, rules_len, status); if (U_FAILURE(status)) { intl_error_set(NULL, status, "rbbi_create_instance: unable to " "create instance from compiled rules", 0 TSRMLS_CC); delete rbbi; RETURN_NULL(); } #else intl_error_set(NULL, U_UNSUPPORTED_ERROR, "rbbi_create_instance: " "compiled rules require ICU >= 4.8", 0 TSRMLS_CC); RETURN_NULL(); #endif } breakiterator_object_create(return_value, rbbi TSRMLS_CC); }