summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-15 01:32:22 +0100
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-15 01:32:22 +0100
commit3300d64c4dd61e71b62d5b55b1f16e34d6335680 (patch)
treec2bd999ba1a2a1320acba20fb99acf0defb9651e /src
parent681d1e6aa735568a492140d2307a89063e7aadb9 (diff)
parentcda98dc0dea7144941a46ff20598f3c095d7a6d0 (diff)
implemented __clone method
Diffstat (limited to 'src')
-rw-r--r--src/arithmetic.h14
-rw-r--r--src/base.cpp35
-rw-r--r--src/classbase.cpp242
-rw-r--r--src/extension.cpp2
-rw-r--r--src/includes.h4
-rw-r--r--src/numericmember.h (renamed from src/longmember.h)10
-rw-r--r--src/property.h160
-rw-r--r--src/super.cpp59
-rw-r--r--src/value.cpp66
9 files changed, 511 insertions, 81 deletions
diff --git a/src/arithmetic.h b/src/arithmetic.h
index ae690bc..21343d1 100644
--- a/src/arithmetic.h
+++ b/src/arithmetic.h
@@ -55,7 +55,7 @@ public:
if (_value->isFloat()) return Value(F<double>()(_value->floatValue(), value));
// apply to natural numbers
- return Value(F<long>()(_value->numericValue(), value));
+ return Value(F<int64_t>()(_value->numericValue(), value));
}
/**
@@ -69,7 +69,7 @@ public:
if (_value->isFloat()) return Value(F<double>()(_value->floatValue(), value));
// apply to natural numbers
- return Value(F<long>()(_value->numericValue(), value));
+ return Value(F<int64_t>()(_value->numericValue(), value));
}
/**
@@ -83,7 +83,7 @@ public:
if (_value->isFloat()) return Value(F<double>()(_value->floatValue(), value));
// apply to natural numbers
- return Value(F<long>()(_value->numericValue(), value));
+ return Value(F<int64_t>()(_value->numericValue(), value));
}
/**
@@ -97,7 +97,7 @@ public:
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));
+ return Value(F<int64_t>()(_value->numericValue(), value?1:0));
}
/**
@@ -114,7 +114,7 @@ public:
if (_value->isFloat()) return Value(F<double>()(_value->floatValue(), v));
// apply to natural numbers
- return Value(F<long>()(_value->numericValue(), v));
+ return Value(F<int64_t>()(_value->numericValue(), v));
}
/**
@@ -174,7 +174,7 @@ public:
if (_value->isFloat()) return _value->operator=(F<double>()(_value->floatValue(), value));
// do a numeric operation
- return _value->operator=(F<long>()(_value->numericValue(), value));
+ return _value->operator=(F<int64_t>()(_value->numericValue(), value));
}
/**
@@ -188,7 +188,7 @@ public:
if (_value->isFloat()) return _value->operator=(F<double>()(_value->floatValue(), value));
// do a numeric operation
- return _value->operator=(F<long>()(_value->numericValue(), value));
+ return _value->operator=(F<int64_t>()(_value->numericValue(), value));
}
/**
diff --git a/src/base.cpp b/src/base.cpp
index 2c46147..f677bcf 100644
--- a/src/base.cpp
+++ b/src/base.cpp
@@ -13,29 +13,6 @@
namespace Php {
/**
- * Function that is called to clean up space that is occupied by the object
- * @param object The object to be deallocated
- */
-static void deallocate_object(void *object TSRMLS_DC)
-{
- // allocate memory for the object
- MixedObject *obj = (MixedObject *)object;
-
- // deallocate the cpp object
- if (obj->cpp) delete obj->cpp;
-
- // get rid of the object properties
- // @todo if we enable the following two lines, segmentation
- // faults and memory corruption occurs. however, the online
- // documentation does it like this
- //zend_hash_destroy(obj->php.properties);
- //FREE_HASHTABLE(obj->php.properties);
-
- // deallocate the entire object
- efree(obj);
-}
-
-/**
* Store the object in the PHP object cache
* @param entry Class entry
* @return MixedObject
@@ -71,13 +48,23 @@ MixedObject *Base::store(zend_class_entry *entry)
// the destructor and clone handlers are set to NULL. I dont know why, but they do not
// seem to be necessary...
- _handle = zend_objects_store_put(result, NULL, deallocate_object, NULL TSRMLS_CC);
+ _handle = zend_objects_store_put(result, (zend_objects_store_dtor_t)ClassBase::destructObject, (zend_objects_free_object_storage_t)ClassBase::freeObject, NULL TSRMLS_CC);
// done
return result;
}
/**
+ * Overridable method that is called right before an object is destructed
+ */
+void Base::__destruct() const
+{
+ // throw exception, so that the PHP-CPP library will check if the user
+ // somehow registered an explicit __destruct method
+ throw NotImplemented();
+}
+
+/**
* Overridable method that is called to check if a property is set
*
* The default implementation does nothing, and the script will fall back
diff --git a/src/classbase.cpp b/src/classbase.cpp
index ccfb9da..0de62dd 100644
--- a/src/classbase.cpp
+++ b/src/classbase.cpp
@@ -649,22 +649,7 @@ zval *ClassBase::readDimension(zval *object, zval *offset, int type)
try
{
// ArrayAccess is implemented, call function
- Value value = arrayaccess->offsetGet(offset);
-
- // because we do not want the value object to destruct the zval when
- // it falls out of scope, we detach the zval from it, if this is a regular
- // read operation we can do this right away
- if (type == 0) return value.detach();
-
- // this is a more complicated read operation, the scripts wants to get
- // deeper access to the returned value. This, however, is only possible
- // if the value has more than once reference (if it has a refcount of one,
- // the value object that we have here is the only instance of the zval,
- // and it is simply impossible to return a reference or so
- if (value.refcount() <= 1) return value.detach();
-
- // we're dealing with an editable zval, return a reference variable
- return Value(value.detach(), true).detach();
+ return toZval(arrayaccess->offsetGet(offset), type);
}
catch (Exception &exception)
{
@@ -817,6 +802,30 @@ void ClassBase::unsetDimension(zval *object, zval *member)
}
/**
+ * Helper method to turn a property into a zval
+ * @param value
+ * @param type
+ * @return Value
+ */
+zval *ClassBase::toZval(Value &&value, int type)
+{
+ // because we do not want the value object to destruct the zval when
+ // it falls out of scope, we detach the zval from it, if this is a regular
+ // read operation we can do this right away
+ if (type == 0) return value.detach();
+
+ // this is a more complicated read operation, the scripts wants to get
+ // deeper access to the returned value. This, however, is only possible
+ // if the value has more than once reference (if it has a refcount of one,
+ // the value object that we have here is the only instance of the zval,
+ // and it is simply impossible to return a reference or so
+ if (value.refcount() <= 1) return value.detach();
+
+ // we're dealing with an editable zval, return a reference variable
+ return Value(value.detach(), true).detach();
+}
+
+/**
* Function that is called when a property is read
* @param object
* @param name
@@ -860,23 +869,23 @@ zval *ClassBase::readProperty(zval *object, zval *name, int type, const struct _
// the exception we know if the object was implemented by the user or not
try
{
- // retrieve value
- Value value = meta->callGet(base, name);
-
- // because we do not want the value object to destruct the zval when
- // it falls out of scope, we detach the zval from it, if this is a regular
- // read operation we can do this right away
- if (type == 0) return value.detach();
+ // convert name to a Value object
+ Value key(name);
- // this is a more complicated read operation, the scripts wants to get
- // deeper access to the returned value. This, however, is only possible
- // if the value has more than once reference (if it has a refcount of one,
- // the value object that we have here is the only instance of the zval,
- // and it is simply impossible to return a reference or so
- if (value.refcount() <= 1) return value.detach();
+ // is it a property with a callback?
+ auto iter = meta->_properties.find(key);
- // we're dealing with an editable zval, return a reference variable
- return Value(value.detach(), true).detach();
+ // was it found?
+ if (iter == meta->_properties.end())
+ {
+ // retrieve value from the __get method
+ return toZval(meta->callGet(base, key), type);
+ }
+ else
+ {
+ // get the value
+ return toZval(iter->second->get(base), type);
+ }
}
catch (const NotImplemented &exception)
{
@@ -932,8 +941,26 @@ void ClassBase::writeProperty(zval *object, zval *name, zval *value, const struc
// we know for sure that the user has not overridden the __set method
try
{
- // call the default
- meta->callSet(base, name, value);
+ // wrap the name
+ Value key(name);
+
+ // check if the property has a callback
+ auto iter = meta->_properties.find(key);
+
+ // is it set?
+ if (iter == meta->_properties.end())
+ {
+ // use the __set method
+ meta->callSet(base, key, value);
+ }
+ else
+ {
+ // check if it could be set
+ if (iter->second->set(base, value)) return;
+
+ // read-only property
+ zend_error(E_ERROR, "Unable to write to read-only property %s", (const char *)key);
+ }
}
catch (const NotImplemented &exception)
{
@@ -992,15 +1019,21 @@ int ClassBase::hasProperty(zval *object, zval *name, int has_set_exists, const s
// we need the C++ class meta-information object
ClassBase *meta = cpp_class(entry);
+
+ // convert the name to a Value object
+ Value key(name);
+
+ // check if this is a callback property
+ if (meta->_properties.find(key) != meta->_properties.end()) return true;
// call the C++ object
- if (!meta->callIsset(base, name)) return false;
+ if (!meta->callIsset(base, key)) return false;
// property exists, but what does the user want to know
if (has_set_exists == 2) return true;
// we have to retrieve the property
- Value value = meta->callGet(base, name);
+ Value value = meta->callGet(base, key);
// should we check on NULL?
switch (has_set_exists) {
@@ -1055,9 +1088,18 @@ void ClassBase::unsetProperty(zval *object, zval *member, const struct _zend_lit
// we need the C++ class meta-information object
ClassBase *meta = cpp_class(entry);
-
- // call the __unset method
- meta->callUnset(cpp_object(object), member);
+
+ // property name
+ Value name(member);
+
+ // is this a callback property?
+ auto iter = meta->_properties.find(name);
+
+ // if the property does not exist, we forward to the __unset
+ if (iter == meta->_properties.end()) meta->callUnset(cpp_object(object), member);
+
+ // callback properties cannot be unset
+ zend_error(E_ERROR, "Property %s can not be unset", (const char *)name);
}
catch (const NotImplemented &exception)
{
@@ -1080,6 +1122,53 @@ void ClassBase::unsetProperty(zval *object, zval *member, const struct _zend_lit
}
/**
+ * Function that is called when an object is about to be destructed
+ * This will call the magic __destruct method
+ */
+void ClassBase::destructObject(zend_object *object, zend_object_handle handle)
+{
+ // allocate memory for the object
+ MixedObject *obj = (MixedObject *)object;
+
+ // get meta info
+ ClassBase *meta = cpp_class(object->ce);
+
+ // prevent exceptions
+ try
+ {
+ // call the destruct function
+ if (obj->cpp) meta->callDestruct(obj->cpp);
+ }
+ catch (const NotImplemented &exception)
+ {
+ // fallback on the default destructor call
+ zend_objects_destroy_object(object, handle);
+ }
+ catch (Exception &exception)
+ {
+ // a regular Php::Exception was thrown by the extension, pass it on
+ // to PHP user space
+ exception.process();
+ }
+}
+
+/**
+ * Function that is called to clean up space that is occupied by the object
+ * @param object The object to be deallocated
+ */
+void ClassBase::freeObject(zend_object *object)
+{
+ // allocate memory for the object
+ MixedObject *obj = (MixedObject *)object;
+
+ // deallocate the cpp object
+ if (obj->cpp) delete obj->cpp;
+
+ // pass on to the default destructor
+ zend_objects_free_object_storage(object);
+}
+
+/**
* Function that is called when an instance of the class needs to be created.
* This function will create the C++ class, and the PHP object
* @param entry Pointer to the class information
@@ -1509,7 +1598,7 @@ void ClassBase::property(const char *name, std::nullptr_t value, int flags)
void ClassBase::property(const char *name, int16_t value, int flags)
{
// add property
- _members.push_back(std::make_shared<LongMember>(name, value, flags));
+ _members.push_back(std::make_shared<NumericMember>(name, value, flags));
}
/**
@@ -1521,7 +1610,7 @@ void ClassBase::property(const char *name, int16_t value, int flags)
void ClassBase::property(const char *name, int32_t value, int flags)
{
// add property
- _members.push_back(std::make_shared<LongMember>(name, value, flags));
+ _members.push_back(std::make_shared<NumericMember>(name, value, flags));
}
/**
@@ -1533,7 +1622,7 @@ void ClassBase::property(const char *name, int32_t value, int flags)
void ClassBase::property(const char *name, int64_t value, int flags)
{
// add property
- _members.push_back(std::make_shared<LongMember>(name, value, flags));
+ _members.push_back(std::make_shared<NumericMember>(name, value, flags));
}
/**
@@ -1597,6 +1686,77 @@ void ClassBase::property(const char *name, double value, int flags)
}
/**
+ * Set property with callbacks
+ * @param name Name of the property
+ * @param getter Getter method
+ */
+void ClassBase::property(const char *name, const getter_callback_0 &getter)
+{
+ // add property
+ _properties[name] = std::make_shared<Property>(getter);
+}
+
+/**
+ * Set property with callbacks
+ * @param name Name of the property
+ * @param getter Getter method
+ */
+void ClassBase::property(const char *name, const getter_callback_1 &getter)
+{
+ // add property
+ _properties[name] = std::make_shared<Property>(getter);
+}
+
+/**
+ * Set property with callbacks
+ * @param name Name of the property
+ * @param getter Getter method
+ * @param setter Setter method
+ */
+void ClassBase::property(const char *name, const getter_callback_0 &getter, const setter_callback_0 &setter)
+{
+ // add property
+ _properties[name] = std::make_shared<Property>(getter,setter);
+}
+
+/**
+ * Set property with callbacks
+ * @param name Name of the property
+ * @param getter Getter method
+ * @param setter Setter method
+ */
+void ClassBase::property(const char *name, const getter_callback_1 &getter, const setter_callback_0 &setter)
+{
+ // add property
+ _properties[name] = std::make_shared<Property>(getter,setter);
+}
+
+/**
+ * Set property with callbacks
+ * @param name Name of the property
+ * @param getter Getter method
+ * @param setter Setter method
+ */
+void ClassBase::property(const char *name, const getter_callback_0 &getter, const setter_callback_1 &setter)
+{
+ // add property
+ _properties[name] = std::make_shared<Property>(getter,setter);
+}
+
+/**
+ * Set property with callbacks
+ * @param name Name of the property
+ * @param getter Getter method
+ * @param setter Setter method
+ */
+void ClassBase::property(const char *name, const getter_callback_1 &getter, const setter_callback_1 &setter)
+{
+ // add property
+ _properties[name] = std::make_shared<Property>(getter,setter);
+}
+
+
+/**
* End namespace
*/
}
diff --git a/src/extension.cpp b/src/extension.cpp
index 3f29d9c..4c6a46f 100644
--- a/src/extension.cpp
+++ b/src/extension.cpp
@@ -117,7 +117,7 @@ int Extension::onStartup(int type, int module_number)
// is the callback registered?
if (extension->_onStartup) extension->_onStartup();
-
+
// done
return BOOL2SUCCESS(true);
}
diff --git a/src/includes.h b/src/includes.h
index 50d4144..0c00df3 100644
--- a/src/includes.h
+++ b/src/includes.h
@@ -55,6 +55,7 @@
#include "../include/byval.h"
#include "../include/byref.h"
#include "../include/global.h"
+#include "../include/super.h"
#include "../include/hashmember.h"
#include "../include/parameters.h"
#include "../include/modifiers.h"
@@ -82,13 +83,14 @@
#include "method.h"
#include "member.h"
#include "nullmember.h"
-#include "longmember.h"
+#include "numericmember.h"
#include "boolmember.h"
#include "stringmember.h"
#include "floatmember.h"
#include "arithmetic.h"
#include "origexception.h"
#include "notimplemented.h"
+#include "property.h"
#ifndef ZVAL_COPY_VALUE
#define ZVAL_COPY_VALUE(z, v) \
diff --git a/src/longmember.h b/src/numericmember.h
index 09d3d8a..99889c6 100644
--- a/src/longmember.h
+++ b/src/numericmember.h
@@ -1,7 +1,7 @@
/**
- * LongMember.h
+ * NumericMember.h
*
- * Implementation for a property that is initially set to a long value
+ * Implementation for a property that is initially set to a numeric value
*
* @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
* @copyright 2013, 2014 Copernica BV
@@ -15,7 +15,7 @@ namespace Php {
/**
* Class definition
*/
-class LongMember : public Member
+class NumericMember : public Member
{
private:
/**
@@ -31,12 +31,12 @@ public:
* @param value
* @param flags
*/
- LongMember(const char *name, long value, int flags) : Member(name, flags), _value(value) {}
+ NumericMember(const char *name, long value, int flags) : Member(name, flags), _value(value) {}
/**
* Destructor
*/
- virtual ~LongMember() {}
+ virtual ~NumericMember() {}
/**
* Declare class constant
diff --git a/src/property.h b/src/property.h
new file mode 100644
index 0000000..f0fd46f
--- /dev/null
+++ b/src/property.h
@@ -0,0 +1,160 @@
+/**
+ * Property.h
+ *
+ * Internal class for properties that are defined with a getter and setter method
+ *
+ * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
+ * @copyright 2014 Copernica BV
+ */
+
+/**
+ * Set up namespace
+ */
+namespace Php {
+
+/**
+ * Class definition
+ */
+class Property
+{
+private:
+ /**
+ * The getter
+ * @var getter_callback
+ */
+ union {
+ getter_callback_0 g0;
+ getter_callback_1 g1;
+ } _getter;
+
+ /**
+ * The setter
+ * @var setter_callback
+ */
+ union {
+ setter_callback_0 s0;
+ setter_callback_1 s1;
+ } _setter;
+
+ /**
+ * Type of getter
+ * @var char
+ */
+ int _gtype = 0;
+
+ /**
+ * Type of setter
+ * @var char
+ */
+ int _stype = 100;
+
+public:
+ /**
+ * Constructor
+ * @param getter
+ * @param setter
+ */
+ Property(const getter_callback_0 &getter) : _gtype(0)
+ {
+ _getter.g0 = getter;
+ }
+
+ /**
+ * Constructor
+ * @param getter
+ * @param setter
+ */
+ Property(const getter_callback_1 &getter) : _gtype(1)
+ {
+ _getter.g1 = getter;
+ }
+
+
+ /**
+ * Constructor
+ * @param getter
+ * @param setter
+ */
+ Property(const getter_callback_0 &getter, const setter_callback_0 &setter) : _gtype(0), _stype(0)
+ {
+ _getter.g0 = getter;
+ _setter.s0 = setter;
+ }
+
+ /**
+ * Constructor
+ * @param getter
+ * @param setter
+ */
+ Property(const getter_callback_1 &getter, const setter_callback_0 &setter) : _gtype(1), _stype(0)
+ {
+ _getter.g1 = getter;
+ _setter.s0 = setter;
+ }
+
+ /**
+ * Constructor
+ * @param getter
+ * @param setter
+ */
+ Property(const getter_callback_0 &getter, const setter_callback_1 &setter) : _gtype(0), _stype(1)
+ {
+ _getter.g0 = getter;
+ _setter.s1 = setter;
+ }
+
+ /**
+ * Constructor
+ * @param getter
+ * @param setter
+ */
+ Property(const getter_callback_1 &getter, const setter_callback_1 &setter) : _gtype(1), _stype(1)
+ {
+ _getter.g1 = getter;
+ _setter.s1 = setter;
+ }
+
+ /**
+ * Copy constructor
+ * @param that
+ */
+ Property(const Property &that) :
+ _getter(that._getter), _setter(that._setter), _gtype(that._gtype), _stype(that._stype) {}
+
+ /**
+ * Destructor
+ */
+ virtual ~Property() {}
+
+ /**
+ * Get the property
+ * @param base Object to call it on
+ * @return Value
+ */
+ Value get(Base *base)
+ {
+ if (_gtype == 0) return (base->*_getter.g0)();
+ else return (base->*_getter.g1)();
+ }
+
+ /**
+ * Set the property
+ * @param base Object to call it on
+ * @param value New value
+ * @return bool
+ */
+ bool set(Base *base, const Value &value)
+ {
+ switch (_stype) {
+ case 0: (base->*_setter.s0)(value); return true;
+ case 1: (base->*_setter.s1)(value); return true;
+ default: return false;
+ }
+ }
+};
+
+/**
+ * End of namespace
+ */
+}
+
diff --git a/src/super.cpp b/src/super.cpp
new file mode 100644
index 0000000..6b02916
--- /dev/null
+++ b/src/super.cpp
@@ -0,0 +1,59 @@
+/**
+ * Super.cpp
+ *
+ * @copyright 2014 Copernica BV
+ * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
+ */
+#include "includes.h"
+
+/**
+ * Set up namespace
+ */
+namespace Php {
+
+/**
+ * A number of super-globals are always accessible
+ */
+Super POST (TRACK_VARS_POST);
+Super GET (TRACK_VARS_GET);
+Super COOKIE (TRACK_VARS_COOKIE);
+Super SERVER (TRACK_VARS_SERVER);
+Super ENV (TRACK_VARS_ENV);
+Super FILES (TRACK_VARS_FILES);
+Super REQUEST (TRACK_VARS_REQUEST);
+
+/**
+ * Array access operator
+ * This can be used for accessing associative arrays
+ * @param key
+ * @return Value
+ */
+Value Super::operator[](const std::string &key) const
+{
+ // create a value object that wraps around the actual zval
+ Value value(PG(http_globals)[_index]);
+
+ // pass on the call
+ return value[key];
+}
+
+/**
+ * Array access operator
+ * This can be used for accessing associative arrays
+ * @param key
+ * @return Value
+ */
+Value Super::operator[](const char *key) const
+{
+ // create a value object that wraps around the actual zval
+ Value value(PG(http_globals)[_index]);
+
+ // pass on the call
+ return value[key];
+}
+
+/**
+ * End namespace
+ */
+}
+
diff --git a/src/value.cpp b/src/value.cpp
index a78c2d4..9af2d14 100644
--- a/src/value.cpp
+++ b/src/value.cpp
@@ -74,7 +74,7 @@ Value::Value(int32_t value)
}
/**
- * Constructor based on long value
+ * Constructor based on int64_t value
* @param value
*/
Value::Value(int64_t value)
@@ -170,6 +170,21 @@ Value::Value(struct _zval_struct *val, bool ref)
}
/**
+ * Wrap around a hash table
+ * @param ht Hashtable to wrap
+ */
+Value::Value(HashTable *ht)
+{
+ // construct a zval
+ MAKE_STD_ZVAL(_val);
+ Z_ARRVAL_P(_val) = ht;
+ Z_TYPE_P(_val) = IS_ARRAY;
+
+ // add a reference
+ Z_ADDREF_P(_val);
+}
+
+/**
* Wrap around an object
* @param object
*/
@@ -302,6 +317,9 @@ Value::~Value()
*/
zval *Value::detach()
{
+ // leap out if already detached
+ if (!_val) return nullptr;
+
// copy return value
zval *result = _val;
@@ -316,6 +334,50 @@ zval *Value::detach()
}
/**
+ * Attach a different zval
+ *
+ * This will first detach the current zval, and link the Value object to
+ * a different zval.
+ *
+ * @param val
+ */
+void Value::attach(struct _zval_struct *val)
+{
+ // detach first
+ if (_val) detach();
+
+ // store the zval
+ _val = val;
+
+ // add one more reference
+ Z_ADDREF_P(_val);
+}
+
+/**
+ * Attach a different zval
+ *
+ * This will first detach the current zval, and link the Value object to
+ * a new zval
+ *
+ * @param hashtable
+ */
+void Value::attach(struct _hashtable *hashtable)
+{
+ // detach first
+ if (_val) detach();
+
+ // construct a new zval
+ MAKE_STD_ZVAL(_val);
+
+ // store pointer to the hashtable, and mark the zval as an array
+ Z_ARRVAL_P(_val) = hashtable;
+ Z_TYPE_P(_val) = IS_ARRAY;
+
+ // add a reference
+ Z_ADDREF_P(_val);
+}
+
+/**
* Retrieve the refcount
* @return int
*/
@@ -1353,7 +1415,7 @@ Value Value::clone(Type type) const
* Retrieve the value as integer
* @return long
*/
-long Value::numericValue() const
+int64_t Value::numericValue() const
{
// already a long?
if (isNumeric()) return Z_LVAL_P(_val);