Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduced PropertyPtrPtr interface to return pointer to Zval of property object. #472

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/c-cpp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: C/C++ CI

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-16.04, ubuntu-18.04, ubuntu-20.04 ]
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
- os: ubuntu-16.04
compiler: clang-10
steps:
- uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
- name: Setup Compilers
run: sudo apt install $COMPILER
env:
COMPILER: ${{ matrix.compiler }}
- name: make
run: make COMPILER=$COMPILER
env:
COMPILER: ${{ matrix.compiler }}
- name: make install
run: sudo make install
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 3 additions & 1 deletion include/class.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace Php {
* Class definition of the class
*/
template <typename T>
class PHPCPP_EXPORT Class : private ClassBase
class PHPCPP_EXPORT Class : public ClassBase
{
public:
/**
Expand Down Expand Up @@ -302,6 +302,8 @@ class PHPCPP_EXPORT Class : private ClassBase
template<typename CLASS>
Class<T> &extends(const Class<CLASS> &base) { ClassBase::extends(base); return *this; }

Class<T> &extends(const ClassBase &base) { ClassBase::extends(base); return *this; }

private:
/**
* Method to create the object if it is default constructable
Expand Down
5 changes: 5 additions & 0 deletions include/namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ class PHPCPP_EXPORT Namespace
return *this;
}

std::shared_ptr<ClassBase> getLastClass() {
return _classes.back();
}


/**
* Add an interface to the namespace by moving it
* @param interface The interface properties
Expand Down
41 changes: 41 additions & 0 deletions include/propertyptrptr.h
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>
* @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
*/
}
79 changes: 79 additions & 0 deletions include/value.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* Dependencies
*/
#include "zval.h"
#include <unordered_map>

/**
* Set up namespace
Expand Down Expand Up @@ -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 <typename T>
Value(const std::unordered_map<std::string,T> &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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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<std::string,Php::Value> uo_mapValue() const;

/**
* Convert the object to a unordered_map with string index and a specific type as value
* @return std::unordered_map
*/
template <typename T>
std::unordered_map<std::string,T> uo_mapValue() const
{
// must be an array or an object, otherwise the map is empty
if (!isArray() && !isObject()) return std::unordered_map<std::string,T>();

// result variable
std::unordered_map<std::string,T> 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
*/
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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<std::string,Php::Value> () const
{
return uo_mapValue();
}

/**
* Convert the object to a map with string index and Php::Value value
* @return std::map
Expand All @@ -754,6 +823,16 @@ class PHPCPP_EXPORT Value : private HashParent
return mapValue<T>();
}

/**
* Convert the object to a map with string index and Php::Value value
* @return std::map
*/
template <typename T>
operator std::unordered_map<std::string,T> () const
{
return uo_mapValue<T>();
}

/**
* Get access to a certain array member
* @param index
Expand Down
1 change: 1 addition & 0 deletions phpcpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include <phpcpp/base.h>
#include <phpcpp/countable.h>
#include <phpcpp/arrayaccess.h>
#include <phpcpp/propertyptrptr.h>
#include <phpcpp/iterator.h>
#include <phpcpp/traversable.h>
#include <phpcpp/serializable.h>
Expand Down
42 changes: 42 additions & 0 deletions zend/classimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<PropertyPtrPtr*>(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
Expand Down
2 changes: 2 additions & 0 deletions zend/classimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions zend/includes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
14 changes: 13 additions & 1 deletion zend/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
Expand Down Expand Up @@ -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();
}

/**
Expand Down