summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-12 12:35:14 +0100
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-12 12:35:14 +0100
commitf8775b64f67cc464e024cf79cd98eed30c659d25 (patch)
treee38670c0a68d8fcc8e4e9d819c0a2fb2c27659d9
parent147f9395449db7fcb32957ae840017cff2740831 (diff)
implemented magic __compare() method
-rw-r--r--include/base.h14
-rw-r--r--include/class.h16
-rw-r--r--include/classbase.h16
-rw-r--r--include/interface.h12
-rw-r--r--include/type.h2
-rw-r--r--src/base.cpp22
-rw-r--r--src/classbase.cpp51
7 files changed, 131 insertions, 2 deletions
diff --git a/include/base.h b/include/base.h
index 6541549..e99023b 100644
--- a/include/base.h
+++ b/include/base.h
@@ -218,6 +218,20 @@ public:
* @return bool
*/
virtual bool __toBool();
+
+ /**
+ * Compare the object with a different object of the same type
+ *
+ * This method should return 0 if both objects are equal, a negative value
+ * if the 'this' object is smaller, and a positive value if the 'this'
+ * object is bigger.
+ *
+ * The passed in object is an instance of base
+ *
+ * @param that Object to compare with
+ * @return int
+ */
+ virtual bool __compare(const Base &that) const;
private:
diff --git a/include/class.h b/include/class.h
index 6bcefda..eabcec6 100644
--- a/include/class.h
+++ b/include/class.h
@@ -185,6 +185,22 @@ private:
}
/**
+ * Compare two objects
+ * @param object1
+ * @param object2
+ * @return int
+ */
+ virtual int compare(Base *object1, Base *object2) const override
+ {
+ // cast to the actual implementation type
+ T *t1 = (T *)object1;
+ T *t2 = (T *)object2;
+
+ // compare the two objects
+ return t1->__compare(*t2);
+ }
+
+ /**
* Namespaces have access to the private base class
*/
friend class Namespace;
diff --git a/include/classbase.h b/include/classbase.h
index da027ab..01f1d55 100644
--- a/include/classbase.h
+++ b/include/classbase.h
@@ -108,6 +108,14 @@ public:
virtual Base *clone(Base *orig) const = 0;
/**
+ * Compare two objects
+ * @param object1
+ * @param object2
+ * @return int
+ */
+ virtual int compare(Base *object1, Base *object2) const = 0;
+
+ /**
* Is this a traversable class?
* @return bool
*/
@@ -383,6 +391,14 @@ private:
static int cast(struct _zval_struct *object, struct _zval_struct *retval, int type);
/**
+ * Function to compare two objects
+ * @param object1
+ * @param object2
+ * @return int
+ */
+ static int compare(struct _zval_struct *object1, struct _zval_struct *object2);
+
+ /**
* Name of the class
* @var string
*/
diff --git a/include/interface.h b/include/interface.h
index bdff75d..52d1a97 100644
--- a/include/interface.h
+++ b/include/interface.h
@@ -71,6 +71,18 @@ private:
}
/**
+ * Compare two objects
+ * @param object1
+ * @param object2
+ * @return int
+ */
+ virtual int compare(Base *object1, Base *object2) const override
+ {
+ // this is never called for interfaces
+ return 0;
+ }
+
+ /**
* Namespaces have access to the private base class
*/
friend class Namespace;
diff --git a/include/type.h b/include/type.h
index e5ebeda..bec0fd5 100644
--- a/include/type.h
+++ b/include/type.h
@@ -21,7 +21,7 @@ enum class Type : unsigned char {
Null = 0,
Numeric = 1,
Float = 2,
- Boolean = 3,
+ Bool = 3,
Array = 4,
Object = 5,
String = 6,
diff --git a/src/base.cpp b/src/base.cpp
index a9faac3..a77b30f 100644
--- a/src/base.cpp
+++ b/src/base.cpp
@@ -256,6 +256,28 @@ bool Base::__toBool()
}
/**
+ * Compare the object with a different object of the same type
+ *
+ * This method should return 0 if both objects are equal, a negative value
+ * if the 'this' object is smaller, and a positive value if the 'this'
+ * object is bigger.
+ *
+ * The passed in object is an instance of base
+ *
+ * @param that Object to compare with
+ * @return int
+ */
+bool Base::__compare(const Base &that) const
+{
+ // throw an exception that will be caught in the ClassBase class,
+ // so that the default implementation of the function can be called
+ throw NotImplemented();
+
+ // unreachable code
+ return 1;
+}
+
+/**
* End namespace
*/
}
diff --git a/src/classbase.cpp b/src/classbase.cpp
index 460bae3..f7d8d94 100644
--- a/src/classbase.cpp
+++ b/src/classbase.cpp
@@ -285,6 +285,9 @@ zend_object_handlers *ClassBase::objectHandlers()
// handler to cast to a different type
handlers.cast_object = &ClassBase::cast;
+ // method to compare two objects
+ handlers.compare_objects = &ClassBase::compare;
+
// remember that object is now initialized
initialized = true;
@@ -293,6 +296,52 @@ zend_object_handlers *ClassBase::objectHandlers()
}
/**
+ * Function to compare two objects
+ * @param object1
+ * @param object2
+ * @return int
+ */
+int ClassBase::compare(zval *object1, zval *object2)
+{
+ // prevent exceptions
+ try
+ {
+ // retrieve the class entry linked to this object
+ auto *entry = zend_get_class_entry(object1);
+
+ // other object must be of the same type
+ if (entry != zend_get_class_entry(object2)) throw NotImplemented();
+
+ // we need the C++ class meta-information object
+ ClassBase *meta = cpp_class(entry);
+
+ // get the base objects
+ Base *base1 = cpp_object(object1);
+ Base *base2 = cpp_object(object2);
+
+ // run the compare method
+ return meta->compare(base1, base2);
+ }
+ catch (const NotImplemented &exception)
+ {
+ // it was not implemented, do we have a default?
+ if (!std_object_handlers.compare_objects) return 1;
+
+ // call default
+ return std_object_handlers.compare_objects(object1, object2);
+ }
+ catch (Exception &exception)
+ {
+ // a Php::Exception was thrown by the extension __compare function,
+ // pass this on to user space
+ exception.process();
+
+ // what shall we return here...
+ return 1;
+ }
+}
+
+/**
* Function to cast the object to a different type
* @param object
* @param retval
@@ -343,7 +392,7 @@ int ClassBase::cast(zval *object, zval *retval, int type)
catch (const NotImplemented &exception)
{
// is there a default?
- if (std_object_handlers.cast_object) return FAILURE;
+ if (!std_object_handlers.cast_object) return FAILURE;
// call default
return std_object_handlers.cast_object(object, retval, type);