summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-01 10:32:26 +0100
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-01 10:32:26 +0100
commitc8d1519f31baed0fb399dac9333e48e2f9e910ad (patch)
tree1e2192f0b91d55512d26f4a14c8eae6b5a1f6ece
parent73945a9cb2b096a5379d17c028bda102b87aedce (diff)
namespace implementation, compile issue for php 5.4 and higher
-rw-r--r--include/class.h2
-rw-r--r--include/classbase.h12
-rw-r--r--include/extension.h95
-rw-r--r--include/hiddenpointer.h27
-rw-r--r--include/namespace.h203
-rw-r--r--phpcpp.h3
-rw-r--r--src/callable.cpp2
-rw-r--r--src/callable.h2
-rw-r--r--src/classbase.cpp33
-rw-r--r--src/extension.cpp83
-rw-r--r--src/function.h14
-rw-r--r--src/includes.h5
-rw-r--r--src/namespace.cpp103
13 files changed, 419 insertions, 165 deletions
diff --git a/include/class.h b/include/class.h
index 51cfb46..1ac4f00 100644
--- a/include/class.h
+++ b/include/class.h
@@ -41,6 +41,8 @@ public:
* @param name Name of the class
*/
Class(const char *name) : ClassBase(name) {}
+
+ // @todo add copy and move constructor
/**
* Destructor
diff --git a/include/classbase.h b/include/classbase.h
index 9726e5a..98a430e 100644
--- a/include/classbase.h
+++ b/include/classbase.h
@@ -88,8 +88,10 @@ public:
* this means that this method is called after the module is already available.
* This function will inform the Zend engine about the existence of the
* class.
+ *
+ * @param ns Namespace name
*/
- void initialize();
+ void initialize(const std::string &ns);
protected:
/**
@@ -173,15 +175,15 @@ private:
/**
* All class methods
- * @var set
+ * @var std::list
*/
- std::set<std::shared_ptr<Method>> _methods;
+ std::list<std::shared_ptr<Method>> _methods;
/**
* All class members (class properties)
- * @var set
+ * @var std::list
*/
- std::set<std::shared_ptr<Member>> _members;
+ std::list<std::shared_ptr<Member>> _members;
};
/**
diff --git a/include/extension.h b/include/extension.h
index 4a89cf9..72c7d56 100644
--- a/include/extension.h
+++ b/include/extension.h
@@ -29,20 +29,9 @@ struct _zend_module_entry;
namespace Php {
/**
- * A couple of predefined native callback functions that can be registered.
- * These are functions that optional accept a Request and/or Parameters object,
- * and that either return void or a Value object.
- */
-typedef void (*native_callback_0)();
-typedef void (*native_callback_1)(Parameters &);
-typedef Value (*native_callback_2)();
-typedef Value (*native_callback_3)(Parameters &);
-
-/**
* Forward declaration
*/
class Extension;
-class Function;
/**
* Optional callback types for starting and stopping the request
@@ -53,7 +42,7 @@ typedef bool (*request_callback)(Extension *extension);
/**
* Class definition
*/
-class Extension
+class Extension : public Namespace
{
public:
/**
@@ -77,36 +66,36 @@ public:
virtual ~Extension();
/**
- * Initialize the extension.
- *
- * This method is called after the extension has been loaded, constructed
- * and after the compatibility has been checked, but before the requests
- * are handled. You can override this method to add your own initialization.
- *
- * The default behavior of this function is to enable all classes that are
- * defined in this extension, so that they are also available in PHP.
+ * Initialize the extension after it was registered
*
- * The method should return true on success, and false on failure (in which
- * case the extension will not be used)
+ * You can override this method to add your own initialization code. The
+ * default implementation registers all classes and namespaces
*
* @return bool
*/
- virtual bool initialize();
+ virtual bool initialize()
+ {
+ // initialize the namespace
+ Namespace::initialize("");
+
+ // ok
+ return true;
+ }
/**
- * Finalize the extension
- *
- * This method gets called after all requests were handled, and right before
- * the Apache module or CLI script will exit. You can override it to add
- * your own cleanup code.
+ * Finalize the extension after it was registered
+ *
+ * You can override this method to do your own cleanup right before the
+ * extension object is going to be destructed
*
* @return bool
*/
virtual bool finalize()
{
+ // ok
return true;
}
-
+
/**
* Start a request
*
@@ -143,32 +132,6 @@ public:
}
/**
- * Add a native function directly to the extension
- * @param name Name of the function
- * @param function The function to add
- * @param arguments Optional argument specification
- */
- void add(const char *name, native_callback_0 function, const Arguments &arguments = {});
- void add(const char *name, native_callback_1 function, const Arguments &arguments = {});
- void add(const char *name, native_callback_2 function, const Arguments &arguments = {});
- void add(const char *name, native_callback_3 function, const Arguments &arguments = {});
-
- /**
- * Add a native class to the extension
- * @param name Name of the class
- * @param type The class implementation
- */
- template<typename T>
- void add(const Class<T> &type)
- {
- // make a copy of the object
- auto *info = new Class<T>(type);
-
- // and copy it to the list of classes
- _classes.insert(std::unique_ptr<ClassBase>(info));
- }
-
- /**
* Retrieve the module entry
*
* This is the memory address that should be exported by the get_module()
@@ -178,19 +141,23 @@ public:
*/
_zend_module_entry *module();
-
-private:
/**
- * Functions defined in the library
- * @var set
+ * Cast to a module entry
+ * @return _zend_module_entry*
*/
- std::set<std::unique_ptr<Function>> _functions;
-
+ operator _zend_module_entry * ()
+ {
+ return module();
+ }
+
+private:
/**
- * Classes defined in the library, indexed by their name
- * @var set
+ * Initialize all functions in this namespace
+ * @param ns Namespace prefix
+ * @param entries The array to be filled
+ * @return int Number of functions that were initialized
*/
- std::set<std::unique_ptr<ClassBase>> _classes;
+ size_t initialize(const std::string &ns, zend_function_entry entries[]);
/**
* The information that is passed to the Zend engine
diff --git a/include/hiddenpointer.h b/include/hiddenpointer.h
index 96bb26a..93fdc7c 100644
--- a/include/hiddenpointer.h
+++ b/include/hiddenpointer.h
@@ -94,7 +94,32 @@ public:
* @param that
* @return HiddenPointer
*/
- HiddenPointer<Type> operator=(const HiddenPointer &that) = delete;
+ HiddenPointer<Type> operator=(const HiddenPointer &that)
+ {
+ // skip self assignmend
+ if (this == &that) return *this;
+
+ // deallocate current object
+ if (_allocated) delete[] _buffer;
+
+ // copy allocated setting
+ _allocated = that._allocated;
+
+ // is the other object allocated?
+ if (_allocated)
+ {
+ // allocate this object too, call constructor
+ HiddenPointer(that, that);
+ }
+ else
+ {
+ // just copy the data
+ _buffer = that._buffer;
+ }
+
+ // done
+ return *this;
+ }
/**
* Retrieve the pointer
diff --git a/include/namespace.h b/include/namespace.h
new file mode 100644
index 0000000..727f1dd
--- /dev/null
+++ b/include/namespace.h
@@ -0,0 +1,203 @@
+/**
+ * Namespace.h
+ *
+ * Class that can be used to group various functions and classes into one
+ * namespace.
+ *
+ * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
+ * @copyright 2014 Copernica BV
+ */
+
+/**
+ * Set up namespace
+ */
+namespace Php {
+
+/**
+ * A couple of predefined native callback functions that can be registered.
+ * These are functions that optional accept a Request and/or Parameters object,
+ * and that either return void or a Value object.
+ */
+typedef void (*native_callback_0)();
+typedef void (*native_callback_1)(Parameters &);
+typedef Value (*native_callback_2)();
+typedef Value (*native_callback_3)(Parameters &);
+
+/**
+ * Forward declaration
+ */
+class Function;
+
+/**
+ * Class definition
+ */
+class Namespace
+{
+public:
+ /**
+ * Constructor
+ * @param name Name of the namespace
+ */
+ Namespace(const char *name) : _name(name) {}
+
+ /**
+ * Copy constructor
+ * @param ns Namespace to copy
+ */
+ Namespace(const Namespace &ns) :
+ _name(ns._name),
+ _functions(ns._functions),
+ _classes(ns._classes),
+ _namespaces(ns._namespaces) {}
+
+ /**
+ * Move constructor
+ * @param ns
+ */
+ Namespace(Namespace &&ns) :
+ _name(std::move(ns._name)),
+ _functions(std::move(ns._functions)),
+ _classes(std::move(ns._classes)),
+ _namespaces(std::move(ns._namespaces)) {}
+
+ /**
+ * Destructor
+ */
+ virtual ~Namespace() {}
+
+ /**
+ * Add a native function directly to the extension
+ * @param name Name of the function
+ * @param function The function to add
+ * @param arguments Optional argument specification
+ */
+ void add(const char *name, native_callback_0 function, const Arguments &arguments = {});
+ void add(const char *name, native_callback_1 function, const Arguments &arguments = {});
+ void add(const char *name, native_callback_2 function, const Arguments &arguments = {});
+ void add(const char *name, native_callback_3 function, const Arguments &arguments = {});
+
+ /**
+ * Add a native class to the extension by moving it
+ * @param name Name of the class
+ * @param type The class implementation
+ */
+ template<typename T>
+ void add(Class<T> &&type)
+ {
+ // make a copy of the object
+ auto *copy = new Class<T>(std::move(type));
+
+ // and add it to the list of classes
+ _classes.push_back(std::unique_ptr<ClassBase>(copy));
+ }
+
+ /**
+ * Add a native class to the extension by copying it
+ * @param name Name of the class
+ * @param type The class implementation
+ */
+ template<typename T>
+ void add(const Class<T> &type)
+ {
+ // make a copy of the object
+ auto *copy = new Class<T>(std::move(type));
+
+ // and add it to the list of classes
+ _classes.push_back(std::unique_ptr<ClassBase>(copy));
+ }
+
+ /**
+ * Add a namespace to the extension by moving it
+ * @param ns The namespace
+ */
+ void add(Namespace &&ns)
+ {
+ // make a copy of the object
+ auto *copy = new Namespace(std::move(ns));
+
+ // add it to the list of namespaces
+ _namespaces.push_back(std::unique_ptr<Namespace>(copy));
+ }
+
+ /**
+ * Add a namespace to the extension by copying it
+ * @param ns The namespace
+ */
+ void add(const Namespace &ns)
+ {
+ // make a copy of the object
+ auto *copy = new Namespace(std::move(ns));
+
+ // add it to the list of namespaces
+ _namespaces.push_back(std::unique_ptr<Namespace>(copy));
+ }
+
+
+protected:
+ /**
+ * Name of the namespace
+ * @var string
+ */
+ std::string _name;
+
+ /**
+ * Functions defined by the extension
+ * @var list
+ */
+ std::list<std::shared_ptr<Function>> _functions;
+
+ /**
+ * Classes defined by the extension
+ * @var list
+ */
+ std::list<std::shared_ptr<ClassBase>> _classes;
+
+ /**
+ * Namespaces defined by the extension
+ * @var list
+ */
+ std::list<std::shared_ptr<Namespace>> _namespaces;
+
+ /**
+ * The total number of functions
+ * @return size_t
+ */
+ size_t functions()
+ {
+ // number of functions in this namespace
+ int result = _functions.size();
+
+ // number of functions in sub-namespace
+ for (auto &ns : _namespaces) result += ns->functions();
+
+ // done
+ return result;
+ }
+
+ /**
+ * Initialize all functions in this namespace
+ * @param ns Namespace prefix
+ * @param entries The array to be filled
+ * @return int Number of functions that were initialized
+ */
+ size_t initialize(const std::string &ns, zend_function_entry entries[]);
+
+ /**
+ * Initialize the namespace after it was registered
+ * @param parent Parent namespace
+ */
+ void initialize(const std::string &parent)
+ {
+ // loop through the classes in this namespace
+ for (auto &c : _classes) c->initialize(parent+"\\"+_name);
+
+ // and loop through the other namespaces
+ for (auto &n : _namespaces) n->initialize(parent+"\\"+_name);
+ }
+};
+
+/**
+ * End namespace
+ */
+}
+
diff --git a/phpcpp.h b/phpcpp.h
index 7b19c64..497f056 100644
--- a/phpcpp.h
+++ b/phpcpp.h
@@ -17,9 +17,8 @@
#include <string>
#include <initializer_list>
#include <vector>
-#include <map>
#include <memory>
-#include <set>
+#include <list>
#include <exception>
/**
diff --git a/src/callable.cpp b/src/callable.cpp
index d410c0b..5745d79 100644
--- a/src/callable.cpp
+++ b/src/callable.cpp
@@ -94,7 +94,7 @@ void Callable::initialize(zend_internal_function_info *info, const char *classna
// because we do not support returning references in PHP-CPP, although Zend
// engine allows it. Inside the name we hide a pointer to the current object
info->_name = _ptr;
- info->_name_len = _ptr.length();
+ info->_name_len = strlen(_ptr);
info->_class_name = classname;
// number of required arguments, and the expected return type
diff --git a/src/callable.h b/src/callable.h
index 1b761ae..d08dc42 100644
--- a/src/callable.h
+++ b/src/callable.h
@@ -68,6 +68,7 @@ public:
/**
* Fill a function entry
* @param entry Entry to be filled
+ * @param ns Active namespace
* @param classname Optional class name
* @param flags Access flags
*/
@@ -76,6 +77,7 @@ public:
/**
* Fill function info
* @param info Info object to be filled
+ * @param ns Active namespace
* @param classname Optional class name
*/
void initialize(struct _zend_internal_function_info *info, const char *classname = nullptr) const;
diff --git a/src/classbase.cpp b/src/classbase.cpp
index 38972f5..b38f6d3 100644
--- a/src/classbase.cpp
+++ b/src/classbase.cpp
@@ -157,12 +157,17 @@ const struct _zend_function_entry *ClassBase::entries()
* this means that this method is called after the module is already available.
* This function will inform the Zend engine about the existence of the
* class.
+ *
+ * @param prefix namespace prefix
*/
-void ClassBase::initialize()
+void ClassBase::initialize(const std::string &prefix)
{
// the class entry
zend_class_entry entry;
+ // update the name
+ if (prefix.size() > 0) _name = prefix + "\\" + _name;
+
// initialize the class entry
INIT_CLASS_ENTRY_EX(entry, _name.c_str(), _name.size(), entries());
@@ -214,7 +219,7 @@ void ClassBase::initialize()
void ClassBase::add(const char *name, method_callback_0 callback, int flags, const Arguments &args)
{
// add the method
- _methods.insert(std::make_shared<Method>(name, callback, flags, args));
+ _methods.push_back(std::make_shared<Method>(name, callback, flags, args));
}
/**
@@ -227,7 +232,7 @@ void ClassBase::add(const char *name, method_callback_0 callback, int flags, con
void ClassBase::add(const char *name, method_callback_1 callback, int flags, const Arguments &args)
{
// add the method
- _methods.insert(std::make_shared<Method>(name, callback, flags, args));
+ _methods.push_back(std::make_shared<Method>(name, callback, flags, args));
}
/**
@@ -240,7 +245,7 @@ void ClassBase::add(const char *name, method_callback_1 callback, int flags, con
void ClassBase::add(const char *name, method_callback_2 callback, int flags, const Arguments &args)
{
// add the method
- _methods.insert(std::make_shared<Method>(name, callback, flags, args));
+ _methods.push_back(std::make_shared<Method>(name, callback, flags, args));
}
/**
@@ -253,7 +258,7 @@ void ClassBase::add(const char *name, method_callback_2 callback, int flags, con
void ClassBase::add(const char *name, method_callback_3 callback, int flags, const Arguments &args)
{
// add the method
- _methods.insert(std::make_shared<Method>(name, callback, flags, args));
+ _methods.push_back(std::make_shared<Method>(name, callback, flags, args));
}
/**
@@ -265,7 +270,7 @@ void ClassBase::add(const char *name, method_callback_3 callback, int flags, con
void ClassBase::add(const char *name, std::nullptr_t value, int flags)
{
// add property
- _members.insert(std::make_shared<NullMember>(name, flags));
+ _members.push_back(std::make_shared<NullMember>(name, flags));
}
/**
@@ -277,7 +282,7 @@ void ClassBase::add(const char *name, std::nullptr_t value, int flags)
void ClassBase::add(const char *name, int16_t value, int flags)
{
// add property
- _members.insert(std::make_shared<LongMember>(name, value, flags));
+ _members.push_back(std::make_shared<LongMember>(name, value, flags));
}
/**
@@ -289,7 +294,7 @@ void ClassBase::add(const char *name, int16_t value, int flags)
void ClassBase::add(const char *name, int32_t value, int flags)
{
// add property
- _members.insert(std::make_shared<LongMember>(name, value, flags));
+ _members.push_back(std::make_shared<LongMember>(name, value, flags));
}
/**
@@ -301,7 +306,7 @@ void ClassBase::add(const char *name, int32_t value, int flags)
void ClassBase::add(const char *name, int64_t value, int flags)
{
// add property
- _members.insert(std::make_shared<LongMember>(name, value, flags));
+ _members.push_back(std::make_shared<LongMember>(name, value, flags));
}
/**
@@ -313,7 +318,7 @@ void ClassBase::add(const char *name, int64_t value, int flags)
void ClassBase::add(const char *name, bool value, int flags)
{
// add property
- _members.insert(std::make_shared<BoolMember>(name, value, flags));
+ _members.push_back(std::make_shared<BoolMember>(name, value, flags));
}
/**
@@ -325,7 +330,7 @@ void ClassBase::add(const char *name, bool value, int flags)
void ClassBase::add(const char *name, char value, int flags)
{
// add property
- _members.insert(std::make_shared<StringMember>(name, &value, 1, flags));
+ _members.push_back(std::make_shared<StringMember>(name, &value, 1, flags));
}
/**
@@ -337,7 +342,7 @@ void ClassBase::add(const char *name, char value, int flags)
void ClassBase::add(const char *name, const std::string &value, int flags)
{
// add property
- _members.insert(std::make_shared<StringMember>(name, value, flags));
+ _members.push_back(std::make_shared<StringMember>(name, value, flags));
}
/**
@@ -349,7 +354,7 @@ void ClassBase::add(const char *name, const std::string &value, int flags)
void ClassBase::add(const char *name, const char *value, int flags)
{
// add property
- _members.insert(std::make_shared<StringMember>(name, value, strlen(value), flags));
+ _members.push_back(std::make_shared<StringMember>(name, value, strlen(value), flags));
}
/**
@@ -361,7 +366,7 @@ void ClassBase::add(const char *name, const char *value, int flags)
void ClassBase::add(const char *name, double value, int flags)
{
// add property
- _members.insert(std::make_shared<FloatMember>(name, value, flags));
+ _members.push_back(std::make_shared<FloatMember>(name, value, flags));
}
/**
diff --git a/src/extension.cpp b/src/extension.cpp
index dae5051..20d5627 100644
--- a/src/extension.cpp
+++ b/src/extension.cpp
@@ -156,7 +156,8 @@ static int request_shutdown(INIT_FUNC_ARGS)
* @param start Request start callback
* @param stop Request stop callback
*/
-Extension::Extension(const char *name, const char *version, request_callback start, request_callback stop) : _start(start), _stop(stop)
+Extension::Extension(const char *name, const char *version, request_callback start, request_callback stop) :
+ Namespace(""), _start(start), _stop(stop)
{
// keep extension pointer based on the name
name2extension[name] = this;
@@ -215,54 +216,6 @@ Extension::~Extension()
}
/**
- * Add a native function directly to the extension
- * @param name Name of the function
- * @param function The function to add
- * @param arguments Optional argument specification
- */
-void Extension::add(const char *name, native_callback_0 function, const Arguments &arguments)
-{
- // add a function
- _functions.insert(std::unique_ptr<Function>(new Function(name, function, arguments)));
-}
-
-/**
- * Add a native function directly to the extension
- * @param name Name of the function
- * @param function The function to add
- * @param arguments Optional argument specification
- */
-void Extension::add(const char *name, native_callback_1 function, const Arguments &arguments)
-{
- // add a function
- _functions.insert(std::unique_ptr<Function>(new Function(name, function, arguments)));
-}
-
-/**
- * Add a native function directly to the extension
- * @param name Name of the function
- * @param function The function to add
- * @param arguments Optional argument specification
- */
-void Extension::add(const char *name, native_callback_2 function, const Arguments &arguments)
-{
- // add a function
- _functions.insert(std::unique_ptr<Function>(new Function(name, function, arguments)));
-}
-
-/**
- * Add a native function directly to the extension
- * @param name Name of the function
- * @param function The function to add
- * @param arguments Optional argument specification
- */
-void Extension::add(const char *name, native_callback_3 function, const Arguments &arguments)
-{
- // add a function
- _functions.insert(std::unique_ptr<Function>(new Function(name, function, arguments)));
-}
-
-/**
* Retrieve the module entry
* @return zend_module_entry
*/
@@ -272,23 +225,13 @@ zend_module_entry *Extension::module()
if (_entry->functions || _functions.size() == 0) return _entry;
// allocate memory for the functions
- zend_function_entry *entries = new zend_function_entry[_functions.size() + 1];
-
- // keep iterator counter
- int i = 0;
+ zend_function_entry *entries = new zend_function_entry[functions() + 1];
- // loop through the functions
- for (auto &function : _functions)
- {
- // retrieve entry
- zend_function_entry *entry = &entries[i++];
-
- // let the function fill the entry
- function->initialize(entry);
- }
+ // initialize the entries
+ int count = initialize(_name, entries);
// last entry should be set to all zeros
- zend_function_entry *last = &entries[i];
+ zend_function_entry *last = &entries[count];
// all should be set to zero
memset(last, 0, sizeof(zend_function_entry));
@@ -301,20 +244,6 @@ zend_module_entry *Extension::module()
}
/**
- * Initialize the extension
- * @return bool
- */
-bool Extension::initialize()
-{
- // loop through the classes
- for (auto &iter : _classes) iter->initialize();
-
- // done
- return true;
-}
-
-
-/**
* End of namespace
*/
}
diff --git a/src/function.h b/src/function.h
index 84d7dcc..40c392f 100644
--- a/src/function.h
+++ b/src/function.h
@@ -50,6 +50,20 @@ public:
}
}
+ /**
+ * Fill a function entry
+ * @param prefix Active namespace prefix
+ * @param entry Entry to be filled
+ */
+ void initialize(const std::string &prefix, struct _zend_function_entry *entry)
+ {
+ // if there is a namespace prefix, we should adjust the name
+ if (prefix.size()) _ptr = HiddenPointer<Callable>(this, prefix+"\\"+(const char *)_ptr);
+
+ // call base initialize
+ Callable::initialize(entry);
+ }
+
private:
/**
* Union of supported callbacks
diff --git a/src/includes.h b/src/includes.h
index d2355c1..4117884 100644
--- a/src/includes.h
+++ b/src/includes.h
@@ -16,9 +16,11 @@
#include <vector>
#include <map>
#include <memory>
-#include <set>
+#include <list>
#include <exception>
+// @todo do we really nead shared_ptr?
+
// for debug
#include <iostream>
@@ -62,6 +64,7 @@
#include "../include/abstractclass.h"
#include "../include/finalclass.h"
#include "../include/interface.h"
+#include "../include/namespace.h"
#include "../include/extension.h"
#include "../include/exception.h"
#include "../include/init.h"
diff --git a/src/namespace.cpp b/src/namespace.cpp
new file mode 100644
index 0000000..0938a90
--- /dev/null
+++ b/src/namespace.cpp
@@ -0,0 +1,103 @@
+/**
+ * Namespace.cpp
+ *
+ * Implementation of the namespace class
+ *
+ * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
+ * @copyright 2014 Copernica BV
+ */
+#include "includes.h"
+
+/**
+ * Open namespace
+ */
+namespace Php {
+
+/**
+ * Add a native function directly to the extension
+ * @param name Name of the function
+ * @param function The function to add
+ * @param arguments Optional argument specification
+ */
+void Namespace::add(const char *name, native_callback_0 function, const Arguments &arguments)
+{
+ // add a function
+ _functions.push_back(std::make_shared<Function>(name, function, arguments));
+}
+
+/**
+ * Add a native function directly to the extension
+ * @param name Name of the function
+ * @param function The function to add
+ * @param arguments Optional argument specification
+ */
+void Namespace::add(const char *name, native_callback_1 function, const Arguments &arguments)
+{
+ // add a function
+ _functions.push_back(std::make_shared<Function>(name, function, arguments));
+}
+
+/**
+ * Add a native function directly to the extension
+ * @param name Name of the function
+ * @param function The function to add
+ * @param arguments Optional argument specification
+ */
+void Namespace::add(const char *name, native_callback_2 function, const Arguments &arguments)
+{
+ // add a function
+ _functions.push_back(std::make_shared<Function>(name, function, arguments));
+}
+
+/**
+ * Add a native function directly to the extension
+ * @param name Name of the function
+ * @param function The function to add
+ * @param arguments Optional argument specification
+ */
+void Namespace::add(const char *name, native_callback_3 function, const Arguments &arguments)
+{
+ // add a function
+ _functions.push_back(std::make_shared<Function>(name, function, arguments));
+}
+
+/**
+ * Initialize all functions in this namespace
+ * @param parent Namespace prefix of the parent
+ * @param entries The array to be filled
+ * @return int Number of functions that were initialized
+ */
+size_t Namespace::initialize(const std::string &parent, zend_function_entry entries[])
+{
+ // keep iterator counter
+ int count = 0;
+
+ // the namespace to use
+ std::string prefix = parent.size() ? parent + "\\" + _name : _name;
+
+ // loop through the functions
+ for (auto &function : _functions)
+ {
+ // retrieve entry
+ zend_function_entry *entry = &entries[count++];
+
+ // let the function fill the entry
+ function->initialize(prefix, entry);
+ }
+
+ // loop through the namespace
+ for (auto &ns : _namespaces)
+ {
+ // let the namespace initialize
+ count += ns->initialize(prefix, &entries[count]);
+ }
+
+ // done
+ return count;
+}
+
+/**
+ * End namespace
+ */
+}
+