Beispiel #1
0
/**
 * @brief Updates value in @a arr at position @a index with @a value
 * @param[in,out] arr Array
 * @param index Index
 * @param[in,out] value Value
 * @param flags Flags
 * @return Whether the operation succeeded
 * @retval @c FAILURE Failure, @a arr is not an array
 * @retval @c SUCCESS Success
 * @throw @c E_WARNING if @c arr is not an array
 *
 * Equivalent to <tt>$arr[$index] = $value</tt> in PHP where @c $index is an integer.
 * Flags may be a bitwise OR of the following values:
 * @arg @c PH_CTOR: create a copy of @a value and work with that copy; @c *value will be updated with the newly constructed value
 * @arg @c PH_SEPARATE: separate @a arr if its reference count is greater than 1; @c *arr will contain the separated version
 * @arg @c PH_COPY: increment the reference count on @c **value
 */
int zephir_array_update_long(zval **arr, unsigned long index, zval **value, int flags ZEPHIR_DEBUG_PARAMS) {

    if (Z_TYPE_PP(arr) != IS_ARRAY) {
        zend_error(E_WARNING, "Cannot use a scalar value as an array in %s on line %d", file, line);
        return FAILURE;
    }

    if ((flags & PH_CTOR) == PH_CTOR) {
        zval *new_zv;
        Z_DELREF_PP(value);
        ALLOC_ZVAL(new_zv);
        INIT_PZVAL_COPY(new_zv, *value);
        *value = new_zv;
        zval_copy_ctor(new_zv);
    }

    if ((flags & PH_SEPARATE) == PH_SEPARATE) {
        SEPARATE_ZVAL_IF_NOT_REF(arr);
    }

    if ((flags & PH_COPY) == PH_COPY) {
        Z_ADDREF_PP(value);
    }

    return zend_hash_index_update(Z_ARRVAL_PP(arr), index, value, sizeof(zval *), NULL);
}
Beispiel #2
0
/**
 * @brief Unsets @a index from array @a arr
 * @param[in,out] arr Array
 * @param index Index
 * @param flags Flags (@c PH_SEPARATE: separate array if its reference count is greater than 1; @c arr will contain the separated array)
 * @return Whether the operation succeeded
 * @retval @c FAILURE Failure, @a arr is not an array or @a index is of not supported type
 * @retval @c SUCCESS Success
 * @note @c index will be handled as follows: @c NULL is treated as an empty string, @c double values are cast to @c integer, @c bool or @c resource are treated as @c integer
 * @throw @c E_WARNING if @a offset is not a scalar
 */
int ZEPHIR_FASTCALL zephir_array_unset(zval **arr, zval *index, int flags) {

    HashTable *ht;

    if (Z_TYPE_PP(arr) != IS_ARRAY) {
        return FAILURE;
    }

    if ((flags & PH_SEPARATE) == PH_SEPARATE) {
        SEPARATE_ZVAL_IF_NOT_REF(arr);
    }

    ht = Z_ARRVAL_PP(arr);

    switch (Z_TYPE_P(index)) {
    case IS_NULL:
        return (zend_hash_del(ht, "", 1) == SUCCESS);

    case IS_DOUBLE:
        return (zend_hash_index_del(ht, (ulong)Z_DVAL_P(index)) == SUCCESS);

    case IS_LONG:
    case IS_BOOL:
    case IS_RESOURCE:
        return (zend_hash_index_del(ht, Z_LVAL_P(index)) == SUCCESS);

    case IS_STRING:
        return (zend_symtable_del(ht, Z_STRVAL_P(index), Z_STRLEN_P(index)+1) == SUCCESS);

    default:
        zend_error(E_WARNING, "Illegal offset type");
        return 0;
    }
}
Beispiel #3
0
/**
 * @brief Updates value in @a arr at position @a index with @a value using the precomputed hash @a key
 * @param[in,out] arr Array
 * @param index Index
 * @param index_length Length of the index, should include the trailing zero
 * @param key Precomputed hash of @c value
 * @param value Value
 * @param flags Flags
 * @return Whether the operation succeeded
 * @retval @c FAILURE Failure, @a arr is not an array
 * @retval @c SUCCESS Success
 * @throw @c E_WARNING if @a arr is not an array
 *
 * Equivalent to <tt>$arr[$index] = $value</tt> in PHP.
 *
 * Flags may be a bitwise OR of the following values:
 * @arg @c PH_CTOR: create a copy of @a value and work with that copy; @c *value will be updated with the newly constructed value
 * @arg @c PH_SEPARATE: separate @a arr if its reference count is greater than 1; @c *arr will contain the separated version
 * @arg @c PH_COPY: increment the reference count on @c **value
 */
