diff options
-rw-r--r-- | include/hashmember.h | 26 | ||||
-rw-r--r-- | include/type.h | 4 | ||||
-rw-r--r-- | include/value.h | 267 | ||||
-rw-r--r-- | src/arithmetic.h | 286 | ||||
-rw-r--r-- | src/includes.h | 2 | ||||
-rw-r--r-- | src/value.cpp | 304 | ||||
-rw-r--r-- | tests/simple/simple.cpp | 97 | ||||
-rw-r--r-- | tests/simple/simple.php | 59 |
8 files changed, 811 insertions, 234 deletions
diff --git a/include/hashmember.h b/include/hashmember.h index 2724836..d476b55 100644 --- a/include/hashmember.h +++ b/include/hashmember.h @@ -71,12 +71,30 @@ public: } /** - * Cast to a long - * @return long + * Cast to a integer + * @return int16_t */ - operator long () const + operator int16_t () const { - return _base.get(_index).longValue(); + return _base.get(_index).numericValue(); + } + + /** + * Cast to a integer + * @return int32_t + */ + operator int32_t () const + { + return _base.get(_index).numericValue(); + } + + /** + * Cast to a integer + * @return int64_t + */ + operator int64_t () const + { + return _base.get(_index).numericValue(); } /** diff --git a/include/type.h b/include/type.h index 04e488b..25b26da 100644 --- a/include/type.h +++ b/include/type.h @@ -19,8 +19,8 @@ namespace Php { */ typedef enum _Type { nullType = 0, - longType = 1, - decimalType = 2, + numericType = 1, + floatType = 2, boolType = 3, arrayType = 4, objectType = 5, diff --git a/include/value.h b/include/value.h index 6c879e6..ed6cec4 100644 --- a/include/value.h +++ b/include/value.h @@ -45,51 +45,17 @@ public: Value(); /** - * Constructor for null ptr - */ - Value(std::nullptr_t value); - - /** - * Constructor based on integer value - * @param value - */ - Value(int value); - - /** - * Constructor based on integer value - * @param value - */ - Value(long value); - - /** - * Constructor based on boolean value + * Constructor for various types * @param value */ + Value(std::nullptr_t value); + Value(int16_t value); + Value(int32_t value); + Value(int64_t value); Value(bool value); - - /** - * Constructor based on single character - * @param value - */ Value(char value); - - /** - * Constructor based on string value - * @param value - */ Value(const std::string &value); - - /** - * Constructor based on byte buffer - * @param value - * @param size - */ Value(const char *value, int size = -1); - - /** - * Constructor based on decimal value - * @param value - */ Value(double value); /** @@ -117,67 +83,146 @@ public: virtual ~Value(); /** - * Assignment operator + * Move assignment * @param value * @return Value */ - Value &operator=(const Value &value); + Value &operator=(Value &&value); /** - * Move assignment + * Assignment operator for various types * @param value * @return Value */ - Value &operator=(Value &&value); + Value &operator=(const Value &value); + Value &operator=(int16_t value); + Value &operator=(int32_t value); + Value &operator=(int64_t value); + Value &operator=(bool value); + Value &operator=(char value); + Value &operator=(const std::string &value); + Value &operator=(const char *value); + Value &operator=(double value); /** - * Assignment operator + * Add a value to the object * @param value * @return Value */ - Value &operator=(long value); + Value &operator+=(const Value &value); + Value &operator+=(int16_t value); + Value &operator+=(int32_t value); + Value &operator+=(int64_t value); + Value &operator+=(bool value); + Value &operator+=(char value); + Value &operator+=(const std::string &value); + Value &operator+=(const char *value); + Value &operator+=(double value); /** - * Assignment operator + * Subtract a value from the object * @param value * @return Value */ - Value &operator=(int value); - + Value &operator-=(const Value &value); + Value &operator-=(int16_t value); + Value &operator-=(int32_t value); + Value &operator-=(int64_t value); + Value &operator-=(bool value); + Value &operator-=(char value); + Value &operator-=(const std::string &value); + Value &operator-=(const char *value); + Value &operator-=(double value); + /** - * Assignment operator + * Multiply the object with a certain value * @param value * @return Value */ - Value &operator=(bool value); + Value &operator*=(const Value &value); + Value &operator*=(int16_t value); + Value &operator*=(int32_t value); + Value &operator*=(int64_t value); + Value &operator*=(bool value); + Value &operator*=(char value); + Value &operator*=(const std::string &value); + Value &operator*=(const char *value); + Value &operator*=(double value); /** + * Divide the object with a certain value + * @param value + * @return Value + */ + Value &operator/=(const Value &value); + Value &operator/=(int16_t value); + Value &operator/=(int32_t value); + Value &operator/=(int64_t value); + Value &operator/=(bool value); + Value &operator/=(char value); + Value &operator/=(const std::string &value); + Value &operator/=(const char *value); + Value &operator/=(double value); + + /** * Assignment operator * @param value * @return Value */ - Value &operator=(char value); + Value operator+(const Value &value); + Value operator+(int16_t value); + Value operator+(int32_t value); + Value operator+(int64_t value); + Value operator+(bool value); + Value operator+(char value); + Value operator+(const std::string &value); + Value operator+(const char *value); + Value operator+(double value); /** - * Assignment operator + * Subtraction operator * @param value * @return Value */ - Value &operator=(const std::string &value); - + Value operator-(const Value &value); + Value operator-(int16_t value); + Value operator-(int32_t value); + Value operator-(int64_t value); + Value operator-(bool value); + Value operator-(char value); + Value operator-(const std::string &value); + Value operator-(const char *value); + Value operator-(double value); + /** - * Assignment operator + * Multiplication operator * @param value * @return Value */ - Value &operator=(const char *value); - + Value operator*(const Value &value); + Value operator*(int16_t value); + Value operator*(int32_t value); + Value operator*(int64_t value); + Value operator*(bool value); + Value operator*(char value); + Value operator*(const std::string &value); + Value operator*(const char *value); + Value operator*(double value); + /** - * Assignment operator + * Division operator * @param value * @return Value */ - Value &operator=(double value); + Value operator/(const Value &value); + Value operator/(int16_t value); + Value operator/(int32_t value); + Value operator/(int64_t value); + Value operator/(bool value); + Value operator/(char value); + Value operator/(const std::string &value); + Value operator/(const char *value); + Value operator/(double value); /** * The type of object @@ -205,73 +250,22 @@ public: Value clone(Type type) const; /** - * Is this a NULL value? - * @return bool - */ - bool isNull() const - { - return type() == nullType; - } - - /** - * Is this an integer value? - * @return bool - */ - bool isLong() const - { - return type() == longType; - } - - /** - * Is this a boolean value? - * @return bool - */ - bool isBool() const - { - return type() == boolType; - } - - /** - * Is this a string value? - * @return bool - */ - bool isString() const - { - return type() == stringType; - } - - /** - * Is this a decimal value? - * @return bool - */ - bool isDecimal() const - { - return type() == decimalType; - } - - /** - * Is this an object value? + * Check if the value is of a certain type * @return bool */ - bool isObject() const - { - return type() == objectType; - } - - /** - * Is this an array value? - * @return bool - */ - bool isArray() const - { - return type() == arrayType; - } + bool isNull() const { return type() == nullType; } + bool isNumeric() const { return type() == numericType; } + bool isBool() const { return type() == boolType; } + bool isString() const { return type() == stringType; } + bool isFloat() const { return type() == floatType; } + bool isObject() const { return type() == objectType; } + bool isArray() const { return type() == arrayType; } /** - * Retrieve the value as integer - * @return int + * Retrieve the value as number + * @return long */ - long longValue() const; + long numericValue() const; /** * Retrieve the value as boolean @@ -297,7 +291,7 @@ public: * Retrieve the value as decimal * @return double */ - double decimalValue() const; + double floatValue() const; /** * The number of members in case of an array or object @@ -349,12 +343,30 @@ public: bool contains(const char *key, int size) const; /** - * Cast to a long - * @return long + * Cast to a number + * @return int32_t + */ + operator int16_t () const + { + return numericValue(); + } + + /** + * Cast to a number + * @return int32_t */ - operator long () const + operator int32_t () const { - return longValue(); + return numericValue(); + } + + /** + * Cast to a number + * @return uint64_t + */ + operator int64_t () const + { + return numericValue(); } /** @@ -390,7 +402,7 @@ public: */ operator double () const { - return decimalValue(); + return floatValue(); } /** @@ -485,7 +497,6 @@ public: */ HashMember<std::string> operator[](const char *key); - protected: /** * The wrapped zval diff --git a/src/arithmetic.h b/src/arithmetic.h new file mode 100644 index 0000000..ae690bc --- /dev/null +++ b/src/arithmetic.h @@ -0,0 +1,286 @@ +/** + * Arithmethic.h + * + * Helper class that takes care of arithmetic operations on PHP variables + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2013 Copernica BV + */ + +/** + * Set up namespace + */ +namespace Php { + +/** + * Class definition + */ +template < template<typename T> class F> +class Arithmetic +{ +public: + /** + * Constructor + * @param value The original object + */ + Arithmetic(Value *value) : _value(value) {} + + /** + * Destructor + */ + virtual ~Arithmetic() {} + + /** + * Apply a number, and return a new value object after running the arithmetic function + * @param value + * @return Value + */ + Value apply(const Value &value) + { + // is this a type a floating point type? + if (value.isFloat()) return apply(value.floatValue()); + + // we are going to treat it as a numeric (non floating) type + return apply(value.numericValue()); + } + + /** + * Apply a number, and return a new value object after running the arithmetic function + * @param value + * @return Value + */ + Value apply(int16_t value) + { + // check if the current object is a floating point number + if (_value->isFloat()) return Value(F<double>()(_value->floatValue(), value)); + + // apply to natural numbers + return Value(F<long>()(_value->numericValue(), value)); + } + + /** + * Apply a number, and return a new value object after running the arithmetic function + * @param value + * @return Value + */ + Value apply(int32_t value) + { + // check if the current object is a floating point number + if (_value->isFloat()) return Value(F<double>()(_value->floatValue(), value)); + + // apply to natural numbers + return Value(F<long>()(_value->numericValue(), value)); + } + + /** + * Apply a number, and return a new value object after running the arithmetic function + * @param value + * @return Value + */ + Value apply(int64_t value) + { + // check if the current object is a floating point number + if (_value->isFloat()) return Value(F<double>()(_value->floatValue(), value)); + + // apply to natural numbers + return Value(F<long>()(_value->numericValue(), value)); + } + + /** + * Apply a boolean (treat is as 0 or 1), and return a new value object after running the arithmetic function + * @param value + * @return Value + */ + Value apply(bool value) + { + // check if the current object is a floating point number + if (_value->isFloat()) return Value(F<double>()(_value->floatValue(), value?1:0)); + + // apply to natural numbers + return Value(F<long>()(_value->numericValue(), value?1:0)); + } + + /** + * Apply a character (value between '0' and '9'), and return a new value object after running the arithmetic function + * @param value + * @return Value + */ + Value apply(char value) + { + // convert to an integer + int v = value < '0' || value > '9' ? 0 : value - '0'; + + // check if the current object is a floating point number + if (_value->isFloat()) return Value(F<double>()(_value->floatValue(), v)); + + // apply to natural numbers + return Value(F<long>()(_value->numericValue(), v)); + } + + /** + * Apply a string (representing a number), and return a new value object after running the arithmetic function + * @param value + * @return Value + */ + Value apply(const std::string &value) + { + // convert string to integer + return apply(atoi(value.c_str())); + } + + /** + * Apply a string (representing a number), and return a new value object after running the arithmetic function + * @param value + * @return Value + */ + Value apply(const char *value) + { + // convert string to integer + return apply(atoi(value)); + } + + /** + * Apply a string (representing a number), and return a new value object after running the arithmetic function + * @param value + * @return Value + */ + Value apply(double value) + { + return Value(F<double>()(_value->floatValue(), value)); + } + + /** + * Assign a different value object, applying the arithmetic operation + * @param value + * @return Value + */ + Value &assign(const Value &value) + { + // is this a type a floating point type? + if (value.isFloat()) return assign(value.floatValue()); + + // we are going to treat it as a numeric (non floating) type + return assign(value.numericValue()); + } + + /** + * Assign a 16bit number, applying the arithmetic operation + * @param value + * @return Value + */ + Value &assign(int16_t value) + { + // is the current object a floating point type? + if (_value->isFloat()) return _value->operator=(F<double>()(_value->floatValue(), value)); + + // do a numeric operation + return _value->operator=(F<long>()(_value->numericValue(), value)); + } + + /** + * Assign 32bit integer, applying the arithmetic operation + * @param value + * @return Value + */ + Value &assign(int32_t value) + { + // is the current object a floating point type? + if (_value->isFloat()) return _value->operator=(F<double>()(_value->floatValue(), value)); + + // do a numeric operation + return _value->operator=(F<long>()(_value->numericValue(), value)); + } + + /** + * Assign 64bit integer, applying the arithmetic operation + * @param value + * @return Value + */ + Value &assign(int64_t value) + { + // is the current object a floating point type? + if (_value->isFloat()) return _value->operator=(F<double>()(_value->floatValue(), value)); + + // do a numeric operation + return _value->operator=(F<int64_t>()(_value->numericValue(), value)); + } + + /** + * Assign 64bit integer - which is treated as 1 or 0 - applying the arithmetic operation + * @param value + * @return Value + */ + Value &assign(bool value) + { + // is the current object a floating point type? + if (_value->isFloat()) return _value->operator=(F<double>()(_value->floatValue(), value?1:0)); + + // do a numeric operation + return _value->operator=(F<int64_t>()(_value->numericValue(), value?1:0)); + } + + /** + * Assign a single character - which is treated as an int, and applying the arithmetic function + * @param value + * @return Value + */ + Value &assign(char value) + { + // convert to an integer + int v = value < '0' || value > '9' ? 0 : value - '0'; + + // is the current object a floating point type? + if (_value->isFloat()) return _value->operator=(F<double>()(_value->floatValue(), v)); + + // do a numeric operation + return _value->operator=(F<int64_t>()(_value->numericValue(), v)); + } + + /** + * Assign a a string - treating it as an integer, and applying the arithmetic function + * @param value + * @return Value + */ + Value &assign(const std::string &value) + { + // assign integer + return assign(atoi(value.c_str())); + } + + /** + * Assign a string - treating it as an integer, and applying the arithmetic function + * @param value + * @return Value + */ + Value &assign(const char *value) + { + // assign integer + return assign(atoi(value)); + } + + /** + * Assign a double, applying the arithmetic operation + * @param value + * @return Value + */ + Value &assign(double value) + { + // do float operation + return _value->operator=(F<double>()(_value->floatValue(), value)); + } + +private: + /** + * Pointer to the original value object + * @var Value + */ + Value *_value; + + +}; + +/** + * End of namespace + */ +} + diff --git a/src/includes.h b/src/includes.h index 0ea9138..4effa90 100644 --- a/src/includes.h +++ b/src/includes.h @@ -69,3 +69,5 @@ #include "stringmember.h" #include "doublemember.h" #include "methodmember.h" +#include "arithmetic.h" + diff --git a/src/value.cpp b/src/value.cpp index 0f6951b..a299f4d 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -43,7 +43,7 @@ Value::Value() /** * Constructor for null ptr - */ +*/ Value::Value(std::nullptr_t value) { // create a null zval @@ -55,7 +55,18 @@ Value::Value(std::nullptr_t value) * Constructor based on integer value * @param value */ -Value::Value(int value) +Value::Value(int16_t value) +{ + // create an integer zval + MAKE_STD_ZVAL(_val); + ZVAL_LONG(_val, value); +} + +/** + * Constructor based on integer value + * @param value + */ +Value::Value(int32_t value) { // create an integer zval MAKE_STD_ZVAL(_val); @@ -66,7 +77,7 @@ Value::Value(int value) * Constructor based on long value * @param value */ -Value::Value(long value) +Value::Value(int64_t value) { // create an integer zval MAKE_STD_ZVAL(_val); @@ -164,14 +175,29 @@ Value::Value(struct _zval_struct *val, bool ref) */ Value::Value(const Value &that) { - // just copy the zval - _val = that._val; - - // and we have one more reference + // how many references does the other object has? + if (Z_REFCOUNT_P(that._val) > 1 && !Z_ISREF_P(that._val)) + { + // there are already multiple variables linked to this value, and it + // is not a reference. this implies that we can not turn this variable + // into a reference, otherwise strange things could happen, we're going + // to create a new zval + ALLOC_ZVAL(_val); + INIT_PZVAL_COPY(_val, that._val); + zval_copy_ctor(_val); + } + else + { + // simply use the same zval + _val = that._val; + } + + // the other object only has one variable using it, or it is already + // a variable by reference, we can safely add one more reference to it + // and make it a variable by reference if it was not already a ref Z_ADDREF_P(_val); - // two value objects are both sharing the same zval, we turn the zval into a reference - // @todo this is not necessarily correct + // make reference Z_SET_ISREF_P(_val); } @@ -207,11 +233,11 @@ Value::~Value() } /** - * Assignment operator + * Move operator * @param value * @return Value */ -Value &Value::operator=(const Value &value) +Value &Value::operator=(Value &&value) { // skip self assignment if (this == &value) return *this; @@ -219,6 +245,8 @@ Value &Value::operator=(const Value &value) // is the object a reference? if (Z_ISREF_P(_val)) { + // @todo difference if the other object is a reference or not? + // the current object is a reference, this means that we should // keep the zval object, and copy the other value into it, get // the current refcount @@ -229,11 +257,33 @@ Value &Value::operator=(const Value &value) // make the copy *_val = *value._val; - zval_copy_ctor(_val); - // restore refcount and reference setting + // restore reference and refcount setting Z_SET_ISREF_TO_P(_val, true); Z_SET_REFCOUNT_P(_val, refcount); + + // how many references did the old variable have? + if (Z_REFCOUNT_P(value._val) > 1) + { + // the other object already had multiple references, this + // implies that many other PHP variables are also referring + // to it, and we still need to store its contents, with one + // reference less + Z_DELREF_P(value._val); + + // and we need to run the copy constructor on the current + // value, because we're making a deep copy + zval_copy_ctor(_val); + } + else + { + // the last and only reference to the other object was + // removed, we no longer need it + FREE_ZVAL(value._val); + + // the other object is no longer valid + value._val = nullptr; + } } else { @@ -241,23 +291,23 @@ Value &Value::operator=(const Value &value) // and only destruct if there are no other references left) zval_ptr_dtor(&_val); - // just copy the zval, and the refcounter + // just copy the zval completely _val = value._val; - // and we have one more reference - Z_ADDREF_P(_val); + // the other object is no longer valid + value._val = nullptr; } - + // update the object return *this; } /** - * Move operator + * Assignment operator * @param value * @return Value */ -Value &Value::operator=(Value &&value) +Value &Value::operator=(const Value &value) { // skip self assignment if (this == &value) return *this; @@ -265,9 +315,6 @@ Value &Value::operator=(Value &&value) // is the object a reference? if (Z_ISREF_P(_val)) { - // @todo difference if the other object is a reference or not? - - // the current object is a reference, this means that we should // keep the zval object, and copy the other value into it, get // the current refcount @@ -278,33 +325,11 @@ Value &Value::operator=(Value &&value) // make the copy *_val = *value._val; + zval_copy_ctor(_val); - // restore reference and refcount setting + // restore refcount and reference setting Z_SET_ISREF_TO_P(_val, true); Z_SET_REFCOUNT_P(_val, refcount); - - // how many references did the old variable have? - if (Z_ISREF_P(value._val) > 1) - { - // the other object already had multiple references, this - // implies that many other PHP variables are also referring - // to it, and we still need to store its contents, with one - // reference less - Z_DELREF_P(value._val); - - // and we need to run the copy constructor on the current - // value, because we're making a deep copy - zval_copy_ctor(_val); - } - else - { - // the last and only reference to the other object was - // removed, we no longer need it - FREE_ZVAL(value._val); - - // the other object is no longer valid - value._val = nullptr; - } } else { @@ -312,12 +337,32 @@ Value &Value::operator=(Value &&value) // and only destruct if there are no other references left) zval_ptr_dtor(&_val); - // just copy the zval completely + // just copy the zval, and the refcounter _val = value._val; - // the other object is no longer valid - value._val = nullptr; + // and we have one more reference + Z_ADDREF_P(_val); } + + // update the object + return *this; +} + +/** + * Assignment operator + * @param value + * @return Value + */ +Value &Value::operator=(int16_t value) +{ + // if this is not a reference variable, we should detach it to implement copy on write + SEPARATE_ZVAL_IF_NOT_REF(&_val); + + // deallocate current zval (without cleaning the zval structure) + zval_dtor(_val); + + // set new value + ZVAL_LONG(_val, value); // update the object return *this; @@ -328,7 +373,7 @@ Value &Value::operator=(Value &&value) * @param value * @return Value */ -Value &Value::operator=(int value) +Value &Value::operator=(int32_t value) { // if this is not a reference variable, we should detach it to implement copy on write SEPARATE_ZVAL_IF_NOT_REF(&_val); @@ -348,7 +393,7 @@ Value &Value::operator=(int value) * @param value * @return Value */ -Value &Value::operator=(long value) +Value &Value::operator=(int64_t value) { // if this is not a reference variable, we should detach it to implement copy on write SEPARATE_ZVAL_IF_NOT_REF(&_val); @@ -464,6 +509,127 @@ Value &Value::operator=(double value) } /** + * Add a value to the object + * @param value + * @return Value + */ +Value &Value::operator+=(const Value &value) { return Arithmetic<std::plus>(this).assign(value); } +Value &Value::operator+=(int16_t value) { return Arithmetic<std::plus>(this).assign(value); } +Value &Value::operator+=(int32_t value) { return Arithmetic<std::plus>(this).assign(value); } +Value &Value::operator+=(int64_t value) { return Arithmetic<std::plus>(this).assign(value); } +Value &Value::operator+=(bool value) { return Arithmetic<std::plus>(this).assign(value); } +Value &Value::operator+=(char value) { return Arithmetic<std::plus>(this).assign(value); } +Value &Value::operator+=(const std::string &value) { return Arithmetic<std::plus>(this).assign(value); } +Value &Value::operator+=(const char *value) { return Arithmetic<std::plus>(this).assign(value); } +Value &Value::operator+=(double value) { return Arithmetic<std::plus>(this).assign(value); } + +/** + * Subtract a value from the object + * @param value + * @return Value + */ +Value &Value::operator-=(const Value &value) { return Arithmetic<std::minus>(this).assign(value); } +Value &Value::operator-=(int16_t value) { return Arithmetic<std::minus>(this).assign(value); } +Value &Value::operator-=(int32_t value) { return Arithmetic<std::minus>(this).assign(value); } +Value &Value::operator-=(int64_t value) { return Arithmetic<std::minus>(this).assign(value); } +Value &Value::operator-=(bool value) { return Arithmetic<std::minus>(this).assign(value); } +Value &Value::operator-=(char value) { return Arithmetic<std::minus>(this).assign(value); } +Value &Value::operator-=(const std::string &value) { return Arithmetic<std::minus>(this).assign(value); } +Value &Value::operator-=(const char *value) { return Arithmetic<std::minus>(this).assign(value); } +Value &Value::operator-=(double value) { return Arithmetic<std::minus>(this).assign(value); } + +/** + * Multiply the object with a certain value + * @param value + * @return Value + */ +Value &Value::operator*=(const Value &value) { return Arithmetic<std::multiplies>(this).assign(value); } +Value &Value::operator*=(int16_t value) { return Arithmetic<std::multiplies>(this).assign(value); } +Value &Value::operator*=(int32_t value) { return Arithmetic<std::multiplies>(this).assign(value); } +Value &Value::operator*=(int64_t value) { return Arithmetic<std::multiplies>(this).assign(value); } +Value &Value::operator*=(bool value) { return Arithmetic<std::multiplies>(this).assign(value); } +Value &Value::operator*=(char value) { return Arithmetic<std::multiplies>(this).assign(value); } +Value &Value::operator*=(const std::string &value) { return Arithmetic<std::multiplies>(this).assign(value); } +Value &Value::operator*=(const char *value) { return Arithmetic<std::multiplies>(this).assign(value); } +Value &Value::operator*=(double value) { return Arithmetic<std::multiplies>(this).assign(value); } + +/** + * Divide the object with a certain value + * @param value + * @return Value + */ +Value &Value::operator/=(const Value &value) { return Arithmetic<std::divides>(this).assign(value); } +Value &Value::operator/=(int16_t value) { return Arithmetic<std::divides>(this).assign(value); } +Value &Value::operator/=(int32_t value) { return Arithmetic<std::divides>(this).assign(value); } +Value &Value::operator/=(int64_t value) { return Arithmetic<std::divides>(this).assign(value); } +Value &Value::operator/=(bool value) { return Arithmetic<std::divides>(this).assign(value); } +Value &Value::operator/=(char value) { return Arithmetic<std::divides>(this).assign(value); } +Value &Value::operator/=(const std::string &value) { return Arithmetic<std::divides>(this).assign(value); } +Value &Value::operator/=(const char *value) { return Arithmetic<std::divides>(this).assign(value); } +Value &Value::operator/=(double value) { return Arithmetic<std::divides>(this).assign(value); } + +/** + * Assignment operator + * @param value + * @return Value + */ +Value Value::operator+(const Value &value) { return Arithmetic<std::plus>(this).apply(value); } +Value Value::operator+(int16_t value) { return Arithmetic<std::plus>(this).apply(value); } +Value Value::operator+(int32_t value) { return Arithmetic<std::plus>(this).apply(value); } +Value Value::operator+(int64_t value) { return Arithmetic<std::plus>(this).apply(value); } +Value Value::operator+(bool value) { return Arithmetic<std::plus>(this).apply(value); } +Value Value::operator+(char value) { return Arithmetic<std::plus>(this).apply(value); } +Value Value::operator+(const std::string &value) { return Arithmetic<std::plus>(this).apply(value); } +Value Value::operator+(const char *value) { return Arithmetic<std::plus>(this).apply(value); } +Value Value::operator+(double value) { return Arithmetic<std::plus>(this).apply(value); } + +/** + * Subtraction operator + * @param value + * @return Value + */ +Value Value::operator-(const Value &value) { return Arithmetic<std::minus>(this).apply(value); } +Value Value::operator-(int16_t value) { return Arithmetic<std::minus>(this).apply(value); } +Value Value::operator-(int32_t value) { return Arithmetic<std::minus>(this).apply(value); } +Value Value::operator-(int64_t value) { return Arithmetic<std::minus>(this).apply(value); } +Value Value::operator-(bool value) { return Arithmetic<std::minus>(this).apply(value); } +Value Value::operator-(char value) { return Arithmetic<std::minus>(this).apply(value); } +Value Value::operator-(const std::string &value) { return Arithmetic<std::minus>(this).apply(value); } +Value Value::operator-(const char *value) { return Arithmetic<std::minus>(this).apply(value); } +Value Value::operator-(double value) { return Arithmetic<std::minus>(this).apply(value); } + +/** + * Multiplication operator + * @param value + * @return Value + */ +Value Value::operator*(const Value &value) { return Arithmetic<std::multiplies>(this).apply(value); } +Value Value::operator*(int16_t value) { return Arithmetic<std::multiplies>(this).apply(value); } +Value Value::operator*(int32_t value) { return Arithmetic<std::multiplies>(this).apply(value); } +Value Value::operator*(int64_t value) { return Arithmetic<std::multiplies>(this).apply(value); } +Value Value::operator*(bool value) { return Arithmetic<std::multiplies>(this).apply(value); } +Value Value::operator*(char value) { return Arithmetic<std::multiplies>(this).apply(value); } +Value Value::operator*(const std::string &value) { return Arithmetic<std::multiplies>(this).apply(value); } +Value Value::operator*(const char *value) { return Arithmetic<std::multiplies>(this).apply(value); } +Value Value::operator*(double value) { return Arithmetic<std::multiplies>(this).apply(value); } + +/** + * Division operator + * @param value + * @return Value + */ +Value Value::operator/(const Value &value) { return Arithmetic<std::divides>(this).apply(value); } +Value Value::operator/(int16_t value) { return Arithmetic<std::divides>(this).apply(value); } +Value Value::operator/(int32_t value) { return Arithmetic<std::divides>(this).apply(value); } +Value Value::operator/(int64_t value) { return Arithmetic<std::divides>(this).apply(value); } +Value Value::operator/(bool value) { return Arithmetic<std::divides>(this).apply(value); } +Value Value::operator/(char value) { return Arithmetic<std::divides>(this).apply(value); } +Value Value::operator/(const std::string &value) { return Arithmetic<std::divides>(this).apply(value); } +Value Value::operator/(const char *value) { return Arithmetic<std::divides>(this).apply(value); } +Value Value::operator/(double value) { return Arithmetic<std::divides>(this).apply(value); } + + +/** * The type of object * @return Type */ @@ -488,8 +654,8 @@ Value &Value::setType(Type type) // run the conversion switch (type) { case nullType: convert_to_null(_val); break; - case longType: convert_to_long(_val); break; - case decimalType: convert_to_double(_val); break; + case numericType: convert_to_long(_val); break; + case floatType: convert_to_double(_val); break; case boolType: convert_to_boolean(_val); break; case arrayType: convert_to_array(_val); break; case objectType: convert_to_object(_val); break; @@ -540,13 +706,15 @@ Value Value::clone(Type type) const * Retrieve the value as integer * @return long */ -long Value::longValue() const +long Value::numericValue() const { // already a long? - if (isLong()) return Z_LVAL_P(_val); + if (isNumeric()) return Z_LVAL_P(_val); + + std::cout << "clone to numeric" << std::endl; // make a clone - return clone(longType).longValue(); + return clone(numericType).numericValue(); } /** @@ -592,13 +760,13 @@ const char *Value::rawValue() const * Retrieve the value as decimal * @return double */ -double Value::decimalValue() const +double Value::floatValue() const { // already a double - if (isDecimal()) return Z_DVAL_P(_val); + if (isFloat()) return Z_DVAL_P(_val); // make a clone - return clone(decimalType).decimalValue(); + return clone(floatType).floatValue(); } /** @@ -617,7 +785,7 @@ int Value::size() const Value copy(*this); // convert the copy to a string - copy.setType(decimalType); + copy.setType(stringType); // return the string size return copy.size(); @@ -807,18 +975,10 @@ HashMember<std::string> Value::operator[](const char *key) return HashMember<std::string>(this, key); } -/** - * Array access operator - * This can be used for adding a record to the array - * Be aware: if the 'this' object is not already an array, it will be converted into one! - * @param key - * @return Value - */ -//Value Value::operator[]() -//{ -// -// -//} +int Value::refcount() +{ + return Z_REFCOUNT_P(_val); +} /** * End of namespace diff --git a/tests/simple/simple.cpp b/tests/simple/simple.cpp index e90fe55..69cf9ce 100644 --- a/tests/simple/simple.cpp +++ b/tests/simple/simple.cpp @@ -15,6 +15,64 @@ */ using namespace std; + +Php::Value bubblesort(Php::Parameters ¶ms) +{ + cout << "start bubblesort" << endl; + + // the array that was passed + Php::Value array(params[0]); + + cout << "go return" << endl; + + return array; + + // size of the array + int size = array.size(); + + cout << "convert to native" << endl; + + int *x = new int[size]; + for (int i=0; i<size; i++) x[i] = array[i]; + + cout << "converted" << endl; + + + // outer loop + for (int i=0; i<size; i++) + { + // left value + int left = x[i]; +// cout << "left: " << left << endl; + + // inner loop + for (int j=i+1; j<size; j++) + { + // right value + int right = x[j]; + + if (left < right) continue; + + // swap values + x[i] = right; + x[j] = left; + left = right; + } + } + + cout << "algorithm end" << endl; + + Php::Value r; + + for (int i=0; i<size; i++) r[i] = x[i]; + + + delete[] x; + + // done + return r; +} + /** * Our own "my_plus" function that will be available in PHP * @param environment @@ -23,22 +81,29 @@ using namespace std; */ static Php::Value my_plus(Php::Environment &env, Php::Parameters ¶ms) { - int p1 = params[0]; - int p2 = params[1]; - return p1 + p2; - - cout << "global g1: " << env["g1"].stringValue() << endl; - cout << "global g2: " << env["g2"].stringValue() << endl; + Php::Value r(0); - Php::Global g(env["g3"]); + for (unsigned int i=0; i<params.size(); i++) r += params[i]; - g = "zo kan het ook"; + return r; - string output = env.call("strtoupper","test in lowercase"); - cout << "output: " << output << endl; - - return p1 + p2; +// int p1 = params[0]; +// int p2 = params[1]; +// return p1 + p2; +// +// cout << "global g1: " << env["g1"].stringValue() << endl; +// cout << "global g2: " << env["g2"].stringValue() << endl; +// +// Php::Global g(env["g3"]); +// +// g = "zo kan het ook"; +// +// string output = env.call("strtoupper","test in lowercase"); +// +// cout << "output: " << output << endl; +// +// return p1 + p2; } /** @@ -88,17 +153,21 @@ extern "C" // export the "get_module" function that will be called by the Zend engine PHPCPP_EXPORT void *get_module() { + cout << "call get_module()" << endl; + // create extension static Php::Extension extension("simple","1.0"); // define the functions extension.add("my_plus", my_plus, { - Php::ByVal("a", Php::longType), - Php::ByVal("b", Php::longType) +// Php::ByVal("a", Php::numericType), +// Php::ByVal("b", Php::numericType) // Php::ByVal("c", "MyClass"), // Php::ByRef("d", Php::stringType) }); + extension.add("bubblesort", bubblesort); + Php::Method<MyCustomClass> x(&MyCustomClass::myMethod); // define classes diff --git a/tests/simple/simple.php b/tests/simple/simple.php index 345c139..5f3bed7 100644 --- a/tests/simple/simple.php +++ b/tests/simple/simple.php @@ -31,26 +31,57 @@ //echo("g2: $g2\n"); //echo("g3: $g3\n"); - -if (class_exists("my_class")) echo("Warempel, de class bestaat\n"); - -class my_extended_class extends my_class +function slowsort($input) { - public function myMethod($val) + $size = count($input); + for ($i=0; $i<$size; $i++) { - echo($this->a."\n"); - echo($this->b."\n"); - echo("hoi\n"); - - parent::myMethod($val); + $left = $input[$i]; + for ($j=$i+1; $j<$size; $j++) + { + $right = $input[$j]; + + if ($left < $right) continue; + + // swap values + $input[$i] = $right; + $input[$j] = $left; + $left = $right; + } } - + return $input; } -$x = new my_extended_class(); -$x->myMethod(123); +//if (class_exists("my_class")) echo("Warempel, de class bestaat\n"); +// +//class my_extended_class extends my_class +//{ +// public function myMethod($val) +// { +// echo($this->a."\n"); +// echo($this->b."\n"); +// echo("hoi\n"); +// +// parent::myMethod($val); +// } +// +//} +// +//$x = new my_extended_class(); +//$x->myMethod(123); + +//echo(my_plus(1,2,3,4)."\n"); + +$array = array(); +for ($i=0; $i<10000; $i++) $array[] = rand(); + +//$array = array(1,2,3); + +//print_r($array); +bubblesort($array); + +print_r($array); -my_plus(1,2,3,4); //echo("my_class::a = ".$x->a."\n"); //echo("my_class::b = ".$x->b."\n"); |