summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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");