From 687714e3ed6c152d1c3e362b9bc79bede20cff61 Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 24 Dec 2020 20:42:20 +0300 Subject: [PATCH 01/17] Introduced PropertyPtrPtr interface to return pointer to Zval of property object. --- CMakeLists.txt | 1 + include/propertyptrptr.h | 41 +++++++++++++++++++++++++++++++++++++++ phpcpp.h | 1 + zend/classimpl.cpp | 42 ++++++++++++++++++++++++++++++++++++++++ zend/classimpl.h | 2 ++ zend/includes.h | 1 + 6 files changed, 88 insertions(+) create mode 100644 include/propertyptrptr.h diff --git a/CMakeLists.txt b/CMakeLists.txt index be97069f..2e1528e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -190,6 +190,7 @@ SET(PHPCPP_HEADERS_INCLUDE include/argument.h include/array.h include/arrayaccess.h + include/propertyptrptr.h include/base.h include/byref.h include/byval.h diff --git a/include/propertyptrptr.h b/include/propertyptrptr.h new file mode 100644 index 00000000..d72fc018 --- /dev/null +++ b/include/propertyptrptr.h @@ -0,0 +1,41 @@ +/** + * PropertyPtrPtr.h + * + * "Interface" that can be "implemented" by your class. If you do, you + * create your class like this: + * + * class MyClass : public Php::Base, public Php::PropertyPtrPtr { ... } + * + * @author Kirill Morozov + * @copyright 2020 Morozov + */ + +/** + * Set up namespace + */ +namespace Php { + +/** + * Class definition + */ +class PHPCPP_EXPORT PropertyPtrPtr +{ +public: + + /** + * Retrieve a member + * @param key + * @return value + */ + virtual Php::Value getPropertyPtrPtr(const Php::Value &member, int type) = 0; + + /** + * Destructor + */ + virtual ~PropertyPtrPtr() = default; +}; + +/** + * End namespace + */ +} diff --git a/phpcpp.h b/phpcpp.h index 1b0da150..8ab55d14 100644 --- a/phpcpp.h +++ b/phpcpp.h @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include diff --git a/zend/classimpl.cpp b/zend/classimpl.cpp index 6ff96c02..904e3192 100644 --- a/zend/classimpl.cpp +++ b/zend/classimpl.cpp @@ -360,6 +360,8 @@ zend_object_handlers *ClassImpl::objectHandlers() _handlers.has_property = &ClassImpl::hasProperty; _handlers.unset_property = &ClassImpl::unsetProperty; + _handlers.get_property_ptr_ptr = &ClassImpl::getPropertyPtrPtr; + // when a method is called (__call and __invoke) _handlers.get_method = &ClassImpl::getMethod; _handlers.get_closure = &ClassImpl::getClosure; @@ -651,6 +653,46 @@ zval *ClassImpl::readDimension(zval *object, zval *offset, int type, zval *rv) return std_object_handlers.read_dimension(object, offset, type, rv); } } +/** + * Function that is called when the object property is used for write operations in PHP + * + * This is the object->property[x]=y operation in PHP, and mapped to the getPropertyPtrPtr() method + * of the ArrayAccess PropertyPtrPtr + * + * @param object The object on which it is called + * @param member The name of the property + * @param type The type of operation 0 - read, 1 - write + * @return zval* + */ +zval *ClassImpl::getPropertyPtrPtr(zval *object, zval *member, int type, void **cache_slot) +{ + PropertyPtrPtr *p_ptr_ptr = dynamic_cast(ObjectImpl::find(object)->object()); + if (p_ptr_ptr) + { + try + { + Php::Value res = p_ptr_ptr->getPropertyPtrPtr(member, type); + return res.detach(true); + } + catch (Throwable &throwable) + { + // object was not caught by the extension, let it end up in user space + throwable.rethrow(); + + // unreachable + return Value(nullptr).detach(false); + } + + } + else + { + // ArrayAccess not implemented, check if there is a default handler + if (!std_object_handlers.get_property_ptr_ptr) return nullptr; + + // call default + return std_object_handlers.get_property_ptr_ptr(object, member, type, cache_slot); + } +} /** * Function that is called when the object is used as an array in PHP diff --git a/zend/classimpl.h b/zend/classimpl.h index 225c3ad7..f654bc1d 100644 --- a/zend/classimpl.h +++ b/zend/classimpl.h @@ -235,6 +235,8 @@ class ClassImpl */ static zend_object_handlers *objectHandlers(zend_class_entry *entry); + static zval *getPropertyPtrPtr(zval *object, zval *member, int type, void **cache_slot); + /** * Function to create a new iterator to iterate over an object * @param entry The class entry diff --git a/zend/includes.h b/zend/includes.h index fd914611..5a60e20b 100644 --- a/zend/includes.h +++ b/zend/includes.h @@ -90,6 +90,7 @@ #include "../include/base.h" #include "../include/countable.h" #include "../include/arrayaccess.h" +#include "../include/propertyptrptr.h" #include "../include/serializable.h" #include "../include/iterator.h" #include "../include/traversable.h" From f06b1abfa5aff37189c23359cb21e67b1c27a359 Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 14 Jan 2021 05:51:04 +0300 Subject: [PATCH 02/17] Expose BaseClass, allows to store and pass reference to extend. --- include/class.h | 4 +++- include/namespace.h | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/class.h b/include/class.h index 14cbd95b..43e497af 100644 --- a/include/class.h +++ b/include/class.h @@ -24,7 +24,7 @@ namespace Php { * Class definition of the class */ template -class PHPCPP_EXPORT Class : private ClassBase +class PHPCPP_EXPORT Class : public ClassBase { public: /** @@ -302,6 +302,8 @@ class PHPCPP_EXPORT Class : private ClassBase template Class &extends(const Class &base) { ClassBase::extends(base); return *this; } + Class &extends(const ClassBase &base) { ClassBase::extends(base); return *this; } + private: /** * Method to create the object if it is default constructable diff --git a/include/namespace.h b/include/namespace.h index 82f0be04..471588fb 100644 --- a/include/namespace.h +++ b/include/namespace.h @@ -156,6 +156,19 @@ class PHPCPP_EXPORT Namespace return *this; } + Namespace &add(const ClassBase &type) + { + // skip when locked + if (locked()) return *this; + + // and add it to the list of classes + _classes.push_back(std::unique_ptr(new ClassBase(type))); + + // allow chaining + return *this; + } + + /** * Add an interface to the namespace by moving it * @param interface The interface properties From 27b24f3fff0aeba3490985b9068ecf26935ac2c8 Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 14 Jan 2021 06:11:59 +0300 Subject: [PATCH 03/17] Add Github Actions CI/CD --- .github/workflows/c-cpp.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/c-cpp.yml diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml new file mode 100644 index 00000000..8f208bd8 --- /dev/null +++ b/.github/workflows/c-cpp.yml @@ -0,0 +1,25 @@ +name: C/C++ CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: install PHP + run: > + sudo apt install software-properties-common && \ + sudo add-apt-repository ppa:ondrej/php && \ + sudo apt-get update \ + sudo apt-get install php7.4 php7.4-dev + - name: make + run: make + - name: make install + run: sudo make install From 663ca666aebb5ba0ab072b1348b94e099932c1b3 Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 14 Jan 2021 06:22:27 +0300 Subject: [PATCH 04/17] Build using different php versions. --- .github/workflows/c-cpp.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 8f208bd8..422d90f7 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -8,9 +8,11 @@ on: jobs: build: - - runs-on: ubuntu-latest - + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-16.04, ubuntu-latest ] + php: [ '7.4', '8.0' ] steps: - uses: actions/checkout@v2 - name: install PHP @@ -18,7 +20,9 @@ jobs: sudo apt install software-properties-common && \ sudo add-apt-repository ppa:ondrej/php && \ sudo apt-get update \ - sudo apt-get install php7.4 php7.4-dev + sudo apt-get install php$PHP_VERSION php$PHP_VERSION-dev + env: + PHP_VERSION: ${{ matrix.php }} - name: make run: make - name: make install From 025c999e39dc0aebc9a42a98ce49006bd631d739 Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 14 Jan 2021 06:38:18 +0300 Subject: [PATCH 05/17] Change php installation tool --- .github/workflows/c-cpp.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 422d90f7..b69f44ec 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -15,14 +15,10 @@ jobs: php: [ '7.4', '8.0' ] steps: - uses: actions/checkout@v2 - - name: install PHP - run: > - sudo apt install software-properties-common && \ - sudo add-apt-repository ppa:ondrej/php && \ - sudo apt-get update \ - sudo apt-get install php$PHP_VERSION php$PHP_VERSION-dev - env: - PHP_VERSION: ${{ matrix.php }} + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} - name: make run: make - name: make install From 0fea26816cb926e9218ec3ee0b985065282ce730 Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 14 Jan 2021 07:13:38 +0300 Subject: [PATCH 06/17] Run builds for php7.4 only for now. --- .github/workflows/c-cpp.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index b69f44ec..dbdc4863 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -11,8 +11,8 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ ubuntu-16.04, ubuntu-latest ] - php: [ '7.4', '8.0' ] + os: [ ubuntu-16.04, ubuntu-18.04, ubuntu-20.04 ] + php: [ '7.4' ] steps: - uses: actions/checkout@v2 - name: Setup PHP From d795a1a48a0b8a74991a22a916632e4c392f797f Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 14 Jan 2021 07:39:51 +0300 Subject: [PATCH 07/17] Added various compilers. --- .github/workflows/c-cpp.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index dbdc4863..f1735e5e 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -13,13 +13,20 @@ jobs: matrix: os: [ ubuntu-16.04, ubuntu-18.04, ubuntu-20.04 ] php: [ '7.4' ] + compiler: [g++-8, g++-9, clang-10, clang-11 ] steps: - uses: actions/checkout@v2 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} + - name: Setup Compilers + run: apt install $COMPILER + env: + COMPILER: ${{ matrix.compiler }} - name: make - run: make + run: make COMPILER=$COMPILER + env: + COMPILER: ${{ matrix.compiler }} - name: make install run: sudo make install From 5ada34c57958f7e5875509e772d3ce7b6431e16c Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 14 Jan 2021 07:42:17 +0300 Subject: [PATCH 08/17] Added various compilers. --- .github/workflows/c-cpp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index f1735e5e..9deda4e6 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -21,7 +21,7 @@ jobs: with: php-version: ${{ matrix.php }} - name: Setup Compilers - run: apt install $COMPILER + run: sudo apt install $COMPILER env: COMPILER: ${{ matrix.compiler }} - name: make From e820e0459c2364be62e6a801b49fbeb4d6b550cd Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 14 Jan 2021 07:47:04 +0300 Subject: [PATCH 09/17] Remove some compilers. --- .github/workflows/c-cpp.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 9deda4e6..ad1e9cbd 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -14,6 +14,13 @@ jobs: os: [ ubuntu-16.04, ubuntu-18.04, ubuntu-20.04 ] php: [ '7.4' ] compiler: [g++-8, g++-9, clang-10, clang-11 ] + exclude: + - os: ubuntu-18.04 + node: clang-11 + - os: ubuntu-16.04 + node: clang-10 + - os: ubuntu-16.04 + node: clang-11 steps: - uses: actions/checkout@v2 - name: Setup PHP From fe9bae328140388d5403214186f428c65c30aeb1 Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 14 Jan 2021 07:48:25 +0300 Subject: [PATCH 10/17] Remove some compilers. --- .github/workflows/c-cpp.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index ad1e9cbd..85b4abb5 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -16,11 +16,11 @@ jobs: compiler: [g++-8, g++-9, clang-10, clang-11 ] exclude: - os: ubuntu-18.04 - node: clang-11 + compiler: clang-11 - os: ubuntu-16.04 - node: clang-10 + compiler: clang-10 - os: ubuntu-16.04 - node: clang-11 + compiler: clang-11 steps: - uses: actions/checkout@v2 - name: Setup PHP From 4e2b97fff4e7443cd1c1e610bbd65fa1aafd9a70 Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 14 Jan 2021 07:51:28 +0300 Subject: [PATCH 11/17] Refine compilers --- .github/workflows/c-cpp.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 85b4abb5..4239b0b8 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -13,14 +13,10 @@ jobs: matrix: os: [ ubuntu-16.04, ubuntu-18.04, ubuntu-20.04 ] php: [ '7.4' ] - compiler: [g++-8, g++-9, clang-10, clang-11 ] + compiler: [g++-8, g++-9, clang-9, clang-10 ] exclude: - - os: ubuntu-18.04 - compiler: clang-11 - os: ubuntu-16.04 compiler: clang-10 - - os: ubuntu-16.04 - compiler: clang-11 steps: - uses: actions/checkout@v2 - name: Setup PHP From 98a02938d11fa10bd66b14940a49ecf721487259 Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 14 Jan 2021 08:01:46 +0300 Subject: [PATCH 12/17] Added g++10 for compilation --- .github/workflows/c-cpp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 4239b0b8..8476562f 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -13,7 +13,7 @@ jobs: matrix: os: [ ubuntu-16.04, ubuntu-18.04, ubuntu-20.04 ] php: [ '7.4' ] - compiler: [g++-8, g++-9, clang-9, clang-10 ] + compiler: [g++-8, g++-9, g++10, clang-9, clang-10 ] exclude: - os: ubuntu-16.04 compiler: clang-10 From 76e54a4a6018af23db779893dcf36ed4a19f166c Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 14 Jan 2021 08:10:13 +0300 Subject: [PATCH 13/17] Added g++10 for compilation --- .github/workflows/c-cpp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 8476562f..9e5de895 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -13,7 +13,7 @@ jobs: matrix: os: [ ubuntu-16.04, ubuntu-18.04, ubuntu-20.04 ] php: [ '7.4' ] - compiler: [g++-8, g++-9, g++10, clang-9, clang-10 ] + compiler: [g++-8, g++-9, g++-10, clang-9, clang-10 ] exclude: - os: ubuntu-16.04 compiler: clang-10 From 16d65f1aa12802cb32a01b6aa64d85d23f366d7e Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 14 Jan 2021 08:12:29 +0300 Subject: [PATCH 14/17] Exclude old system --- .github/workflows/c-cpp.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 9e5de895..f4e00257 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -15,6 +15,8 @@ jobs: php: [ '7.4' ] compiler: [g++-8, g++-9, g++-10, clang-9, clang-10 ] exclude: + - os: ubuntu-16.04 + compiler: g++-10 - os: ubuntu-16.04 compiler: clang-10 steps: From 767c22f78b09a789dbcd973c82fe6b1d198796c2 Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 14 Jan 2021 08:25:17 +0300 Subject: [PATCH 15/17] Updated build badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6171477f..9e3a3c23 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PHP-CPP ======= -[![Build Status](https://travis-ci.org/CopernicaMarketingSoftware/PHP-CPP.svg?branch=master)](https://travis-ci.org/CopernicaMarketingSoftware/PHP-CPP) +[![Build Status](https://github.com/kirmorozov/PHP-CPP/workflows/C/C++%20CI/badge.svg?branch=master)](https://github.com/kirmorozov/PHP-CPP/actions) The PHP-CPP library is a C++ library for developing PHP extensions. It offers a collection of well documented and easy-to-use classes that can be used and extended to build native From 11e75edd2595593759f1c3133e29221809b374af Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Thu, 14 Jan 2021 08:42:44 +0300 Subject: [PATCH 16/17] Added php 7.2 and php7.3 to builds. --- .github/workflows/c-cpp.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index f4e00257..ff138d8d 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -12,8 +12,8 @@ jobs: strategy: matrix: os: [ ubuntu-16.04, ubuntu-18.04, ubuntu-20.04 ] - php: [ '7.4' ] - compiler: [g++-8, g++-9, g++-10, clang-9, clang-10 ] + php: [ 7.2, 7.3, 7.4 ] + compiler: [ g++-8, g++-9, g++-10, clang-9, clang-10 ] exclude: - os: ubuntu-16.04 compiler: g++-10 From fde096ca0a23c33c63e7c5f529891e9b679601a1 Mon Sep 17 00:00:00 2001 From: Kirill Morozov Date: Fri, 15 Jan 2021 15:19:06 +0300 Subject: [PATCH 17/17] Added conversion to unordered map and string_view access to string value(avoid extra copying). --- Makefile | 2 +- include/namespace.h | 12 ++----- include/value.h | 79 +++++++++++++++++++++++++++++++++++++++++++++ zend/value.cpp | 14 +++++++- 4 files changed, 95 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 6ecab3fd..6c45edb1 100644 --- a/Makefile +++ b/Makefile @@ -101,7 +101,7 @@ endif # you want to leave that flag out on production servers). # -COMPILER_FLAGS = -Wall -c -std=c++11 -fvisibility=hidden -DBUILDING_PHPCPP -Wno-write-strings -MD +COMPILER_FLAGS = -Wall -c -std=c++17 -fvisibility=hidden -DBUILDING_PHPCPP -Wno-write-strings -MD SHARED_COMPILER_FLAGS = -fpic STATIC_COMPILER_FLAGS = PHP_COMPILER_FLAGS = ${COMPILER_FLAGS} `${PHP_CONFIG} --includes` diff --git a/include/namespace.h b/include/namespace.h index 471588fb..f1f4109f 100644 --- a/include/namespace.h +++ b/include/namespace.h @@ -156,16 +156,8 @@ class PHPCPP_EXPORT Namespace return *this; } - Namespace &add(const ClassBase &type) - { - // skip when locked - if (locked()) return *this; - - // and add it to the list of classes - _classes.push_back(std::unique_ptr(new ClassBase(type))); - - // allow chaining - return *this; + std::shared_ptr getLastClass() { + return _classes.back(); } diff --git a/include/value.h b/include/value.h index 45f7464e..532ea0a5 100644 --- a/include/value.h +++ b/include/value.h @@ -22,6 +22,7 @@ * Dependencies */ #include "zval.h" +#include /** * Set up namespace @@ -113,6 +114,17 @@ class PHPCPP_EXPORT Value : private HashParent for (auto &iter : value) setRaw(iter.first.c_str(), iter.first.size(), iter.second); } + /** + * Constructor from a unordered_map (this will create an associative array) + * @param value + */ + template + Value(const std::unordered_map &value) : Value(Type::Array) + { + // set all elements + for (auto &iter : value) setRaw(iter.first.c_str(), iter.first.size(), iter.second); + } + /** * Wrap object around zval * @param zval Zval to wrap @@ -448,6 +460,12 @@ class PHPCPP_EXPORT Value : private HashParent */ std::string stringValue() const; + /** + * Retrieve the value as a string + * @return string + */ + std::string_view stringViewValue() const; + /** * Retrieve the value as decimal * @return double @@ -557,6 +575,40 @@ class PHPCPP_EXPORT Value : private HashParent return result; } + /** + * Convert the object to a unordered_map with string index and Php::Value value + * @return std::unordered_map + */ + std::unordered_map uo_mapValue() const; + + /** + * Convert the object to a unordered_map with string index and a specific type as value + * @return std::unordered_map + */ + template + std::unordered_map uo_mapValue() const + { + // must be an array or an object, otherwise the map is empty + if (!isArray() && !isObject()) return std::unordered_map(); + + // result variable + std::unordered_map result; + + // iterate over the values + iterate([&result](const Value &key, const Value &value) { + + // first convert the value to the appropriate type (otherwise + // compiler errors occur) + T val = value; + + // add the value to the array + result[key] = val; + }); + + // done + return result; + } + /** * Define the iterator type */ @@ -692,6 +744,14 @@ class PHPCPP_EXPORT Value : private HashParent { return stringValue(); } + /** + * Cast to a string + * @return string + */ + operator std::string_view () const + { + return stringViewValue(); + } /** * Cast to byte array @@ -744,6 +804,15 @@ class PHPCPP_EXPORT Value : private HashParent return mapValue(); } + /** + * Convert the object to a map with string index and Php::Value value + * @return std::unordered_map + */ + operator std::unordered_map () const + { + return uo_mapValue(); + } + /** * Convert the object to a map with string index and Php::Value value * @return std::map @@ -754,6 +823,16 @@ class PHPCPP_EXPORT Value : private HashParent return mapValue(); } + /** + * Convert the object to a map with string index and Php::Value value + * @return std::map + */ + template + operator std::unordered_map () const + { + return uo_mapValue(); + } + /** * Get access to a certain array member * @param index diff --git a/zend/value.cpp b/zend/value.cpp index 6ded9556..2ca1048e 100644 --- a/zend/value.cpp +++ b/zend/value.cpp @@ -1295,6 +1295,18 @@ std::string Value::stringValue() const return ret; } +/** + * Retrieve the value as string + * @return string + */ +std::string_view Value::stringViewValue() const +{ + zend_string* s = zval_get_string(_val); + std::string_view ret(ZSTR_VAL(s), ZSTR_LEN(s)); + zend_string_release(s); + return ret; +} + /** * Access to the raw buffer * @return char * @@ -1838,7 +1850,7 @@ std::string Value::debugZval() const */ std::ostream &operator<<(std::ostream &stream, const Value &value) { - return stream << value.stringValue(); + return stream << value.stringViewValue(); } /**