summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-04-01 16:39:52 +0200
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-04-01 16:39:52 +0200
commit61ded13eaa25b332208cd659c5c844890db0cb57 (patch)
treec50f5319fc975faf80e3a7a41a9b8cdb36656bec
parent777949f8751ded6e56140bb513c6b93e4d5c3f08 (diff)
much simpler implementation of hash member, i do not understand why i first used this complicated zval wrapping implementation, fixes problems reported in issue #56
-rw-r--r--include/classbase.h8
-rw-r--r--include/global.h8
-rw-r--r--include/hashmember.h181
-rw-r--r--include/hashparent.h92
-rw-r--r--include/value.h29
-rw-r--r--phpcpp.h1
-rw-r--r--src/includes.h1
-rw-r--r--src/value.cpp30
8 files changed, 240 insertions, 110 deletions
diff --git a/include/classbase.h b/include/classbase.h
index 4e03f1c..f4a6f22 100644
--- a/include/classbase.h
+++ b/include/classbase.h
@@ -94,10 +94,10 @@ public:
ClassBase(const ClassBase &that) :
_name(that._name),
_type(that._type),
+ _entry(that._entry),
_methods(that._methods),
_members(that._members),
- _properties(that._properties),
- _entry(nullptr) {}
+ _properties(that._properties) {}
/**
* Move constructor
@@ -106,10 +106,10 @@ public:
ClassBase(ClassBase &&that) :
_name(std::move(that._name)),
_type(that._type),
+ _entry(that._entry),
_methods(std::move(that._methods)),
_members(std::move(that._members)),
- _properties(std::move(that._properties)),
- _entry(that._entry)
+ _properties(std::move(that._properties))
{
// other entry are invalid now (not that it is used..., class objects are
// only moved during extension setup, when the entry pointer has not yet
diff --git a/include/global.h b/include/global.h
index 4531f77..ae54212 100644
--- a/include/global.h
+++ b/include/global.h
@@ -106,13 +106,13 @@ public:
* @param value Value to set
* @return Value The value that was set
*/
- virtual const Value &set(int index, const Value &value) override
+ virtual void set(int index, const Value &value) override
{
// update current object
update();
// call base
- return Value::set(index, value);
+ Value::set(index, value);
}
/**
@@ -123,13 +123,13 @@ public:
* @param value Value to set
* @return Value The value that was set
*/
- virtual const Value &set(const char *key, int size, const Value &value) override
+ virtual void set(const char *key, int size, const Value &value) override
{
// update current object
update();
// call base
- return Value::set(key, size, value);
+ Value::set(key, size, value);
}
diff --git a/include/hashmember.h b/include/hashmember.h
index 0bb5a4c..6603b57 100644
--- a/include/hashmember.h
+++ b/include/hashmember.h
@@ -24,26 +24,20 @@ namespace Php {
class Value;
/**
- * Base class for hash members
- */
-class HashMemberBase
-{
-public:
- /**
- * Assignment operator
- * @param param value
- */
- virtual void assign(const Value &value) = 0;
-};
-
-/**
* Member class
*/
template <typename Type>
-class HashMember : public HashMemberBase
+class HashMember : private HashParent
{
public:
/**
+ * Constructor
+ * @param parent
+ * @param index
+ */
+ HashMember(HashParent *parent, Type index) : _parent(parent), _index(index) {}
+
+ /**
* Destructor
*/
virtual ~HashMember() {}
@@ -55,9 +49,9 @@ public:
*/
HashMember &operator=(const Value &value)
{
- // assign the property
- assign(value);
-
+ // set new value in the parent
+ _parent->set(_index, value);
+
// done
return *this;
}
@@ -69,7 +63,8 @@ public:
*/
bool exists() const
{
- return _base.contains(_index);
+ // ask the parent
+ return _parent->contains(_index);
}
/**
@@ -78,7 +73,7 @@ public:
*/
Value value() const
{
- return _base.get(_index);
+ return _parent->get(_index);
}
/**
@@ -87,7 +82,7 @@ public:
*/
operator Value () const
{
- return _base.get(_index);
+ return _parent->get(_index);
}
/**
@@ -96,7 +91,7 @@ public:
*/
operator int16_t () const
{
- return _base.get(_index).numericValue();
+ return value().numericValue();
}
/**
@@ -105,7 +100,7 @@ public:
*/
operator int32_t () const
{
- return _base.get(_index).numericValue();
+ return value().numericValue();
}
/**
@@ -114,7 +109,7 @@ public:
*/
operator int64_t () const
{
- return _base.get(_index).numericValue();
+ return value().numericValue();
}
/**
@@ -123,7 +118,7 @@ public:
*/
operator bool () const
{
- return _base.get(_index).boolValue();
+ return value().boolValue();
}
/**
@@ -132,7 +127,7 @@ public:
*/
operator std::string () const
{
- return _base.get(_index).stringValue();
+ return value().stringValue();
}
/**
@@ -141,7 +136,7 @@ public:
*/
operator const char * () const
{
- return _base.get(_index).rawValue();
+ return value().rawValue();
}
/**
@@ -150,7 +145,7 @@ public:
*/
operator double () const
{
- return _base.get(_index).decimalValue();
+ return value().floatValue();
}
/**
@@ -161,7 +156,7 @@ public:
*/
HashMember<int> operator[](int index)
{
- return _base.get(_index)[index].add(this);
+ return HashMember<int>(this, index);
}
/**
@@ -172,7 +167,7 @@ public:
*/
HashMember<std::string> operator[](const std::string &key)
{
- return _base.get(_index)[key].add(this);
+ return HashMember<std::string>(this, key);
}
/**
@@ -183,11 +178,11 @@ public:
*/
HashMember<std::string> operator[](const char *key)
{
- return _base.get(_index)[key].add(this);
+ return HashMember<std::string>(this, key);
}
/**
- * Add a value to the object
+ * Add a value to the object (or other arithmetric operators)
* @param value
* @return HashMember
*/
@@ -373,70 +368,124 @@ public:
Value operator()(Value param0, Value param1, Value param2, Value param3, Value param4, Value param5, Value param6, Value param7, Value param8) { return value()(param0, param1, param2, param3, param4, param5, param6, param7, param8); }
Value operator()(Value param0, Value param1, Value param2, Value param3, Value param4, Value param5, Value param6, Value param7, Value param8, Value param9) { return value()(param0, param1, param2, param3, param4, param5, param6, param7, param8, param9); }
-private:
/**
- * Constructor
- * @param base Base value
- * @param index Index in the array
+ * Check if a certain key exists in the array/object
+ * @param key
+ * @return bool
*/
- HashMember(struct _zval_struct *base, Type index) : _base(base, true), _index(index) {}
+ virtual bool contains(const std::string &key) const override
+ {
+ // object must exist, and the value must contain the key
+ return exists() && value().contains(key);
+ }
- // @todo add move constructor
+ /**
+ * Check if a certain index exists in the array/object
+ * @param key
+ * @return bool
+ */
+ virtual bool contains(int index) const override
+ {
+ // object must exist, and the value must contain the key
+ return exists() && value().contains(index);
+ }
/**
- * Protected copy constructor
- * @param value Other element
+ * Retrieve the value at a string index
+ * @param key
+ * @return Value
*/
- HashMember(const HashMember<Type> &member) : _base(member._base._val, true), _index(member._index), _parent(member._parent) {}
+ virtual Value get(const std::string &key) const override
+ {
+ // return null if it does not exist
+ if (!exists()) return nullptr;
+
+ // ask the value
+ return value().get(key);
+ }
/**
- * Add parent
- * @param parent
+ * Retrieve the value at a numeric index
+ * @param index
+ * @return Value
*/
- HashMember &add(HashMemberBase *parent)
+ virtual Value get(int index) const override
{
- _parent = parent;
- return *this;
+ // return null if it does not exist
+ if (!exists()) return nullptr;
+
+ // ask the value
+ return value().get(index);
}
-
+
/**
- * Implementation of the assign method
+ * Overwrite the value at a certain string index
+ * @param key
* @param value
*/
- virtual void assign(const Value &value) override
+ virtual void set(const std::string &key, const Value &value) override
{
- // set property in parent array
- _base.set(_index, value);
-
- // if there is a parent, it should sets its value too
- if (_parent) _parent->assign(_base);
+ // get the current value
+ Value current(this->value());
+
+ // add the value
+ current[key] = value;
+
+ // pass this to the base
+ _parent->set(_index, current);
}
/**
- * The original index
- * @var Type
+ * Overwrite the value at a certain numeric index
+ * @param index
+ * @param value
*/
- Type _index;
-
+ virtual void set(int index, const Value &value) override
+ {
+ // get the current value
+ Value current(value());
+
+ // add the value
+ current[index] = value;
+
+ // pass this to the base
+ _parent->set(_index, current);
+ }
+
+protected:
+ /**
+ * Protected copy constructor
+ * @param value Other element
+ */
+ HashMember(const HashMember<Type> &member) : _parent(member._parent), _index(member._index) {}
+
+ /**
+ * Move constructor
+ * @param value Other element
+ */
+// HashMember(HashMember<Type> &&member) :
+// _parent(std::move(member._parent)), _index(std::move(member._index)) {}
+
+private:
/**
* Base value
- * @var Value
+ * @var
*/
- Value _base;
+ HashParent *_parent;
/**
- * Parent member (in case of nested members)
- * @var HashMemberBase
+ * The original index
+ * @var Type
*/
- HashMemberBase *_parent = nullptr;
+ Type _index;
/**
- * Only value objects may construct members
+ * Friend classes
*/
- friend class Value;
- friend class Base;
- friend class HashMember<int>;
friend class HashMember<std::string>;
+ friend class HashMember<int>;
+ friend class Base;
+ friend class Value;
};
/**
diff --git a/include/hashparent.h b/include/hashparent.h
new file mode 100644
index 0000000..4c2ee68
--- /dev/null
+++ b/include/hashparent.h
@@ -0,0 +1,92 @@
+/**
+ * HashParent.h
+ *
+ * Interface that is implemented by all objects that can be accessed with
+ * array-access variables ([]). When the value of a hash-member is changed,
+ * it will call one of the methods from this class to set the new property
+ *
+ * This is an internal class that you normally not need when writing
+ * extensions. It is used by the PHP-CPP library when you use constructs
+ * like value["x"]["y"] = 10;
+ *
+ * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
+ * @copyright 2014 Copernica BV
+ */
+
+/**
+ * Set up namespace
+ */
+namespace Php {
+
+/**
+ * Forwards
+ */
+class Value;
+
+/**
+ * Class definition
+ */
+class HashParent
+{
+protected:
+ /**
+ * Protected constructor - users should not instantiate HashParent
+ * objects themselved. Use a Value object instead.
+ */
+ HashParent() {}
+
+public:
+ /**
+ * Destructor
+ */
+ virtual ~HashParent() {}
+
+ /**
+ * Check if a certain key exists in the array/object
+ * @param key
+ * @return bool
+ */
+ virtual bool contains(const std::string &key) const = 0;
+
+ /**
+ * Check if a certain index exists in the array/object
+ * @param key
+ * @return bool
+ */
+ virtual bool contains(int index) const = 0;
+
+ /**
+ * Retrieve the value at a string index
+ * @param key
+ * @return Value
+ */
+ virtual Value get(const std::string &key) const = 0;
+
+ /**
+ * Retrieve the value at a numeric index
+ * @param index
+ * @return Value
+ */
+ virtual Value get(int index) const = 0;
+
+ /**
+ * Overwrite the value at a certain string index
+ * @param key
+ * @param value
+ */
+ virtual void set(const std::string &key, const Value &value) = 0;
+
+ /**
+ * Overwrite the value at a certain numeric index
+ * @param index
+ * @param value
+ */
+ virtual void set(int index, const Value &value) = 0;
+
+};
+
+/**
+ * End namespace
+ */
+}
+
diff --git a/include/value.h b/include/value.h
index 34ac510..2e1dd84 100644
--- a/include/value.h
+++ b/include/value.h
@@ -38,7 +38,7 @@ template <class Type> class HashMember;
/**
* Class definition
*/
-class Value
+class Value : private HashParent
{
public:
/**
@@ -543,14 +543,14 @@ public:
* @param index
* @return bool
*/
- bool contains(int index) const;
+ virtual bool contains(int index) const override;
/**
* Is a certain key set in the array
* @param key
* @return bool
*/
- bool contains(const std::string &key) const
+ virtual bool contains(const std::string &key) const override
{
return contains(key.c_str(), key.size());
}
@@ -671,7 +671,7 @@ public:
* @param index
* @return Value
*/
- Value get(int index) const;
+ virtual Value get(int index) const override;
/**
* Get access to a certain assoc member
@@ -686,7 +686,7 @@ public:
* @param key
* @return Value
*/
- Value get(const std::string &key) const
+ virtual Value get(const std::string &key) const override
{
return get(key.c_str(), key.size());
}
@@ -698,7 +698,7 @@ public:
* @param value Value to set
* @return Value The value that was set
*/
- virtual const Value &set(int index, const Value &value);
+ virtual void set(int index, const Value &value) override;
/**
* Set a certain property
@@ -706,20 +706,18 @@ public:
* @param key Key of the property to set
* @param size Size of the key
* @param value Value to set
- * @return Value The value that was set
*/
- virtual const Value &set(const char *key, int size, const Value &value);
+ virtual void set(const char *key, int size, const Value &value);
/**
* Set a certain property
* Calling this method will turn the object into an array
* @param key Key to set
* @param value Value to set
- * @return Value The value that was set
*/
- const Value &set(const char *key, const Value &value)
+ void set(const char *key, const Value &value)
{
- return set(key, strlen(key), value);
+ set(key, strlen(key), value);
}
/**
@@ -727,9 +725,8 @@ public:
* Calling this method will turn the object into an array
* @param key Key to set
* @param value Value to set
- * @return Value The value that was set
*/
- const Value &set(const std::string &key, const Value &value)
+ virtual void set(const std::string &key, const Value &value) override
{
return set(key.c_str(), key.size(), value);
}
@@ -919,9 +916,8 @@ protected:
*
* @param index Index of the property to set
* @param value Value to set
- * @return Value The value that was set
*/
- const Value &setRaw(int index, const Value &value);
+ void setRaw(int index, const Value &value);
/**
* Set a certain property without any checks (you must already know for
@@ -931,9 +927,8 @@ protected:
* @param key Key of the property to set
* @param size Size of the key
* @param value Value to set
- * @return Value The value that was set
*/
- const Value &setRaw(const char *key, int size, const Value &value);
+ void setRaw(const char *key, int size, const Value &value);
/**
* Internal helper method to create an iterator
diff --git a/phpcpp.h b/phpcpp.h
index 86828a4..f1c806b 100644
--- a/phpcpp.h
+++ b/phpcpp.h
@@ -54,6 +54,7 @@
#include <phpcpp/exception.h>
#include <phpcpp/streams.h>
#include <phpcpp/type.h>
+#include <phpcpp/hashparent.h>
#include <phpcpp/value.h>
#include <phpcpp/valueiterator.h>
#include <phpcpp/array.h>
diff --git a/src/includes.h b/src/includes.h
index 50cb65f..f06f686 100644
--- a/src/includes.h
+++ b/src/includes.h
@@ -42,6 +42,7 @@
#include "../include/exception.h"
#include "../include/streams.h"
#include "../include/type.h"
+#include "../include/hashparent.h"
#include "../include/value.h"
#include "../include/valueiterator.h"
#include "../include/array.h"
diff --git a/src/value.cpp b/src/value.cpp
index 26c753f..6684bd0 100644
--- a/src/value.cpp
+++ b/src/value.cpp
@@ -1741,7 +1741,7 @@ Value Value::get(const char *key, int size) const
* @param value
* @return Value
*/
-const Value &Value::setRaw(int index, const Value &value)
+void Value::setRaw(int index, const Value &value)
{
// if this is not a reference variable, we should detach it to implement copy on write
SEPARATE_ZVAL_IF_NOT_REF(&_val);
@@ -1751,19 +1751,15 @@ const Value &Value::setRaw(int index, const Value &value)
// the variable has one more reference (the array entry)
Z_ADDREF_P(value._val);
-
- // done
- return value;
}
-
/**
* Set a certain property
* @param index
* @param value
* @return Value
*/
-const Value &Value::set(int index, const Value &value)
+void Value::set(int index, const Value &value)
{
// the current value
zval **current;
@@ -1772,14 +1768,14 @@ const Value &Value::set(int index, const Value &value)
if (isArray() && zend_hash_index_find(Z_ARRVAL_P(_val), index, (void **)&current) != FAILURE)
{
// skip if nothing is going to change
- if (value._val == *current) return value;
+ if (value._val == *current) return;
}
// must be an array
setType(Type::Array);
// set property
- return setRaw(index, value);
+ setRaw(index, value);
}
/**
@@ -1787,9 +1783,8 @@ const Value &Value::set(int index, const Value &value)
* @param key
* @param size
* @param value
- * @return Value
*/
-const Value &Value::setRaw(const char *key, int size, const Value &value)
+void Value::setRaw(const char *key, int size, const Value &value)
{
// is this an object?
if (isObject())
@@ -1817,9 +1812,6 @@ const Value &Value::setRaw(const char *key, int size, const Value &value)
// the variable has one more reference (the array entry)
Z_ADDREF_P(value._val);
}
-
- // done
- return value;
}
/**
@@ -1829,7 +1821,7 @@ const Value &Value::setRaw(const char *key, int size, const Value &value)
* @param value
* @return Value
*/
-const Value &Value::set(const char *key, int size, const Value &value)
+void Value::set(const char *key, int size, const Value &value)
{
// the current value
zval **current;
@@ -1838,14 +1830,14 @@ const Value &Value::set(const char *key, int size, const Value &value)
if (isArray() && zend_hash_find(Z_ARRVAL_P(_val), key, size + 1, (void **)&current) != FAILURE)
{
// skip if nothing is going to change
- if (value._val == *current) return value;
+ if (value._val == *current) return;
}
// this should be an object or an array
if (!isObject()) setType(Type::Array);
// done
- return setRaw(key, size, value);
+ setRaw(key, size, value);
}
/**
@@ -1856,7 +1848,7 @@ const Value &Value::set(const char *key, int size, const Value &value)
*/
HashMember<int> Value::operator[](int index)
{
- return HashMember<int>(_val, index);
+ return HashMember<int>(this, index);
}
/**
@@ -1867,7 +1859,7 @@ HashMember<int> Value::operator[](int index)
*/
HashMember<std::string> Value::operator[](const std::string &key)
{
- return HashMember<std::string>(_val, key);
+ return HashMember<std::string>(this, key);
}
/**
@@ -1878,7 +1870,7 @@ HashMember<std::string> Value::operator[](const std::string &key)
*/
HashMember<std::string> Value::operator[](const char *key)
{
- return HashMember<std::string>(_val, key);
+ return HashMember<std::string>(this, key);
}
/**