int zephir_array_update_quick_string(zval **arr, const char *index, uint index_length, unsigned long key, zval **value, int flags) {

    if (Z_TYPE_PP(arr) != IS_ARRAY) {
        zend_error(E_WARNING, "Cannot use a scalar value as an array (3)");
        return FAILURE;
    }

    if ((flags & PH_CTOR) == PH_CTOR) {
        zval *new_zv;
        Z_DELREF_PP(value);
        ALLOC_ZVAL(new_zv);
        INIT_PZVAL_COPY(new_zv, *value);
        *value = new_zv;
        zval_copy_ctor(new_zv);
    }

    if ((flags & PH_SEPARATE) == PH_SEPARATE) {
        SEPARATE_ZVAL_IF_NOT_REF(arr);
    }

    if ((flags & PH_COPY) == PH_COPY) {
        Z_ADDREF_PP(value);
    }

    return zend_hash_quick_update(Z_ARRVAL_PP(arr), index, index_length, key, value, sizeof(zval *), NULL);
}
Beispiel #4
0
/**
 * @brief Unsets numeric @a index from array @a arr
 * @param[in,out] arr Array
 * @param index Index
 * @param flags Flags (@c PH_SEPARATE: separate array if its reference count is greater than 1; @c arr will contain the separated array)
 * @return Whether the operation succeeded
 * @retval @c FAILURE Failure or @a arr is not an array
 * @retval @c SUCCESS Success
 */
int ZEPHIR_FASTCALL zephir_array_unset_long(zval **arr, unsigned long index, int flags) {

    if (Z_TYPE_PP(arr) != IS_ARRAY) {
        return 0;
    }

    if ((flags & PH_SEPARATE) == PH_SEPARATE) {
        SEPARATE_ZVAL_IF_NOT_REF(arr);
    }

    return zend_hash_index_del(Z_ARRVAL_PP(arr), index);
}
Beispiel #5
0
/**
 * @brief Unsets string @a index from array @a arr
 * @param[in,out] arr Array
 * @param index Index
 * @param index_length strlen(index)+1
 * @param flags Flags (@c PH_SEPARATE: separate array if its reference count is greater than 1; @c arr will contain the separated array)
 * @return Whether the operation succeeded
 * @retval @c FAILURE Failure or @a arr is not an array
 * @retval @c SUCCESS Success
 */
int ZEPHIR_FASTCALL zephir_array_unset_string(zval **arr, const char *index, uint index_length, int flags) {

    if (Z_TYPE_PP(arr) != IS_ARRAY) {
        return 0;
    }

    if ((flags & PH_SEPARATE) == PH_SEPARATE) {
        SEPARATE_ZVAL_IF_NOT_REF(arr);
    }

    return zend_hash_del(Z_ARRVAL_PP(arr), index, index_length);
}
Beispiel #6
0
/*
 * Multiple array-offset update
 */
int zephir_update_static_property_array_multi_ce(zend_class_entry *ce, const char *property, zend_uint property_length, zval *value, const char *types, int types_length, int types_count, ...)
{
	va_list ap;
	zval tmp_arr;
	int separated = 0;

	ZVAL_UNDEF(&tmp_arr);

	zephir_read_static_property_ce(&tmp_arr, ce, property, property_length, PH_NOISY | PH_READONLY);

	/** Separation only when refcount > 1 */
	if (Z_REFCOUNTED(tmp_arr)) {
		if (Z_REFCOUNT(tmp_arr) > 1) {
			if (!Z_ISREF(tmp_arr)) {
				zval new_zv;
				ZVAL_DUP(&new_zv, &tmp_arr);
				ZVAL_COPY_VALUE(&tmp_arr, &new_zv);
				Z_TRY_DELREF(new_zv);
				separated = 1;
			}
		}
	} else {
		zval new_zv;
		ZVAL_DUP(&new_zv, &tmp_arr);
		ZVAL_COPY_VALUE(&tmp_arr, &new_zv);
		Z_TRY_DELREF(new_zv);
		separated = 1;
	}

	/** Convert the value to array if not is an array */
	if (Z_TYPE(tmp_arr) != IS_ARRAY) {
		if (separated) {
			convert_to_array(&tmp_arr);
		} else {
			array_init(&tmp_arr);
			separated = 1;
		}
		Z_DELREF(tmp_arr);
	}

	va_start(ap, types_count);
	SEPARATE_ZVAL_IF_NOT_REF(&tmp_arr);
	zephir_array_update_multi_ex(&tmp_arr, value, types, types_length, types_count, ap);
	va_end(ap);

	if (separated) {
		zephir_update_static_property_ce(ce, property, property_length, &tmp_arr);
	}

	return SUCCESS;
}
Beispiel #7
0
/**
 * @brief Pushes @a value onto the end of @a arr
 * @param[in,out] arr Array
 * @param[in,out] value Value to add; reference counter of @c *value will be incrememnted
 * @param flags Flags (@c PH_SEPARATE: separate array if its reference count is greater than 1; @c arr will contain the separated array)
 * @return Whether the operation succeeded
 * @retval @c FAILURE Failure or @a arr is not an array
 * @retval @c SUCCESS Success
 * @throw @c E_WARNING if @a is not an array
 */
