summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2013-10-20 14:25:24 -0700
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2013-10-20 14:25:24 -0700
commit87462517ca9ae8ece9ef3f97d3f105c72e74a4d7 (patch)
treeb1f53acdcb1e33a774cfea6e17b950c6db54f8a9
parent61ba30d716dab670a5f2ed0ee2f6650375b2058d (diff)
long types have been replaced with int16, int32 and int64 types to make code more readable and easier portable between architectures
longType and decimalType have been replace by numericType and floatType Many arithmetic operators have been added to the value class Solved various issues with copying and moving value objects
-rw-r--r--include/hashmember.h26
-rw-r--r--include/type.h4
-rw-r--r--include/value.h267
-rw-r--r--src/arithmetic.h286
-rw-r--r--src/includes.h2
-rw-r--r--src/value.cpp304
-rw-r--r--tests/simple/simple.cpp97
-rw-r--r--tests/simple/simple.php59
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 &params)
+{
+ 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 &params)
{
- 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");