1/* -----------------------------------------------------------------------------
2 * director.swg
3 *
4 * This file contains support for director classes that proxy
5 * method calls from C++ to PHP extensions.
6 * ----------------------------------------------------------------------------- */
7
8#ifndef SWIG_DIRECTOR_PHP_HEADER_
9#define SWIG_DIRECTOR_PHP_HEADER_
10
11#ifdef __cplusplus
12
13#include <string>
14#include <map>
15
16/*
17  Use -DSWIG_DIRECTOR_STATIC if you prefer to avoid the use of the
18  'Swig' namespace. This could be useful for multi-modules projects.
19*/
20#ifdef SWIG_DIRECTOR_STATIC
21/* Force anonymous (static) namespace */
22#define Swig
23#endif
24
25namespace Swig {
26  /* memory handler */
27  struct GCItem
28  {
29    virtual ~GCItem() {}
30
31    virtual int get_own() const
32    {
33      return 0;
34    }
35  };
36
37  struct GCItem_var
38  {
39    GCItem_var(GCItem *item = 0) : _item(item)
40    {
41    }
42
43    GCItem_var& operator=(GCItem *item)
44    {
45      GCItem *tmp = _item;
46      _item = item;
47      delete tmp;
48      return *this;
49    }
50
51    ~GCItem_var()
52    {
53      delete _item;
54    }
55
56    GCItem * operator->() const
57    {
58      return _item;
59    }
60
61    private:
62    GCItem *_item;
63  };
64
65  struct GCItem_Object : GCItem
66  {
67    GCItem_Object(int own) : _own(own)
68    {
69    }
70
71    virtual ~GCItem_Object()
72    {
73    }
74
75    int get_own() const
76    {
77      return _own;
78    }
79
80    private:
81    int _own;
82  };
83
84  template <typename Type>
85  struct GCItem_T : GCItem
86  {
87    GCItem_T(Type *ptr) : _ptr(ptr)
88    {
89    }
90
91    virtual ~GCItem_T()
92    {
93      delete _ptr;
94    }
95
96    private:
97    Type *_ptr;
98  };
99
100  class Director {
101    protected:
102      zval *swig_self;
103      typedef std::map<void*, GCItem_var> swig_ownership_map;
104      mutable swig_ownership_map swig_owner;
105#ifdef ZTS
106      // Store the ZTS context so it's available when C++ calls back to PHP.
107      void *** swig_zts_ctx;
108#endif
109    public:
110      Director(zval* self TSRMLS_DC) : swig_self(self) {
111        TSRMLS_SET_CTX(swig_zts_ctx);
112      }
113
114      bool swig_is_overridden_method(char *cname, char *lc_fname) {
115        TSRMLS_FETCH_FROM_CTX(swig_zts_ctx);
116        zend_class_entry **ce;
117        zend_function *mptr;
118        int name_len = strlen(lc_fname);
119
120        if (zend_lookup_class(cname, strlen(cname), &ce TSRMLS_CC) != SUCCESS) {
121          return false;
122        }
123        if (zend_hash_find(&(*ce)->function_table, lc_fname, name_len + 1, (void**) &mptr) != SUCCESS) {
124          return false;
125        }
126        // common.scope points to the declaring class
127        return strcmp(mptr->common.scope->name, cname);
128      }
129
130      template <typename Type>
131      void swig_acquire_ownership(Type *vptr) const
132      {
133        if (vptr) {
134          swig_owner[vptr] = new GCItem_T<Type>(vptr);
135        }
136      }
137  };
138
139  /* base class for director exceptions */
140  class DirectorException {
141  protected:
142    std::string swig_msg;
143  public:
144    DirectorException(int code, const char *hdr, const char* msg TSRMLS_DC)
145      : swig_msg(hdr)
146    {
147      if (strlen(msg)) {
148        swig_msg += " ";
149        swig_msg += msg;
150      }
151      SWIG_ErrorCode() = code;
152      SWIG_ErrorMsg() = swig_msg.c_str();
153    }
154
155    static void raise(int code, const char *hdr, const char* msg TSRMLS_DC)
156    {
157      throw DirectorException(code, hdr, msg TSRMLS_CC);
158    }
159  };
160
161  /* attempt to call a pure virtual method via a director method */
162  class DirectorPureVirtualException : public Swig::DirectorException
163  {
164  public:
165    DirectorPureVirtualException(const char* msg TSRMLS_DC)
166      : DirectorException(E_ERROR, "SWIG director pure virtual method called", msg TSRMLS_CC)
167    {
168    }
169
170    static void raise(const char *msg TSRMLS_DC)
171    {
172      throw DirectorPureVirtualException(msg TSRMLS_CC);
173    }
174  };
175  /* any php exception that occurs during a director method call */
176  class DirectorMethodException : public Swig::DirectorException
177  {
178  public:
179    DirectorMethodException(const char* msg TSRMLS_DC)
180      : DirectorException(E_ERROR, "SWIG director method error", msg TSRMLS_CC)
181    {
182    }
183
184    static void raise(const char *msg TSRMLS_DC)
185    {
186      throw DirectorMethodException(msg TSRMLS_CC);
187    }
188  };
189}
190
191// DirectorMethodException() is documented to be callable with no parameters
192// so use a macro to insert TSRMLS_CC so any ZTS context gets passed.
193#define DirectorMethodException() DirectorMethodException("" TSRMLS_CC)
194
195#endif /* __cplusplus */
196
197#endif
198