int zephir_array_append(zval **arr, zval *value, int flags ZEPHIR_DEBUG_PARAMS) {

    if (Z_TYPE_PP(arr) != IS_ARRAY) {
        zend_error(E_WARNING, "Cannot use a scalar value as an array in %s on line %d", file, line);
        return FAILURE;
    }

    if ((flags & PH_SEPARATE) == PH_SEPARATE) {
        SEPARATE_ZVAL_IF_NOT_REF(arr);
    }

    Z_ADDREF_P(value);
    return add_next_index_zval(*arr, value);
}
Beispiel #8
0
/**
 * @brief Updates value in @a arr at position @a index with @a value
 * @param[in,out] arr Array
 * @param index Index
 * @param[in,out] value Value
 * @param flags Flags
 * @return Whether the operation succeeded
 * @retval @c FAILURE Failure, @a arr is not an array or @a index is of not supported type
 * @retval @c SUCCESS Success
 * @note @c index will be handled as follows: @c NULL is treated as an empty string, @c double values are cast to @c integer, @c bool or @c resource are treated as @c integer
 * @throw @c E_WARNING if @a offset is not a scalar or @c arr is not an array
 *
 * Equivalent to <tt>$arr[$index] = $value</tt> in PHP.
 * Flags may be a bitwise OR of the following values:
 * @arg @c PH_CTOR: create a copy of @a value and work with that copy; @c *value will be updated with the newly constructed value
 * @arg @c PH_SEPARATE: separate @a arr if its reference count is greater than 1; @c *arr will contain the separated version
 * @arg @c PH_COPY: increment the reference count on @c **value
 */
