summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2013-09-12 05:46:02 -0700
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2013-09-12 05:46:02 -0700
commit9634a336f080bc15c1e67495eb9216d1863808f8 (patch)
tree139d3abc65f156d5e72e02364481fea370c807dc
parent68fd128d82819db1022137a45ca3224cee8ef029 (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.h17
-rw-r--r--include/global.h193
-rw-r--r--include/value.h8
-rw-r--r--phpcpp.h1
-rw-r--r--src/config.m44
-rw-r--r--src/environment.cpp70
-rw-r--r--src/global.cpp42
-rw-r--r--src/includes.h1
-rw-r--r--src/value.cpp63
-rw-r--r--tests/simple/simple.cpp10
-rw-r--r--tests/simple/simple.php7
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
diff --git a/phpcpp.h b/phpcpp.h
index 84ecbf1..f93081c 100644
--- a/phpcpp.h
+++ b/phpcpp.h
@@ -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 &params)
+static Php::Value my_plus(Php::Environment &env, Php::Parameters &params)
{
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");