diff --git a/include/call.h b/include/call.h index 6e0229fd..9e7c70d4 100644 --- a/include/call.h +++ b/include/call.h @@ -19,9 +19,9 @@ extern PHPCPP_EXPORT bool class_exists(const char *classname, size_t size, b static inline bool class_exists(const char *classname, bool autoload = true) { return class_exists(classname, strlen(classname), autoload); } static inline bool class_exists(const std::string &classname, bool autoload = true) { return class_exists(classname.c_str(), classname.size(), autoload); } extern PHPCPP_EXPORT Value constant(const char *constant); -extern PHPCPP_EXPORT Value constant(const char *constant, size_t size); +//extern PHPCPP_EXPORT Value constant(const char *constant, size_t size); extern PHPCPP_EXPORT Value constant(const std::string &constant); -extern PHPCPP_EXPORT bool define(const char *name, size_t size, const Value &value); +//extern PHPCPP_EXPORT bool define(const char *name, size_t size, const Value &value); extern PHPCPP_EXPORT bool define(const char *name, const Value &value); extern PHPCPP_EXPORT bool define(const std::string &name, const Value &value); extern PHPCPP_EXPORT bool defined(const char *constant); @@ -46,8 +46,8 @@ extern PHPCPP_EXPORT Value require(const char *filename); static inline Value require(const std::string &filename) { return require(filename.c_str()); } extern PHPCPP_EXPORT Value require_once(const char *filename); static inline Value require_once(const std::string &filename) { return require_once(filename.c_str()); } -extern PHPCPP_EXPORT Value set_exception_handler(const std::function &handler); -extern PHPCPP_EXPORT Value set_error_handler(const std::function &handler, Message message = Message::All); +//extern PHPCPP_EXPORT Value set_exception_handler(const std::function &handler); +//extern PHPCPP_EXPORT Value set_error_handler(const std::function &handler, Message message = Message::All); extern PHPCPP_EXPORT Value error_reporting(Message message); extern PHPCPP_EXPORT const char *sapi_name(); diff --git a/include/streams.h b/include/streams.h index b5e45003..997defe7 100644 --- a/include/streams.h +++ b/include/streams.h @@ -21,11 +21,11 @@ namespace Php { /** * Define the out and err objects */ -extern thread_local PHPCPP_EXPORT std::ostream out; -extern thread_local PHPCPP_EXPORT std::ostream error; -extern thread_local PHPCPP_EXPORT std::ostream notice; -extern thread_local PHPCPP_EXPORT std::ostream warning; -extern thread_local PHPCPP_EXPORT std::ostream deprecated; +extern PHPCPP_EXPORT std::ostream out; +extern PHPCPP_EXPORT std::ostream error; +extern PHPCPP_EXPORT std::ostream notice; +extern PHPCPP_EXPORT std::ostream warning; +extern PHPCPP_EXPORT std::ostream deprecated; /** * End namespace diff --git a/include/throwable.h b/include/throwable.h index 8b9adafa..d6a1b22e 100644 --- a/include/throwable.h +++ b/include/throwable.h @@ -11,6 +11,7 @@ */ #include #include +#include /** * Forward declarations diff --git a/phpcpp.h b/phpcpp.h index 1b0da150..3c2608c4 100644 --- a/phpcpp.h +++ b/phpcpp.h @@ -27,52 +27,52 @@ /** * Include all headers files that are related to this library */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #endif /* phpcpp.h */ diff --git a/zend/base.cpp b/zend/base.cpp index c0d9e5af..df82a654 100644 --- a/zend/base.cpp +++ b/zend/base.cpp @@ -277,7 +277,7 @@ Php::Value Base::__count(Php::Parameters ¶ms) if (countable == nullptr) return 0; // pass the call to the interface - return countable->count(); + return (Php::Value*) countable->count(); } /** diff --git a/zend/callable.cpp b/zend/callable.cpp index 98c98140..e67bc163 100644 --- a/zend/callable.cpp +++ b/zend/callable.cpp @@ -90,7 +90,7 @@ void Callable::initialize(zend_function_entry *entry, const char *classname, int { // that's nice, we simply install the callback // no need to store any data in a lookup map - entry->handler = _callback; + entry->handler = (zif_handler) _callback; } else { @@ -107,7 +107,8 @@ void Callable::initialize(zend_function_entry *entry, const char *classname, int // we use our own invoke method, which does a lookup // in the map we just installed ourselves in - entry->handler = &Callable::invoke; + //entry->handler = this->invoke(); + entry->handler = (zif_handler)_callback; } // fill the members of the entity, and hide a pointer to the current object in the name diff --git a/zend/classimpl.cpp b/zend/classimpl.cpp index c78ab216..6a624838 100644 --- a/zend/classimpl.cpp +++ b/zend/classimpl.cpp @@ -223,7 +223,7 @@ zend_function *ClassImpl::getMethod(zend_object **object, zend_string *method, c function->num_args = 0; function->required_num_args = 0; function->arg_info = nullptr; - function->handler = &ClassImpl::callMethod; + function->handler = (zif_handler) &ClassImpl::callMethod; // store pointer to ourselves data->self = self(entry); @@ -267,7 +267,7 @@ zend_function *ClassImpl::getStaticMethod(zend_class_entry *entry, zend_string * function->num_args = 0; function->required_num_args = 0; function->arg_info = nullptr; - function->handler = &ClassImpl::callMethod; + function->handler = (zif_handler) &ClassImpl::callMethod; // store pointer to ourselves data->self = self(entry); @@ -311,7 +311,7 @@ int ClassImpl::getClosure(zval *object, zend_class_entry **entry_ptr, zend_funct function->num_args = 0; function->required_num_args = 0; function->arg_info = nullptr; - function->handler = &ClassImpl::callInvoke; + function->handler = (zif_handler) & ClassImpl::callInvoke; // store pointer to ourselves (note that the entry_ptr is useless // inside this function as it is always uninitialized for some reason) diff --git a/zend/constantfuncs.cpp b/zend/constantfuncs.cpp index 09e1be25..b929d2fa 100644 --- a/zend/constantfuncs.cpp +++ b/zend/constantfuncs.cpp @@ -11,7 +11,7 @@ * Dependencies */ #include "includes.h" -#include "string.h" +#include "strings.h" /** * Set up namespace @@ -26,7 +26,7 @@ namespace Php { Value constant(const char *name) { // pass on to other implementation - return constant(name, ::strlen(name)); + return constant(name); } /** diff --git a/zend/exception_handler.cpp b/zend/exception_handler.cpp index 19191df6..54549ac5 100644 --- a/zend/exception_handler.cpp +++ b/zend/exception_handler.cpp @@ -10,7 +10,7 @@ * Dependencies */ #include "includes.h" -#include "string.h" +#include "strings.h" /** * Open the PHP namespace diff --git a/zend/exists.cpp b/zend/exists.cpp index be7a5151..a03dc13a 100644 --- a/zend/exists.cpp +++ b/zend/exists.cpp @@ -11,7 +11,7 @@ * Dependencies */ #include "includes.h" -#include "string.h" +#include "strings.h" /** * Open the PHP namespace diff --git a/zend/globals.cpp b/zend/globals.cpp index 4f1e8dee..6f64f783 100644 --- a/zend/globals.cpp +++ b/zend/globals.cpp @@ -7,7 +7,7 @@ * @copyright 2013 Copernica BV */ #include "includes.h" -#include "string.h" +#include "strings.h" /** * Namespace diff --git a/zend/module.h b/zend/module.h index 7902f8e9..02989215 100644 --- a/zend/module.h +++ b/zend/module.h @@ -75,7 +75,7 @@ class Module auto iter = _handles.begin(); // remove the handle - DL_UNLOAD(*iter); + DL_UNLOAD((HMODULE) * iter); // remove from set _handles.erase(iter); @@ -99,7 +99,7 @@ class Module void add(const char *module) { // insert the handle - _handles.insert(DL_LOAD(module)); + _handles.insert(DL_LOAD((LPCWSTR)module)); } }; @@ -126,7 +126,7 @@ class Module ExtensionPath path(module); // load the module - _handle = DL_LOAD(path); + _handle = DL_LOAD((LPCWSTR)*path); // handle should be valid if (!_handle) return; diff --git a/zend/object.cpp b/zend/object.cpp index 9e656c1a..0a98c66a 100644 --- a/zend/object.cpp +++ b/zend/object.cpp @@ -5,7 +5,7 @@ * @copyright 2014 - 2019 Copernica BV */ #include "includes.h" -#include "string.h" +#include "strings.h" /** * Set up namespace diff --git a/zend/parametersimpl.h b/zend/parametersimpl.h index fa58d9fa..e9b60fba 100644 --- a/zend/parametersimpl.h +++ b/zend/parametersimpl.h @@ -29,7 +29,9 @@ class ParametersImpl : public Parameters reserve(argc); // array to store all the arguments in - zval arguments[argc]; + //zval arguments[argc]; + + zval* arguments = new zval[argc]; // retrieve the arguments zend_get_parameters_array_ex(argc, arguments); diff --git a/zend/streambuf.cpp b/zend/streambuf.cpp index 11d928d1..5cdfce93 100644 --- a/zend/streambuf.cpp +++ b/zend/streambuf.cpp @@ -41,7 +41,7 @@ int StreamBuf::sync() } // reset the buffer - pbump(-size); + pbump(size); // done return 0; diff --git a/zend/streams.cpp b/zend/streams.cpp index ecead47b..d081d07a 100644 --- a/zend/streams.cpp +++ b/zend/streams.cpp @@ -7,31 +7,66 @@ * @copyright 2014 Copernica BV */ #include "includes.h" +#include /** * Set up namespace */ namespace Php { + StreamBuf::StreamBuf(int error) : _error(error) + { + // we reserve one byte, so that when overflow is called, we still have one + // byte extra in the buffer to put the overflowed byte int + setp(_buffer, _buffer + 1024 - 1); + } + + + /** + * Method that is called when the internal buffer overflows + * @param c + * @return int + */ + int StreamBuf::overflow(int c) + { + // for error buffers, overflow is simply discarded + if (_error) return c; + + // end-of-file has not output, we call EOF directly, and by using the + // comma operator we ensure that EOF is returned + if (c == EOF) return sync(), EOF; + + // because we lied the underlying buffer about the size of the buffer + // by one byte, there is no real overflow, and we can still add the byte + // to the end of the buffer + *pptr() = c; + + // increment buffer size + pbump(1); + + // and now we're going to syn the buffer + return sync() == -1 ? EOF : c; + } + /** * Some static buffers for writing data * @var StreamBuf */ -static thread_local StreamBuf bufOut (0); -static thread_local StreamBuf bufError (E_ERROR); -static thread_local StreamBuf bufWarning (E_WARNING); -static thread_local StreamBuf bufNotice (E_NOTICE); -static thread_local StreamBuf bufDeprecated (E_DEPRECATED); +static StreamBuf bufOut (0); +static StreamBuf bufError (E_ERROR); +static StreamBuf bufWarning (E_WARNING); +static StreamBuf bufNotice (E_NOTICE); +static StreamBuf bufDeprecated (E_DEPRECATED); /** * Create the actual steams * @var std::ostream */ -thread_local std::ostream out (&bufOut); -thread_local std::ostream error (&bufError); -thread_local std::ostream warning (&bufWarning); -thread_local std::ostream notice (&bufNotice); -thread_local std::ostream deprecated (&bufDeprecated); +std::ostream out (&bufOut); +std::ostream error (&bufError); +std::ostream warning (&bufWarning); +std::ostream notice (&bufNotice); +std::ostream deprecated (&bufDeprecated); /** * End namespace diff --git a/zend/strings.h b/zend/strings.h new file mode 100644 index 00000000..def611c5 --- /dev/null +++ b/zend/strings.h @@ -0,0 +1,167 @@ +/** + * string.h + * + * Simple wrapper around a zend_string object that + * implements RAII. This helps to avoid memory leaks + * + * @copyright 2016 Copernica B.V. + */ + +/** + * Include guard + */ +#pragma once + +/** + * Dependencies + */ +#include +#include + +/** + * Start namespace + */ +namespace Php { + +/** + * Wrapper class for a zend_string + */ +class String +{ +private: + /** + * The string we are wrapping + * @var zend_string* + */ + zend_string *_string; +public: + /** + * Constructor + * + * @param string The string to wrap + */ + String(zend_string *string) : _string(string) + { + // add another reference to the string + zend_string_addref(_string); + } + + /** + * Constructor + * + * @param string The string to wrap + */ + String(const std::string &string) : _string(zend_string_init(string.data(), string.size(), 1)) {} + + /** + * Constructor + * + * @param string The string to wrap + */ + String(const char *string) : _string(zend_string_init(string, std::strlen(string), 1)) {} + + /** + * Constructor + * + * @param string The string to wrap + * @param size Number of bytes in the string + */ + String(const char *string, size_t size) : _string(zend_string_init(string, size, 1)) {} + + /** + * Constructor + * + * @param string The string to wrap + */ + template + String(const char (&string)[size]) : _string(zend_string_init(string, size - 1, 1)) {} + + /** + * Copy constructor + * + * @param that The string to copy + */ + String(const String &that) : _string(that._string) + { + // increment refcount + zend_string_addref(_string); + } + + /** + * Move constructor + * + * @param that The string to move + */ + String(String &&that) : _string(that._string) + { + // reset other string + that._string = nullptr; + } + + /** + * Destructor + */ + virtual ~String() + { + // release the reference, freeing the + // string if we are the last referee + if (_string) zend_string_release(_string); + } + + /** + * Retrieve the data for the string + * + * @return Pointer to the string data + */ + char *data() + { + return ZSTR_VAL(_string); + } + + /** + * Retrieve the data for the string + * + * @return Pointer to the string data + */ + const char *data() const + { + return ZSTR_VAL(_string); + } + + /** + * Retrieve number of characters in the string + * + * @return Number of characters, not including the terminating null + */ + size_t size() const + { + return ZSTR_LEN(_string); + } + + /** + * Retrieve the underlying string + * + * @return The zend string + */ + operator zend_string * () + { + // return the wrapped string + return _string; + } + + /** + * Retrieve the underlying string + * + * @return The zend string + */ + zend_string *operator->() + { + // return the wrapped string + return _string; + } +}; + +/** + * End namespace + */ +} diff --git a/zend/super.cpp b/zend/super.cpp index 2f88d474..ebc15691 100644 --- a/zend/super.cpp +++ b/zend/super.cpp @@ -5,7 +5,7 @@ * @author Emiel Bruijntjes */ #include "includes.h" -#include "string.h" +#include "strings.h" /** * Set up namespace diff --git a/zend/value.cpp b/zend/value.cpp index 6ded9556..5baa66e2 100644 --- a/zend/value.cpp +++ b/zend/value.cpp @@ -24,8 +24,11 @@ * @author Emiel Bruijntjes * @copyright 2013 - 2019 Copernica BV */ + +#pragma warning (disable : 4703) + #include "includes.h" -#include "string.h" +#include "strings.h" #include "lowercase.h" /** @@ -892,7 +895,9 @@ Value Value::call(const char *name) Value Value::exec(int argc, Value *argv) const { // array of zvals to execute - zval params[argc]; + //zval params[argc]; + + zval* params = new zval[argc]; // convert all the values for(int i = 0; i < argc; i++) { params[i] = *argv[i]._val; } @@ -914,7 +919,9 @@ Value Value::exec(const char *name, int argc, Value *argv) const Value method(name); // array of zvals to execute - zval params[argc]; + //zval params[argc]; + + zval* params = new zval[argc]; // convert all the values for(int i = 0; i < argc; i++) { params[i] = *argv[i]._val; } @@ -936,7 +943,9 @@ Value Value::exec(const char *name, int argc, Value *argv) Value method(name); // array of zvals to execute - zval params[argc]; + //zval params[argc]; + + zval* params = new zval[argc]; // convert all the values for(int i = 0; i < argc; i++) { params[i] = *argv[i]._val; }