diff options
author | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2013-09-12 05:46:02 -0700 |
---|---|---|
committer | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2013-09-12 05:46:02 -0700 |
commit | 9634a336f080bc15c1e67495eb9216d1863808f8 (patch) | |
tree | 139d3abc65f156d5e72e02364481fea370c807dc | |
parent | 68fd128d82819db1022137a45ca3224cee8ef029 (diff) |
It now is possible to access global variables, using environment[varname], and to set global variable using environment[varname] = "value"
-rw-r--r-- | include/environment.h | 17 | ||||
-rw-r--r-- | include/global.h | 193 | ||||
-rw-r--r-- | include/value.h | 8 | ||||
-rw-r--r-- | phpcpp.h | 1 | ||||
-rw-r--r-- | src/config.m4 | 4 | ||||
-rw-r--r-- | src/environment.cpp | 70 | ||||
-rw-r--r-- | src/global.cpp | 42 | ||||
-rw-r--r-- | src/includes.h | 1 | ||||
-rw-r--r-- | src/value.cpp | 63 | ||||
-rw-r--r-- | tests/simple/simple.cpp | 10 | ||||
-rw-r--r-- | tests/simple/simple.php | 7 |
11 files changed, 379 insertions, 37 deletions
diff --git a/include/environment.h b/include/environment.h index b8b4f74..6484d83 100644 --- a/include/environment.h +++ b/include/environment.h @@ -23,6 +23,7 @@ namespace Php { * Forward definitions */ class Extension; +class Global; /** * Class definition @@ -91,6 +92,22 @@ public: { _data = data; } + + /** + * Get access to a global variable + * @param name + * @return Global + */ + Global operator[](const char *name); + + /** + * Get access to a global variable + * @param name + * @return Global + */ + Global operator[](const std::string &name); + + protected: /** diff --git a/include/global.h b/include/global.h new file mode 100644 index 0000000..ead2e08 --- /dev/null +++ b/include/global.h @@ -0,0 +1,193 @@ +/** + * Global variable + * + * A global variable is a value that - once updated - also updates + * the global scope + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2013 Copernica BV + */ + +/** + * Forward definitions + */ +struct _zval_struct; + +/** + * Namespace + */ +namespace Php { + +/** + * Class definition + */ +class Global : public Value +{ +public: + /** + * No copy constructor + * @param global + */ + Global(const Global &global) = delete; + + /** + * Move constructor + * @param global + */ + Global(Global &&global) : Value(std::move(global)), _name(std::move(global._name)), _exists(global._exists) {} + + /** + * Destructor + */ + virtual ~Global() {} + + /** + * Assignment operator + * @param global + * @return Global + */ + /* + Global &operator=(const Global &global) + { + // skip self assignment + if (&global == this) return *this; + + // call base + Value::operator=(global); + + // copy name and exists setting + _name = global._name; + _exists = global._exists; + + // done + return *this; + } + */ + + /** + * Move operator + * @param global + * @return Global + */ + /* + Global &operator=(Global &&global) + { + // skip self assignment + if (&global == this) return *this; + + // call base + Value::operator=(std::move(global)); + + // copy name and exists setting + _name = std::move(global._name); + _exists = global._exists; + + // done + return *this; + } + */ + + /** + * Assignment operator + * @param value + * @return Global + */ + template <typename T> + Global &operator=(const T &value) + { + Value::operator=(value); + return update(); + } + + /** + * Set a certain property + * Calling this method will turn the value into an array + * @param index Index of the property to set + * @param value Value to set + * @return Value The value that was set + */ + virtual const Value &set(int index, const Value &value) override + { + // update current object + update(); + + // call base + return Value::set(index, value); + } + + /** + * Set a certain property + * Calling this method will turn the value into an array + * @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) override + { + // update current object + update(); + + // call base + return Value::set(key, size, value); + } + + +protected: + /** + * Function that is called when the value is updated + * @return Value + */ + Global &update(); + +private: + /** + * Constructor for non-existing var + * @param name + */ + Global(const char *name) : Value(), _name(name), _exists(false) {} + + /** + * Alternative constructor for non-existing var + * @param name + */ + Global(const std::string &name) : Value(), _name(name), _exists(false) {} + + /** + * Constructor to wrap zval for existing global bar + * @param name + * @param val + */ + Global(const char *name, struct _zval_struct *val) : Value(val, true), _name(name), _exists(true) {} + + /** + * Alternative constructor to wrap zval + * @param name + * @param val + */ + Global(const std::string &name, struct _zval_struct *val) : Value(val, true), _name(name), _exists(true) {} + + /** + * Name of the variable + * @var string + */ + std::string _name; + + /** + * Does it already exist? + * @var bool + */ + bool _exists; + + /** + * The environment can access the private method from this class + */ + friend class Environment; +}; + +/** + * End of namespace + */ +} + + diff --git a/include/value.h b/include/value.h index 4854437..fa2b608 100644 --- a/include/value.h +++ b/include/value.h @@ -121,14 +121,14 @@ public: * @param value * @return Value */ - virtual Value &operator=(const Value &value); + Value &operator=(const Value &value); /** * Move assignment * @param value * @return Value */ - virtual Value &operator=(Value &&value); + Value &operator=(Value &&value); /** * Assignment operator @@ -425,7 +425,7 @@ public: * @param value Value to set * @return Value The value that was set */ - const Value &set(int index, const Value &value); + virtual const Value &set(int index, const Value &value); /** * Set a certain property @@ -435,7 +435,7 @@ public: * @param value Value to set * @return Value The value that was set */ - const Value &set(const char *key, int size, const Value &value); + virtual const Value &set(const char *key, int size, const Value &value); /** * Set a certain property @@ -28,6 +28,7 @@ #include <phpcpp/byval.h> #include <phpcpp/byref.h> #include <phpcpp/value.h> +#include <phpcpp/global.h> #include <phpcpp/member.h> #include <phpcpp/parameters.h> #include <phpcpp/function.h> diff --git a/src/config.m4 b/src/config.m4 deleted file mode 100644 index a81d11d..0000000 --- a/src/config.m4 +++ /dev/null @@ -1,4 +0,0 @@ -dnl PHP_REQUIRE_CXX() -dnl PHP_ADD_LIBRARY(stdc++, 1, PHP5CPP_SHARED_LIBADD) -PHP_NEW_EXTENSION(phpcpp, extension.cpp, $ext_shared,,"","yes") - diff --git a/src/environment.cpp b/src/environment.cpp new file mode 100644 index 0000000..b2fdad6 --- /dev/null +++ b/src/environment.cpp @@ -0,0 +1,70 @@ +/** + * Environment.cpp + * + * Implementation of the environment class + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2013 Copernica BV + */ +#include "includes.h" + +/** + * Namespace + */ +namespace Php { + +/** + * Get access to a global variable + * @param name + * @return Global + */ +Global Environment::operator[](const char *name) +{ + // pointer to a zval + zval **varvalue; + + // check if the variable already exists + if (zend_hash_find(&EG(symbol_table), name, strlen(name)+1, (void**)&varvalue) == FAILURE) + { + // the variable does not already exist, return a global object + // that will automatically set the value when it is updated + return Global(name); + } + else + { + // we are in the happy situation that the variable exists, we turn + // this value into a reference value, and return that + return Global(name, *varvalue); + } +} + +/** + * Get access to a global variable + * @param name + * @return Global + */ +Global Environment::operator[](const std::string &name) +{ + // pointer to a zval + zval **varvalue; + + // check if the variable already exists + if (zend_hash_find(&EG(symbol_table), name.c_str(), name.size()+1, (void**)&varvalue) == FAILURE) + { + // the variable does not already exist, return a global object + // that will automatically set the value when it is updated + return Global(name); + } + else + { + // we are in the happy situation that the variable exists, we turn + // this value into a reference value, and return that + return Global(name, *varvalue); + } +} + +/** + * End of namespace + */ +} + diff --git a/src/global.cpp b/src/global.cpp new file mode 100644 index 0000000..af72bc0 --- /dev/null +++ b/src/global.cpp @@ -0,0 +1,42 @@ +/** + * Global.cpp + * + * Implementation for the global variable + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2013 Copernica BV + */ +#include "includes.h" + +/** + * Namespace + */ +namespace Php { + +/** + * Function that is called when the value is updated + * @return Value + */ +Global &Global::update() +{ + // skip if the variable already exists + if (_exists) return *this; + + // add the variable to the globals + zend_hash_add(EG(active_symbol_table), _name.c_str(), _name.size()+1, &_val, sizeof(zval*), NULL); + + // add one extra reference because the variable now is a global var too + Z_ADDREF_P(_val); + + // remember that the variable now exists + _exists = true; + + // done + return *this; +} + +/** + * End of namespace + */ +} + diff --git a/src/includes.h b/src/includes.h index 1a60b67..7fb8c5f 100644 --- a/src/includes.h +++ b/src/includes.h @@ -41,6 +41,7 @@ #include "../include/byval.h" #include "../include/byref.h" #include "../include/value.h" +#include "../include/global.h" #include "../include/member.h" #include "../include/parameters.h" #include "../include/function.h" diff --git a/src/value.cpp b/src/value.cpp index 4cdac58..5239b33 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -134,19 +134,28 @@ Value::Value(double value) * @param zval Value to wrap * @param ref Force this to be a reference */ -Value::Value(struct _zval_struct *zval, bool ref) +Value::Value(struct _zval_struct *val, bool ref) { // just copy the zval into this object - _val = zval; + _val = val; + + // if the variable is not already a reference, and it has more than one + // variable pointing to it, we should seperate it so that any changes + // we're going to make will not change the other variable + if (ref && Z_REFCOUNT_P(_val) > 1) + { + // separate the zval + SEPARATE_ZVAL_IF_NOT_REF(&_val); + } // we see ourselves as reference too Z_ADDREF_P(_val); // we're ready if we do not have to force it as a reference - if (!ref || Z_ISREF_P(zval)) return; + if (!ref || Z_ISREF_P(_val)) return; // make this a reference - Z_SET_ISREF_P(zval); + Z_SET_ISREF_P(_val); } /** @@ -238,9 +247,9 @@ Value &Value::operator=(const Value &value) // and we have one more reference Z_ADDREF_P(_val); } - - // done - return *this; + + // update the object + return *this; } /** @@ -309,9 +318,9 @@ Value &Value::operator=(Value &&value) // the other object is no longer valid value._val = nullptr; } - - // done - return *this; + + // update the object + return *this; } /** @@ -329,9 +338,9 @@ Value &Value::operator=(int value) // set new value ZVAL_LONG(_val, value); - - // done - return *this; + + // update the object + return *this; } /** @@ -349,9 +358,9 @@ Value &Value::operator=(long value) // set new value ZVAL_LONG(_val, value); - - // done - return *this; + + // update the object + return *this; } /** @@ -369,9 +378,9 @@ Value &Value::operator=(bool value) // set new value ZVAL_BOOL(_val, value); - - // done - return *this; + + // update the object + return *this; } /** @@ -390,8 +399,8 @@ Value &Value::operator=(char value) // set new value ZVAL_STRINGL(_val, &value, 1, 1); - // done - return *this; + // update the object + return *this; } /** @@ -410,8 +419,8 @@ Value &Value::operator=(const std::string &value) // set new value ZVAL_STRINGL(_val, value.c_str(), value.size(), 1); - // done - return *this; + // update the object + return *this; } /** @@ -430,8 +439,8 @@ Value &Value::operator=(const char *value) // set new value ZVAL_STRING(_val, value, 1); - // done - return *this; + // update the object + return *this; } /** @@ -450,8 +459,8 @@ Value &Value::operator=(double value) // set new value ZVAL_DOUBLE(_val, value); - // done - return *this; + // update the object + return *this; } /** diff --git a/tests/simple/simple.cpp b/tests/simple/simple.cpp index 2ab177f..dede458 100644 --- a/tests/simple/simple.cpp +++ b/tests/simple/simple.cpp @@ -15,10 +15,18 @@ */ using namespace std; -static Php::Value my_plus(Php::Parameters ¶ms) +static Php::Value my_plus(Php::Environment &env, Php::Parameters ¶ms) { string p1 = params[0]; string p2 = params[1]; + + cout << "global g1: " << env["g1"].stringValue() << endl; + cout << "global g2: " << env["g2"].stringValue() << endl; + + Php::Global g(env["g3"]); + + g = "zo kan het ook"; + return p1 + p2; } diff --git a/tests/simple/simple.php b/tests/simple/simple.php index 6f70a7a..af9a2a2 100644 --- a/tests/simple/simple.php +++ b/tests/simple/simple.php @@ -18,11 +18,16 @@ class MyClass { } } +$g1 = 123; +$g2 = "abc"; + $result = my_plus(new MyClass(), array(), new MyClass(), $myvar, "blabla", new XXX()); echo("myvar = $myvar\n"); echo("resultaat: $result\n"); -print_r($result); +echo("g1: $g1\n"); +echo("g2: $g2\n"); +echo("g3: $g3\n"); |