summaryrefslogtreecommitdiff
path: root/src/method.h
blob: 6a91068fd98c0f1ea63fd3adbc9ba05aacdabfc0 (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
/**
 *  Method.h
 *
 *  Internal class that represents a native class method, that can be called
 *  from PHP scripts.
 *
 *  @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
 *  @copyright 2014 Copernica BV
 */

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

/**
 *  Class definition
 */
class Method : public Callable
{
public:
    /**
     *  Constructor 
     * 
     *  @param  name            Method name
     *  @param  callback        Native callback
     *  @param  flags           Access flags
     *  @param  args            Argument description
     */
    Method(const char *name, method_callback_0 callback, int flags, const Arguments &args) : Callable(name, args), _type(0), _flags(flags) { _callback.m0 = callback; }
    Method(const char *name, method_callback_1 callback, int flags, const Arguments &args) : Callable(name, args), _type(1), _flags(flags) { _callback.m1 = callback; }
    Method(const char *name, method_callback_2 callback, int flags, const Arguments &args) : Callable(name, args), _type(2), _flags(flags) { _callback.m2 = callback; }
    Method(const char *name, method_callback_3 callback, int flags, const Arguments &args) : Callable(name, args), _type(3), _flags(flags) { _callback.m3 = callback; }

    /**
     *  Destructor
     *  @param  type
     *  @param  callback
     */
    virtual ~Method() {}

    /**
     *  Internal method to fill a function entry
     *  @param  zend_function_entry
     *  @param  classname
     */
    void initialize(struct _zend_function_entry *entry, const std::string &classname)
    {
        // fix the flags, if neither public, private and protected is set, we use public,
        // (this solves php warnings if only "final" or only "abstract" is set
        if ((_flags & (Public|Private|Protected)) == 0) _flags |= Public;
        
        // call base
        Callable::initialize(entry, classname.c_str(), _flags);
    }

    /**
     *  Invoke the method
     *  @param  parameters
     *  @return Value
     */
    virtual Value invoke(Parameters &parameters) override
    {
        // the object to call a method on
        Base *base = parameters.object();
        
        // find out which method to call, and call it
        switch (_type) {
        case 0:     (base->*_callback.m0)(); return Value();
        case 1:     (base->*_callback.m1)(parameters); return Value();
        case 2:     return (base->*_callback.m2)();
        case 3:     return (base->*_callback.m3)(parameters);
        default:    return Value();
        }
    }


private:
    /**
     *  Callback type
     *  @var int
     */
    int _type;

    /**
     *  Access flags (protected, public, abstract, final, private, etc)
     *  @var int
     *  @todo   use this
     */
    int _flags;
    
    /**
     *  The actual callback
     *  @var void*
     */
    union {
         method_callback_0 m0;
         method_callback_1 m1;
         method_callback_2 m2;
         method_callback_3 m3;
    } _callback;
};

/**
 *  End of namespace
 */
}