int zephir_array_update_zval(zval **arr, zval *index, zval **value, int flags) {

    HashTable *ht;

    if (Z_TYPE_PP(arr) != IS_ARRAY) {
        zend_error(E_WARNING, "Cannot use a scalar value as an array (2)");
        return FAILURE;
    }

    if ((flags & PH_CTOR) == PH_CTOR) {
        zval *new_zv;
        Z_DELREF_PP(value);
        ALLOC_ZVAL(new_zv);
        INIT_PZVAL_COPY(new_zv, *value);
        *value = new_zv;
        zval_copy_ctor(new_zv);
    }

    if ((flags & PH_SEPARATE) == PH_SEPARATE) {
        SEPARATE_ZVAL_IF_NOT_REF(arr);
    }

    if ((flags & PH_COPY) == PH_COPY) {
        Z_ADDREF_PP(value);
    }

    ht = Z_ARRVAL_PP(arr);

    switch (Z_TYPE_P(index)) {
    case IS_NULL:
        return zend_symtable_update(ht, "", 1, value, sizeof(zval*), NULL);

    case IS_DOUBLE:
        return zend_hash_index_update(ht, (ulong)Z_DVAL_P(index), value, sizeof(zval*), NULL);

    case IS_LONG:
    case IS_BOOL:
    case IS_RESOURCE:
        return zend_hash_index_update(ht, Z_LVAL_P(index), value, sizeof(zval*), NULL);

    case IS_STRING:
        return zend_symtable_update(ht, Z_STRVAL_P(index), Z_STRLEN_P(index)+1, value, sizeof(zval*), NULL);

    default:
        zend_error(E_WARNING, "Illegal offset type");
        return FAILURE;
    }
}
Beispiel #9
0
static int32_t qb_transfer_value_to_import_source(qb_interpreter_context *cxt, qb_variable *ivar, qb_import_scope *scope) {
	int32_t result = TRUE;
	if(ivar->flags & QB_VARIABLE_IMPORTED) {
		USE_TSRM
		zval *zvalue = ivar->value, **p_zvalue = ivar->value_pointer;
		if(!IS_READ_ONLY(ivar->address)) {
			if(zvalue) {
				// separate the zval first, since we're modifying it
				SEPARATE_ZVAL_IF_NOT_REF(&zvalue);
			} else {
				ALLOC_INIT_ZVAL(zvalue);
			}
			if(!qb_transfer_value_to_zval(scope->storage, ivar->address, zvalue)) {
				uint32_t line_id = qb_get_zend_line_id(TSRMLS_C);
				qb_append_exception_variable_name(ivar TSRMLS_CC);
				qb_set_exception_line_id(line_id TSRMLS_CC);
				result = FALSE;
			}

			if(p_zvalue) {
				*p_zvalue = zvalue;
			} else {
				if(ivar->flags & QB_VARIABLE_GLOBAL) {
					zend_hash_quick_update(&EG(symbol_table), ivar->name, ivar->name_length + 1, ivar->hash_value, (void **) &zvalue, sizeof(zval *), NULL);
				} else if(ivar->flags & QB_VARIABLE_CLASS_INSTANCE) {
					zval *container = scope->object;
					zval *name = qb_string_to_zval(ivar->name, ivar->name_length TSRMLS_CC);
					Z_OBJ_WRITE_PROP(container, name, zvalue);
				}
			}
		}
		if(!p_zvalue && zvalue) {
			// if p_zvalue isn't null, then something else has put a refcount 
			// on the zval (and we didn't increment it earlier)
			zval_ptr_dtor(&zvalue);
		}
		ivar->value_pointer = NULL;
		ivar->value = NULL;
		ivar->flags &= ~QB_VARIABLE_IMPORTED;
	}
	return result;
}
Beispiel #10
0
/**
 * Sharpen the image by a given amount.
 *
 * @param int $amount amount to sharpen: 1-100
 * @return Phalcon\Image\Adapter
 */
PHP_METHOD(Phalcon_Image_Adapter, sharpen) {

    zval **amount;

    phalcon_fetch_params_ex(1, 0, &amount);

    PHALCON_MM_GROW();

    SEPARATE_ZVAL_IF_NOT_REF(amount);
    if (Z_TYPE_PP(amount) != IS_LONG) {
        convert_to_long(*amount);
    }

    if (Z_LVAL_PP(amount) > 100) {
        ZVAL_LONG(*amount, 100);
    } else if (Z_LVAL_PP(amount) < 1) {
        ZVAL_LONG(*amount, 1);
    }

    PHALCON_CALL_METHOD(NULL, this_ptr, "_sharpen", *amount);

    RETURN_THIS();
}
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
Beispiel #12
0
/**
 * Crop an image to the given size. Either the width or the height can be
 * omitted and the current width or height will be used.
 *
 * @param int $width new width
 * @param int $height new height
 * @param int $offset_x offset from the left, if it's true then will center
 * @param int $offset_y offset from the top, if it's true then will middle
 * @return Phalcon\Image\Adapter
 */
