summaryrefslogtreecommitdiff
path: root/src/callable.cpp
blob: b4b1a6e3a4cbe761beb10ec51f597a30437a6d0a (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/**
 *  Callable.cpp
 *
 *  Implementation for the Callable class
 *
 *  @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
 *  @copyright 2013 Copernica BV
 */
#include "includes.h"

/**
 *  Namespace
 */
namespace PhpCpp {

/**
 *  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_callable(INTERNAL_FUNCTION_PARAMETERS)
{
    // find the function name
    const char *function = get_active_function_name(TSRMLS_C);
    
    // when we registered the function name, we have hidden the pointer to the 
    // callable right in front of the function name - we retrieve it back
    Callable *callable = *((Callable **)(function - sizeof(Callable *)));

    // call the appropriate object
    callable->invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}

/**
 *  Fill a function entry
 * 
 *  This method is called when the extension is registering itself, when the 
 *  function or method introces himself
 * 
 *  @param  entry
 */
void Callable::fill(zend_function_entry *entry)
{
    // fill the members of the entity
    entry->fname = _name;
    entry->handler = invoke_callable;
    entry->arg_info = _argv;
    entry->num_args = _argc;
    entry->flags = _flags;
}

/**
 *  Another attempt to fill internal function info
 * 
 *  This method is called when the extension is registering itself, when the 
 *  function or method introces himself
 * 
 *  @param  entry
 */
void Callable::fill(zend_internal_function_info *info)
{
    // fill in all the members, not that the returning by reference is not used
    info->_name = _name;
    info->_name_len = _data.size() - sizeof(this);
    info->_class_name = _classname.size() ? _classname.c_str() : NULL;
    info->required_num_args = _required;
    info->_type_hint = _type;
    info->return_reference = false;
    info->pass_rest_by_reference = false;
}

/**
 *  Process the arguments
 * 
 *  The arguments are called by the user of the PhpCpp library when he 
 * 
 *  @param  arguments
 */
void Callable::process(const std::initializer_list<Argument> &arguments)
{
    // store counters
    _argc = arguments.size();
    _required = arguments.size();
    
    // allocate memory for the arguments, with one extra record to hold information
    _argv = new zend_arg_info[_argc + 1];
    
    // fill the info
    fill((zend_internal_function_info *)_argv);
    
    // iteration counter
    int i = 0;
    
    // loop through the arguments
    for (auto it = begin(arguments); it != arguments.end(); it++)
    {
        // fill the argument structure
        it->internal()->fill(&_argv[++i]);
    }
}

int do_test(int a, int b)
{
    std::cout << "do_test: " << a << " " << b << std::endl;
    
    return 77;
}

/**
 *  Invoke the method
 *  @param  ht      
 *  @param  return_value
 *  @param  return_value_ptr
 *  @param  this_ptr
 *  @param  return_value_used
 *  @param  tsrm_ls
 *  @return integer
 */
int Callable::invoke(INTERNAL_FUNCTION_PARAMETERS)
{
    std::cout << "args: " << ZEND_NUM_ARGS() << std::endl;
    std::cout << "required: " << _required << std::endl;
    std::cout << "argc: " << _argc << std::endl;
    
    // number of arguments should be sufficient // @todo show error message
//    if (ZEND_NUM_ARGS() < _required) return FAILURE;
    
    // and not be too much // @todo show error message
//    if (ZEND_NUM_ARGS() > _argc) return FAILURE;
    
    // number of arguments on the stack
    int arg_count = (int)(zend_uintptr_t) *(zend_vm_stack_top(TSRMLS_C) - 1);
    
    // loop through the arguments
    Arguments args(ZEND_NUM_ARGS());
    
    for (auto iter = args.begin(); iter != args.end(); iter++)
    {
        Value val = *iter;
        
        val = 1234;
        
        std::cout << "argument: " << iter->stringValue() << std::endl;
    }
    
    int result = do_test(args[1], args[2]);
    
    return SUCCESS;

    Value ret(return_value, true);
    
    ret = result;

    // done
    return SUCCESS;
}




/**
 *  End of namespace
 */
}