diff options
author | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-04-10 11:36:44 +0200 |
---|---|---|
committer | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-04-10 11:36:44 +0200 |
commit | f0dec5907bd49bb468089b0fe50d8cbf2979272e (patch) | |
tree | f6ca989d6233cfc591efe07660e6dbb774d5f505 | |
parent | ec2ee67b805b3f431db4ce2f9cdfc8d74aadfe35 (diff) | |
parent | 3119060c9c8905b9d07e04a342a2c32cf0bf1358 (diff) |
Merge pull request #76 from valmat/ini
Implemented issue # 64
-rw-r--r-- | include/call.h | 4 | ||||
-rw-r--r-- | include/extension.h | 2 | ||||
-rw-r--r-- | include/ini.h | 163 | ||||
-rw-r--r-- | include/namespace.h | 51 | ||||
-rw-r--r-- | phpcpp.h | 2 | ||||
-rw-r--r-- | tests/cpp/h/ini_entries.h | 16 | ||||
-rw-r--r-- | tests/cpp/include/ini_entries/001.h | 29 | ||||
-rw-r--r-- | tests/cpp/main.cpp | 27 | ||||
-rw-r--r-- | tests/php/dbg.php | 54 | ||||
-rwxr-xr-x | tests/php/php_alias.sh | 2 | ||||
-rw-r--r-- | zend/extensionimpl.cpp | 22 | ||||
-rw-r--r-- | zend/includes.h | 3 | ||||
-rw-r--r-- | zend/ini.cpp | 57 | ||||
-rw-r--r-- | zend/namespace.cpp | 15 |
14 files changed, 428 insertions, 19 deletions
diff --git a/include/call.h b/include/call.h index 9be5c91..2fcc9b0 100644 --- a/include/call.h +++ b/include/call.h @@ -67,7 +67,7 @@ inline void unset(const HashMember<Value> &member) { member.unset(); } /** * The isset function conflicts with the 'isset' macro defined by the Zend engine */ -#pragma push_macro("isset"); +#pragma push_macro("isset") #undef isset /** @@ -81,7 +81,7 @@ inline Value isset(const HashMember<Value> &member) { return member.exists() && /** * Re-install the ISSET macro */ -#pragma pop_macro("isset"); +#pragma pop_macro("isset") /** * End of namespace diff --git a/include/extension.h b/include/extension.h index 84789d3..fcc0f72 100644 --- a/include/extension.h +++ b/include/extension.h @@ -123,7 +123,7 @@ public: { return module(); } - + private: /** * The implementation object diff --git a/include/ini.h b/include/ini.h new file mode 100644 index 0000000..9d4cbd9 --- /dev/null +++ b/include/ini.h @@ -0,0 +1,163 @@ +/** + * Ini.h + * + * + * + * + * @copyright 2013 Copernica BV + */ + +/** + * Forward declaration + */ + +struct _zend_ini_entry; + +/** + * Set up namespace + */ +namespace Php { + + + /** + * Class definition + */ + class Ini + { + public: + + /** + * Supported place-types for ini setting + * The possible settings for where the configuration can be changed are: + * PHP_INI_USER, PHP_INI_PERDIR, PHP_INI_SYSTEM and PHP_INI_ALL + * Usually you would choose where the setting can be changed based on how it is used. For example if you want to access + * the setting during RINIT stage then you would want PHP_INI_PERDIR because the setting would have no use after RINIT. + */ + enum Place : int { + User = (1<<0), // ZEND_INI_USER (1<<0) + Perdir = (1<<1), // ZEND_INI_PERDIR (1<<1) + System = (1<<2), // ZEND_INI_SYSTEM (1<<2) + All = (1<<0) | (1<<1) | (1<<2) // ZEND_INI_ALL (ZEND_INI_USER|ZEND_INI_PERDIR|ZEND_INI_SYSTEM) + }; + + /** + * default constructors + */ + Ini(const char *name, const char *value, const char *orig_value, const Place place = Place::All) : + _name(name), _value(value), _orig_value(orig_value), _place(place) {} + + Ini(const char *name, const char *value, const Place place = Place::All) : + _name(name), _value(value), _orig_empty(true), _place(place) {} + + /** + * Constructors for bool value + */ + Ini(const char *name,const bool value, const bool orig_value, const Place place = Place::All) : + _name(name), _value(bool2str(value)), _orig_value(bool2str(orig_value)), _place(place) {} + + Ini(const char *name, const bool value, const Place place = Place::All) : + _name(name), _value(bool2str(value)), _orig_empty(true), _place(place) {} + + /** + * Constructors for integer value + * @param value + */ + Ini(const char *name, const int16_t value, const int16_t orig_value, const Place place = Place::All) : + _name(name), _value(std::to_string(value)), _orig_value(std::to_string(orig_value)), _place(place) {} + + Ini(const char *name, const int16_t value, const Place place = Place::All) : + _name(name), _value(std::to_string(value)), _orig_empty(true), _place(place) {} + + + Ini(const char *name, const int32_t value, const int32_t orig_value, const Place place = Place::All) : + _name(name), _value(std::to_string(value)), _orig_value(std::to_string(orig_value)), _place(place) {} + + Ini(const char *name, const int32_t value, const Place place = Place::All) : + _name(name), _value(std::to_string(value)), _orig_empty(true), _place(place) {} + + + Ini(const char *name, const int64_t value, const int64_t orig_value, const Place place = Place::All) : + _name(name), _value(std::to_string(value)), _orig_value(std::to_string(orig_value)), _place(place) {} + + Ini(const char *name, const int64_t value, const Place place = Place::All) : + _name(name), _value(std::to_string(value)), _orig_empty(true), _place(place) {} + + /** + * Constructors for float value + * @param value + */ + Ini(const char *name, const double value, const double orig_value, const Place place = Place::All) : + _name(name), _value(std::to_string(value)), _orig_value(std::to_string(orig_value)), _place(place) {} + + Ini(const char *name, const double value, const Place place = Place::All) : + _name(name), _value(std::to_string(value)), _orig_empty(true), _place(place) {} + + + /** + * Copy constructor + * @param Ini + */ + Ini(const Ini &that) : + _name(that._name), _value(that._value), _orig_value(that._orig_value), _orig_empty(that._orig_empty), _place(that._place) + {} + + /** + * Move constructor + * @param Ini + */ + Ini(Ini &&that) : + _name(that._name), _value(std::move(that._value)), _orig_value(std::move(that._orig_value)), _orig_empty(that._orig_empty), _place(that._place) + {} + + + /** + * Filling ini_entries + * @param zend_ini_entry *ini_entry, int module_number + * @param int module_number + */ + void fill(_zend_ini_entry *ini_entry, int module_number); + + + /** + * Compare by name + * A predicate that takes two arguments of type Ini. + * Used when adding elements of type Ini in the container std::set + */ + struct Compare + { + int operator()(const std::shared_ptr<Ini> &s1, const std::shared_ptr<Ini> &s2) const + { + return s1->_name.compare(s2->_name); + } + }; + + private: + + static constexpr const char* bool2str(const bool value) + { + return ( static_cast<bool>(value) ? "On" : "Off"); + } + + // ini entry name + std::string _name; + + // ini entry value + std::string _value; + + // ini entry original value + std::string _orig_value; + + // _orig_value is empty + bool _orig_empty = false; + + // plase where the configuration can be changed + Place _place; + }; + + + +/** + * End of namespace + */ +} + diff --git a/include/namespace.h b/include/namespace.h index 1775061..1c9d457 100644 --- a/include/namespace.h +++ b/include/namespace.h @@ -48,6 +48,12 @@ protected: */ std::list<std::shared_ptr<Namespace>> _namespaces; + /** + * Ini entry defined by the extension + * @var list + */ + std::set<std::shared_ptr<Ini>, Ini::Compare> _ini_entries; + public: /** * Constructor @@ -159,6 +165,34 @@ public: } /** + * Add a ini entry to the extension by moving it + * @param ini The class implementation + * @return Namespace Same object to allow chaining + */ + Namespace &add(Ini &&ini) + { + // and add it to the list of classes + _ini_entries.emplace(new Ini(std::move(ini))); + + // allow chaining + return *this; + } + + /** + * Add a ini entry to the extension by copying it + * @param ini The class implementation + * @param Namespace Same object to allow chaining + */ + Namespace &add(const Ini &ini) + { + // and add it to the list of classes + _ini_entries.emplace(new Ini(ini)); + + // allow chaining + return *this; + } + + /** * The total number of functions * @return size_t */ @@ -173,6 +207,15 @@ public: // done return result; } + + /** + * The total number of ini entries + * @return size_t + */ + size_t ini_size() + { + return _ini_entries.size(); + } /** * Apply a callback to each registered function @@ -193,7 +236,13 @@ public: * @param callback */ void classes(const std::function<void(const std::string &ns, ClassBase &clss)> &callback); - + + /** + * Filling ini entries into external zend_ini_entry array + * @param zend_ini_entry* + */ + void fill_ini(_zend_ini_entry *ini_entries, int module_number); + }; /** @@ -21,10 +21,12 @@ #include <list> #include <exception> #include <map> +#include <set> /** * Include all headers files that are related to this library */ +#include <phpcpp/ini.h> #include <phpcpp/exception.h> #include <phpcpp/streams.h> #include <phpcpp/type.h> diff --git a/tests/cpp/h/ini_entries.h b/tests/cpp/h/ini_entries.h new file mode 100644 index 0000000..a6fb10e --- /dev/null +++ b/tests/cpp/h/ini_entries.h @@ -0,0 +1,16 @@ +/** + * + * Test ini entries + * + */ + + +#include "../include/ini_entries/001.h" +//#include "../include/ini_entries/.h" +//#include "../include/ini_entries/.h" + + + + + + diff --git a/tests/cpp/include/ini_entries/001.h b/tests/cpp/include/ini_entries/001.h new file mode 100644 index 0000000..649b0bd --- /dev/null +++ b/tests/cpp/include/ini_entries/001.h @@ -0,0 +1,29 @@ +/** + * + * Test ini entries + * test ini_entries/001.phpt + * + */ + +/** + * Set up namespace + */ +namespace TestIniEntries { + + + void iniTest1(Php::Parameters ¶ms) + { + Php::out << "extension_for_tests.some_string ={{" << Php::ini_get("extension_for_tests.some_string") << "}}" << std::endl; + Php::out << "extension_for_tests.some_string2 ={{" << Php::ini_get("extension_for_tests.some_string2") << "}}" << std::endl; + Php::out << "extension_for_tests.some_string3 ={{" << Php::ini_get("extension_for_tests.some_string3") << "}}" << std::endl; + Php::out << "extension_for_tests.some_string3 ={{" << Php::ini_get("extension_for_tests.some_bool") << "}}" << std::endl; + + + + return; + } +/** + * End of namespace + */ +} + diff --git a/tests/cpp/main.cpp b/tests/cpp/main.cpp index 84d95d8..2e0a1dc 100644 --- a/tests/cpp/main.cpp +++ b/tests/cpp/main.cpp @@ -11,6 +11,7 @@ #include "h/ValueIterator.h" #include "h/Classes_and_objects.h" #include "h/variables.h" +#include "h/ini_entries.h" @@ -128,6 +129,32 @@ extern "C" extension.add(std::move(cObj2Scalar)); + /** + * tests ini entries + * + */ + extension + .add(Php::Ini("ini1", "valIni1")) + .add(Php::Ini("ini2", "valIni2", "OrigValIni2")) + .add(Php::Ini("ini3", "valIni3", "OrigValIni3", Php::Ini::System)) + .add(Php::Ini("ini4", true, false, Php::Ini::Place::User)) + .add(Php::Ini("ini5", false)); + + Php::Ini ini6("ini6", 55, 11); + extension + .add(ini6) + .add(Php::Ini("ini7", 74,5)); + + Php::Ini ini8("ini8", 3.1415926, 6.2831852); + Php::Ini ini9("ini9", 2.7182818, 5.4365636, Php::Ini::User); + extension.add(Php::Ini("ini9", 0.333333, 0.777777, Php::Ini::Perdir)); + + extension.add(ini8); + extension.add(std::move(ini9)); + + extension.add("TestIniEntries\\iniTest1", TestIniEntries::iniTest1); + + diff --git a/tests/php/dbg.php b/tests/php/dbg.php index 003c494..8de0bb8 100644 --- a/tests/php/dbg.php +++ b/tests/php/dbg.php @@ -13,14 +13,46 @@ -var_dump( TestBaseClass\MyClass::CONSTANT1 ); -var_dump( TestBaseClass\MyClass::EXP ); -var_dump( TestBaseClass\MyClass::CONSTANT2 ); -var_dump( TestBaseClass\MyClass::CONSTANT3 ); - -var_dump( TestBaseClass\MyClass::$StatProp1 ); -var_dump( TestBaseClass\MyClass::$Exp ); -var_dump( TestBaseClass\MyClass::$StatProp2 ); -var_dump( TestBaseClass\MyClass::$StatProp3 ); -TestBaseClass\MyClass::$StatProp2 = "otherval"; -var_dump( TestBaseClass\MyClass::$StatProp2 ); +echo "\x1b[1;31m"; +(new ReflectionExtension('extension_for_tests') )->info(); +echo "\x1b[0m"; +echo "\x1b[0;34m"; +var_export( ini_get_all ( 'extension_for_tests' ) ); +echo "\x1b[0m", PHP_EOL; +exit; + +TestIniEntries\iniTest1(); + +//ini_set("extension_for_tests.some_string3", 'RFVBGT') ; +echo PHP_EOL; +echo "extension_for_tests.some_string ={{" , ini_get("extension_for_tests.some_string") , "}}", PHP_EOL; +echo "extension_for_tests.some_string2 ={{" , ini_get("extension_for_tests.some_string2") , "}}", PHP_EOL; +echo "extension_for_tests.some_string3 ={{" , ini_get("extension_for_tests.some_string3") , "}}", PHP_EOL; +echo "extension_for_tests.some_string3 ={{" , ini_get("extension_for_tests.some_bool") , "}}", PHP_EOL; + + +echo "\x1b[1;31m"; +(new ReflectionExtension('extension_for_tests') )->info(); +echo "\x1b[0m"; + +echo "\x1b[0;34m"; +var_export( ini_get_all ( 'extension_for_tests' ) ); +echo "\x1b[0m", PHP_EOL; + +ini_set("extension_for_tests.some_string3", 'RFVBGT') ; +echo "extension_for_tests.some_string3 ={{" , ini_get("extension_for_tests.some_string3") , "}}", PHP_EOL; +ini_restore ( 'extension_for_tests.some_string3' ); +echo "extension_for_tests.some_string3 ={{" , ini_get("extension_for_tests.some_string3") , "}}", PHP_EOL; + + +echo "extension_for_tests.some_bool :"; +var_dump(ini_get("extension_for_tests.some_bool")); +echo PHP_EOL; + +ini_set("extension_for_tests.some_bool", 'off'); + +echo "extension_for_tests.some_bool :"; +var_dump(ini_get("extension_for_tests.some_bool")); +echo PHP_EOL; + +//var_export(php_sapi_name()); diff --git a/tests/php/php_alias.sh b/tests/php/php_alias.sh index f4c7f8f..6947325 100755 --- a/tests/php/php_alias.sh +++ b/tests/php/php_alias.sh @@ -16,4 +16,4 @@ fi LD_LIBRARY_PATH="$(cd $PWD/../.. && echo $PWD):${LD_LIBRARY_PATH}" export LD_LIBRARY_PATH -/usr/bin/php -d extension_dir=../ext_dir -d extension=extfortest.so $1 +/usr/bin/php -d extension_dir=../ext_dir -d extension=extfortest.so -d ini7=47 -d extension_for_tests.frcli=frcli $1 $2 $3 $4 $5 diff --git a/zend/extensionimpl.cpp b/zend/extensionimpl.cpp index b1ec6e8..0308c63 100644 --- a/zend/extensionimpl.cpp +++ b/zend/extensionimpl.cpp @@ -110,10 +110,20 @@ int ExtensionImpl::processStartup(int type, int module_number TSRMLS_DC) { // initialize and allocate the "global" variables ZEND_INIT_MODULE_GLOBALS(phpcpp, init_globals, NULL); - + + // get the extension auto *extension = find(module_number TSRMLS_CC); + + // array contains ini settings + static zend_ini_entry *ini_entries = new zend_ini_entry[ extension->_data->ini_size()+1 ]; + + // Filling ini entries + extension->_data->fill_ini(ini_entries, module_number); + // register ini entries in Zend core + REGISTER_INI_ENTRIES(); + // initialize the extension extension->initialize(TSRMLS_C); @@ -135,7 +145,13 @@ int ExtensionImpl::processShutdown(int type, int module_number TSRMLS_DC) { // get the extension auto *extension = find(module_number TSRMLS_CC); - + + + UNREGISTER_INI_ENTRIES(); + // free memory from array ini entries + static zend_ini_entry *ini_entries; + delete [] ini_entries; + // is the callback registered? if (extension->_onShutdown) extension->_onShutdown(); @@ -197,7 +213,7 @@ ExtensionImpl::ExtensionImpl(Extension *data, const char *name, const char *vers _entry.zend_api = ZEND_MODULE_API_NO; // api number _entry.zend_debug = ZEND_DEBUG; // debug mode enabled? _entry.zts = USING_ZTS; // is thread safety enabled? - _entry.ini_entry = NULL; // the php.ini record + _entry.ini_entry = NULL; // the php.ini record, will be filled by Zend engine _entry.deps = NULL; // dependencies on other modules _entry.name = name; // extension name _entry.functions = NULL; // functions supported by this module (none for now) diff --git a/zend/includes.h b/zend/includes.h index 274ad85..4aa5eb0 100644 --- a/zend/includes.h +++ b/zend/includes.h @@ -15,6 +15,7 @@ #include <initializer_list> #include <vector> #include <map> +#include <set> #include <memory> #include <list> #include <exception> @@ -34,6 +35,7 @@ #include <php.h> #include <zend_exceptions.h> #include <zend_interfaces.h> +#include <zend_ini.h> /** * Macro to convert results to success status @@ -43,6 +45,7 @@ /** * Include other files from this library */ +#include "../include/ini.h" #include "../include/exception.h" #include "../include/streams.h" #include "../include/type.h" diff --git a/zend/ini.cpp b/zend/ini.cpp new file mode 100644 index 0000000..0c04d6a --- /dev/null +++ b/zend/ini.cpp @@ -0,0 +1,57 @@ +/** + * Ini.cpp + * + * Implementation for .... + * + * @copyright 2013 Copernica BV + */ +#include "includes.h" + +/** + * Set up namespace + */ +namespace Php { + + /** + * Filling ini_entries + * @param zend_ini_entry *ini_entry, int module_number + * @param int module_number + */ + void Ini::fill(zend_ini_entry *ini_entry, int module_number) + { + ini_entry->module_number = module_number; + ini_entry->modifiable = static_cast<int>(this->_place); + ini_entry->name = const_cast<char*>(this->_name.c_str()); + ini_entry->name_length = this->_name.size()+1; + ini_entry->on_modify = OnUpdateString; + ini_entry->mh_arg1 = nullptr; + #ifdef ZTS + ini_entry->mh_arg2 = (void *) &phpcpp_globals_id; + #else + ini_entry->mh_arg2 = (void *) &phpcpp_globals; + #endif + ini_entry->mh_arg3 = nullptr; + ini_entry->value = const_cast<char*>(this->_value.c_str()); + ini_entry->value_length = this->_value.size(); + if( this->_orig_empty) + { + ini_entry->orig_value = nullptr; + ini_entry->orig_value_length = 0; + } + else + { + ini_entry->orig_value = const_cast<char*>(this->_orig_value.c_str()); + ini_entry->orig_value_length = this->_orig_value.size(); + } + ini_entry->orig_modifiable = 0; + ini_entry->modified = 0; + ini_entry->displayer = nullptr; + } + + +/** + * End of namespace + */ +} + + diff --git a/zend/namespace.cpp b/zend/namespace.cpp index 2b4b62a..8b97c52 100644 --- a/zend/namespace.cpp +++ b/zend/namespace.cpp @@ -128,6 +128,21 @@ void Namespace::classes(const std::function<void(const std::string &ns, ClassBas } /** + * Filling ini entries into external zend_ini_entry array + * @param zend_ini_entry* + */ +void Namespace::fill_ini(zend_ini_entry *ini_entries, int module_number) +{ + // loop through the ini entries + unsigned int Ind = 0; + for (auto &ini : _ini_entries) ini->fill(&ini_entries[Ind++], module_number); + + // add last empty ini entry (Zend, for some reason, it requires) + zend_ini_entry empty_entry { 0, 0, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, 0, nullptr, 0, 0, 0, nullptr }; + ini_entries[Ind] = empty_entry; +} + +/** * End namespace */ } |