PHP_METHOD(Phalcon_Image_Adapter, crop) {

    zval **w, **h, **ofs_x = NULL, **ofs_y = NULL;
    zval *image_width, *image_height;
    zval *width, *height, *offset_x, *offset_y;
    long tmp_max_width, tmp_max_height, tmp_width, tmp_height, tmp_image_width, tmp_image_height, tmp_offset_x, tmp_offset_y;

    phalcon_fetch_params_ex(2, 2, &w, &h, &ofs_x, &ofs_y);

    PHALCON_ENSURE_IS_LONG(w);
    PHALCON_ENSURE_IS_LONG(h);

    PHALCON_MM_GROW();

    image_width  = phalcon_fetch_nproperty_this(this_ptr, SL("_width"), PH_NOISY TSRMLS_CC);
    image_height = phalcon_fetch_nproperty_this(this_ptr, SL("_height"), PH_NOISY TSRMLS_CC);

    SEPARATE_ZVAL_IF_NOT_REF(w);
    if (Z_TYPE_PP(w) != IS_LONG) {
        convert_to_long(*w);
    }

    SEPARATE_ZVAL_IF_NOT_REF(h);
    if (Z_TYPE_PP(h) != IS_LONG) {
        convert_to_long(*h);
    }

    if (ofs_x && Z_TYPE_PP(ofs_x) != IS_NULL && Z_TYPE_PP(ofs_x) != IS_BOOL && Z_TYPE_PP(ofs_x) != IS_LONG) {
        SEPARATE_ZVAL_IF_NOT_REF(ofs_x);
        convert_to_long(*ofs_x);
    }

    if (ofs_y && Z_TYPE_PP(ofs_y) != IS_NULL && Z_TYPE_PP(ofs_y) != IS_BOOL && Z_TYPE_PP(ofs_x) != IS_LONG) {
        SEPARATE_ZVAL_IF_NOT_REF(ofs_y);
        convert_to_long(*ofs_y);
    }

    tmp_width        = Z_LVAL_PP(w);
    tmp_height       = Z_LVAL_PP(h);
    tmp_image_width  = phalcon_get_intval(image_width);
    tmp_image_height = phalcon_get_intval(image_height);

    if (tmp_width > tmp_image_width) {
        tmp_width = tmp_image_width;
    }

    if (tmp_height > tmp_image_height) {
        tmp_height = tmp_image_height;
    }

    if (!ofs_x) {
        tmp_offset_x = (int)(((tmp_image_width - tmp_width) / 2) + 0.5);
    } else if (Z_TYPE_PP(ofs_x) == IS_BOOL && PHALCON_IS_TRUE(*ofs_x)) {
        tmp_offset_x = tmp_image_width - tmp_width;
    } else if (Z_TYPE_PP(ofs_x) == IS_LONG) {
        if (Z_LVAL_PP(ofs_x) < 0) {
            tmp_offset_x = (int)(tmp_image_width - tmp_width + Z_LVAL_PP(ofs_x) + 0.5);
        } else {
            tmp_offset_x = Z_LVAL_PP(ofs_x);
        }
    } else {
        tmp_offset_x = (int)(((tmp_image_width - tmp_width) / 2) + 0.5);
    }

    if (!ofs_y) {
        tmp_offset_y = (int)(((tmp_image_height - tmp_height) / 2) + 0.5);
    } else if (Z_TYPE_PP(ofs_x) == IS_BOOL && PHALCON_IS_TRUE(*ofs_y)) {
        tmp_offset_y = tmp_image_height - tmp_height;
    } else if (Z_TYPE_PP(ofs_y) == IS_LONG) {
        if (Z_LVAL_PP(ofs_y) < 0) {
            tmp_offset_y = tmp_image_height - tmp_height + Z_LVAL_PP(ofs_y);
        } else {
            tmp_offset_y = Z_LVAL_PP(ofs_y);
        }
    } else {
        tmp_offset_y = (int)(((tmp_image_height - tmp_height) / 2) + 0.5);
    }

    tmp_max_width  = tmp_image_width  - tmp_offset_x;
    tmp_max_height = tmp_image_height - tmp_offset_y;

    if (tmp_width > tmp_max_width) {
        tmp_width = tmp_max_width;
    }

    if (tmp_height > tmp_max_height) {
        tmp_height = tmp_max_height;
    }

    PHALCON_ALLOC_GHOST_ZVAL(width);
    PHALCON_ALLOC_GHOST_ZVAL(height);
    PHALCON_ALLOC_GHOST_ZVAL(offset_x);
    PHALCON_ALLOC_GHOST_ZVAL(offset_y);

    ZVAL_LONG(width,    tmp_width);
    ZVAL_LONG(height,   tmp_height);
    ZVAL_LONG(offset_x, tmp_offset_x);
    ZVAL_LONG(offset_y, tmp_offset_y);

    PHALCON_CALL_METHOD(NULL, this_ptr, "_crop", width, height, offset_x, offset_y);

    RETURN_THIS();
}
Beispiel #13
0
/* the core of COM */
int php_com_do_invoke_byref(php_com_dotnet_object *obj, zend_internal_function *f,
		WORD flags,	VARIANT *v, int nargs, zval *args)
{
	DISPID dispid, altdispid;
	DISPPARAMS disp_params;
	HRESULT hr;
	VARIANT *vargs = NULL, *byref_vals = NULL;
	int i, byref_count = 0, j;

	/* assumption: that the active function (f) is the function we generated for the engine */
	if (!f) {
		return FAILURE;
	}
	
	hr = php_com_get_id_of_name(obj, f->function_name->val, f->function_name->len, &dispid);

	if (FAILED(hr)) {
		char *winerr = NULL;
		char *msg = NULL;
		winerr = php_win32_error_to_msg(hr);
		spprintf(&msg, 0, "Unable to lookup `%s': %s", f->function_name->val, winerr);
		LocalFree(winerr);
		php_com_throw_exception(hr, msg);
		efree(msg);
		return FAILURE;
	}


	if (nargs) {
		vargs = (VARIANT*)safe_emalloc(sizeof(VARIANT), nargs, 0);
	}

	if (f->arg_info) {
		for (i = 0; i < nargs; i++) {
			if (f->arg_info[nargs - i - 1].pass_by_reference) {
				byref_count++;
			}
		}
	}

	if (byref_count) {
		byref_vals = (VARIANT*)safe_emalloc(sizeof(VARIANT), byref_count, 0);
		for (j = 0, i = 0; i < nargs; i++) {
			if (f->arg_info[nargs - i - 1].pass_by_reference) {
				/* put the value into byref_vals instead */
				php_com_variant_from_zval(&byref_vals[j], &args[nargs - i - 1], obj->code_page);

				/* if it is already byref, "move" it into the vargs array, otherwise
				 * make vargs a reference to this value */
				if (V_VT(&byref_vals[j]) & VT_BYREF) {
					memcpy(&vargs[i], &byref_vals[j], sizeof(vargs[i]));
					VariantInit(&byref_vals[j]); /* leave the variant slot empty to simplify cleanup */
				} else {
					VariantInit(&vargs[i]);
					V_VT(&vargs[i]) = V_VT(&byref_vals[j]) | VT_BYREF;
					/* union magic ensures that this works out */
					vargs[i].byref = &V_UINT(&byref_vals[j]);
				}
				j++;
			} else {
				php_com_variant_from_zval(&vargs[i], &args[nargs - i - 1], obj->code_page);
			}
		}
		
	} else {
		/* Invoke'd args are in reverse order */
		for (i = 0; i < nargs; i++) {
			php_com_variant_from_zval(&vargs[i], &args[nargs - i - 1], obj->code_page);
		}
	}

	disp_params.cArgs = nargs;
	disp_params.cNamedArgs = 0;
	disp_params.rgvarg = vargs;
	disp_params.rgdispidNamedArgs = NULL;

	if (flags & DISPATCH_PROPERTYPUT) {
		altdispid = DISPID_PROPERTYPUT;
		disp_params.rgdispidNamedArgs = &altdispid;
		disp_params.cNamedArgs = 1;
	}

	/* this will create an exception if needed */
	hr = php_com_invoke_helper(obj, dispid, flags, &disp_params, v, 0, 0);	

	/* release variants */
	if (vargs) {
		if (f && f->arg_info) {
			for (i = 0, j = 0; i < nargs; i++) {
				/* if this was byref, update the zval */
				if (f->arg_info[nargs - i - 1].pass_by_reference) {
					SEPARATE_ZVAL_IF_NOT_REF(&args[nargs - i - 1]);

					/* if the variant is pointing at the byref_vals, we need to map
					 * the pointee value as a zval; otherwise, the value is pointing
					 * into an existing PHP variant record */
					if (V_VT(&vargs[i]) & VT_BYREF) {
						if (vargs[i].byref == &V_UINT(&byref_vals[j])) {
							/* copy that value */
							php_com_zval_from_variant(&args[nargs - i - 1], &byref_vals[j],
								obj->code_page);
						}
					} else {
						/* not sure if this can ever happen; the variant we marked as BYREF
						 * is no longer BYREF - copy its value */
						php_com_zval_from_variant(&args[nargs - i - 1], &vargs[i],
							obj->code_page);
					}
					VariantClear(&byref_vals[j]);
					j++;
				}
				VariantClear(&vargs[i]);
			}
		} else {
			for (i = 0, j = 0; i < nargs; i++) {
				VariantClear(&vargs[i]);
			}
		}
		efree(vargs);
	}

	return SUCCEEDED(hr) ? SUCCESS : FAILURE;
}