summaryrefslogtreecommitdiff
path: root/src/callable.h
blob: 2af7d41653956fd5964b178a0bb2b549bc274043 (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
/**
 *  Callable.h
 *
 *  This is an internal class that is used internally by the Function and Method 
 *  classes, and that wraps the Zend function entry into a CPP object.
 *
 *  This is an internal class, that is not supposed to be used or called from
 *  outside the PhpCpp library.
 * 
 *  @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
 *  @copyright 2013 Copernica BV
 */

/**
 *  Set up namespace
 */
namespace PhpCpp {

/**
 *  Class definition
 */
class Callable
{
public:
    /**
     *  Constructor
     *  @param  classname       Name of the class
     *  @param  function        Name of the function or method
     *  @param  type            Hint for the return type
     *  @param  arguments       The arguments that are passed to the function
     *  @param  flags           Optional flags to be passed to the function
     */
    Callable(const std::string &classname, const std::string &function, Type type = nullType, const std::initializer_list<Argument> &arguments = {}, int flags = 0) :
        _classname(classname), _type(type), _flags(flags)
    {
        // somehow "&this" is not accepted by the compiler, so we make a copy
        Callable *callable = this;

        // append function name to the data (the data contains a pointer
        // to this object, appended with the function name. this is a trick
        // so that we have the pointer to this function available in the 
        // function name by going back a number of bytes)
        _data.reserve(function.size() + sizeof(this));
        _data.assign(std::string((const char *)&callable, sizeof(callable)));
        _data.append(function);
        
        // find the name
        _name = _data.c_str() + sizeof(this);
        
        // process the arguments
        process(arguments);
    }

    /**
     *  Constructor
     *  @param  classname       Name of the class
     *  @param  function        Name of the function or method
     *  @param  type            Hint for the return type
     *  @param  arguments       The arguments that are passed to the function
     *  @param  flags           Optional flags to be passed to the function
     */
    Callable(const std::string &classname, const std::string &function, const std::initializer_list<Argument> &arguments = {}, int flags = 0) : 
        Callable(classname, function, nullType, arguments, flags) {}
    
    /**
     *  Constructor
     *  @param  function        Name of the function or method
     *  @param  type            Hint for the return type
     *  @param  arguments       The arguments that are passed to the function
     *  @param  flags           Optional flags to be passed to the function
     */
    Callable(const std::string &function, Type type = nullType, const std::initializer_list<Argument> &arguments = {}, int flags = 0) :
        Callable("", function, type, arguments, flags) {}

    /**
     *  Constructor
     *  @param  function        Name of the function or method
     *  @param  type            Hint for the return type
     *  @param  arguments       The arguments that are passed to the function
     *  @param  flags           Optional flags to be passed to the function
     */
    Callable(const std::string &function, const std::initializer_list<Argument> &arguments = {}, int flags = 0) :
        Callable("", function, nullType, arguments, flags) {}

    /**
     *  Destructor
     */
    virtual ~Callable()
    {
        delete[] _argv;
    }
    
    /**
     *  Fill a function entry
     *  @param  entry
     */
    void fill(zend_function_entry *entry);
    

private:
    /**
     *  Classname
     *  @var string
     */
    std::string _classname;
    
    /**
     *  Pointer to current object, appended with function name
     *  @var string
     */
    std::string _data;
    
    /**
     *  Pointer to the function name
     *  @var char*
     */
    const char *_name;
    
    /**
     *  The return type
     *  @var Type
     */
    Type _type;
    
    /**
     *  Function flags (like deprecated, abstract, private, etc)
     *  @var int
     */
    int _flags;
    
    /**
     *  The number of arguments
     *  @var int
     */
    int _argc;
    
    /**
     *  The number of required arguments
     *  @var int
     */
    int _required;
    
    /**
     *  The arguments
     *  @var zend_arg_info[]
     */
    zend_arg_info *_argv;

    /**
     *  Another attempt to fill internal function info
     *  @param  entry
     */
    void fill(zend_internal_function_info *info);
    
    /**
     *  Process the arguments
     *  @param  arguments
     */
    void process(const std::initializer_list<Argument> &arguments);
};

/**
 *  End of namespace
 */
}