summaryrefslogtreecommitdiff
path: root/src/function.cpp
blob: 79117e55a2478926e255f44e1ac0bfa3b67ae0f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/**
 *  Function.cpp
 *
 *  Implementation for the function class
 *
 *  @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
 *  @copyright 2013 Copernica BV
 */
#include "includes.h"

/**
 *  Set up namespace
 */
namespace Php {

/**
 *  Function that is called by the Zend engine every time that a function gets called
 *  @param  ht      
 *  @param  return_value
 *  @param  return_value_ptr
 *  @param  this_ptr
 *  @param  return_value_used
 *  @param  tsrm_ls
 *  @return integer
 */
void invoke_function(INTERNAL_FUNCTION_PARAMETERS)
{
    // find the function name
    const char *name = get_active_function_name(TSRMLS_C);
    
    // uncover the hidden pointer inside the function name
    Function *function = HiddenPointer<Function>(name);

    // wrap the return value
    Value result(return_value, true);

    // construct parameters
    Parameters params(ZEND_NUM_ARGS());

    // get the result
    result = function->invoke(*PHPCPP_G(environment), params);
}

/**
 *  Constructor
 *  @param  name    Name of the function
 *  @param  min     Min number of arguments
 *  @param  max     Max number of arguments
 */
Function::Function(const char *name, const std::initializer_list<Argument> &arguments) : _ptr(this, name)
{
    // construct vector for arguments
    _argc = arguments.size();
    _argv = new zend_arg_info[_argc+1];
    
    // counter
    int i=1;
    
    // loop through the arguments
    for (auto it = arguments.begin(); it != arguments.end(); it++)
    {
        // fill the arg info
        it->fill(&_argv[i++]);
    }
    
    // @todo find out number of required arguments
    _required = _argc;
}

/**
 *  Destructor
 */
Function::~Function()
{
    delete[] _argv;
}

/**
 *  Fill a function entry
 * 
 *  This method is called when the extension is registering itself, when the 
 *  function or method introces himself
 * 
 *  @param  entry       Entry to be filled
 */
void Function::fill(zend_function_entry *entry) const
{
    // fill the members of the entity, and hide a pointer to the current object in the name
    entry->fname = _ptr;
    entry->handler = invoke_function;
    entry->arg_info = _argv;
    entry->num_args = _argc;

    // there are no flags like deprecated, private or protected
    entry->flags = 0;
    
    // we should fill the first argument as well
    fill((zend_internal_function_info *)entry->arg_info);
}

/**
 *  Fill a function entry
 *  @param  info        Info to be filled
 */
void Function::fill(zend_internal_function_info *info) const
{
    // fill in all the members, note that return reference is false by default,
    // because we do want to return references, inside the name we hide a pointer
    // to the current object
    info->_name = _ptr;
    info->_name_len = _ptr.length();
    info->_class_name = NULL;
    
    // number of required arguments, and the expected return type
    info->required_num_args = _required;
    info->_type_hint = _type;
    
    // we do not support return-by-reference
    info->return_reference = false;
    
    // passing by reference is not used
    info->pass_rest_by_reference = false;
}

/**
 *  End of namespace
 */
}