]> git.sesse.net Git - xml-template/blob - php5-swig/xml-template.swig
Do weird dances to get php5-swig garbage collection going. Something tells me this...
[xml-template] / php5-swig / xml-template.swig
1 %module XML_Template_SWIG
2
3 struct XmlDocPtrWrapper {
4         ~XmlDocPtrWrapper();
5 };
6
7 %{
8
9 #include <memory>
10
11 #include "../c++11/xml-template.h"
12
13 struct XmlDocWrapper {
14         ~XmlDocWrapper() { xmlFreeDoc(ptr); }
15         xmlDocPtr ptr;
16 };
17 typedef std::shared_ptr<XmlDocWrapper> XmlDocPtrWrapper;
18
19 bool is_associative_array(HashTable *ht)
20 {
21         if (ht->nNumOfElements == 0) {
22                 return true;
23         }
24         for (unsigned i = 0; i < ht->nNumOfElements; ++i) {
25                 if (!zend_hash_index_exists(ht, i)) {
26                         return true;
27                 }
28         }
29         return false;
30 }
31
32 Directive* convert_php_objects_to_directive(zval *obj)
33 {
34         switch (Z_TYPE_P(obj)) {
35         case IS_ARRAY: {
36                 HashTable *ht = Z_ARRVAL_P(obj);
37                 if (is_associative_array(ht)) {
38                         std::unordered_map<std::string, Directive *> my_map;
39                         for (zend_hash_internal_pointer_reset(ht); zend_hash_has_more_elements(ht) == SUCCESS; zend_hash_move_forward(ht)) {
40                                 char *str_key;
41                                 ulong num_key;
42                                 zend_hash_get_current_key(ht, &str_key, &num_key, 0);
43
44                                 std::string key;
45                                 if (zend_hash_get_current_key_type(ht) == HASH_KEY_IS_STRING) {
46                                         key = str_key;
47                                 } else {
48                                         char buf[32];
49                                         sprintf(buf, "%lu", num_key);
50                                         key = buf;
51                                 }
52
53                                 zval **data;
54                                 zend_hash_get_current_data(ht, (void **)&data);
55                                 my_map.insert(make_pair(key, convert_php_objects_to_directive(*data)));
56                         }
57                         return new Substitute(my_map);
58                 } else {
59                         std::vector<Directive *> subdirectives;
60                         for (unsigned i = 0; i < ht->nNumOfElements; ++i) {
61                                 zval **data;
62                                 zend_hash_index_find(ht, i, (void **)&data);
63                                 subdirectives.push_back(convert_php_objects_to_directive(*data));
64                         }
65                         return new Clone(subdirectives);
66                 }
67                 break;
68         }
69         case IS_STRING: {
70                 char *str = Z_STRVAL_P(obj);
71                 return new Replace(str);
72         }
73         case IS_RESOURCE: {
74                 XmlDocPtrWrapper *doc;
75                 if (SWIG_ConvertPtr(obj, (void **)&doc, SWIGTYPE_p_XmlDocPtrWrapper, 0) < 0 || doc == NULL) {
76                         return NULL;
77                 }
78                 return new ReplaceInclude(xmlCopyDoc(doc->get()->ptr, 1));
79         }
80         case IS_NULL:
81                 return NULL;
82         default:
83                 printf("WARNING: Unknown type %d!\n", Z_TYPE_P(obj));
84                 break;
85         }
86
87         return NULL;
88 }
89
90 XmlDocPtrWrapper XML_Template_process_file(const char *input_filename, Directive *root_directive, bool clean)
91 {
92         xmlDocPtr ret = process_file(input_filename, root_directive, clean);
93         delete root_directive;
94         return XmlDocPtrWrapper(new XmlDocWrapper { ret });
95 }
96         
97 void output_to_fd(XmlDocPtrWrapper doc, int fd)
98 {
99         xmlOutputBufferPtr buf = xmlOutputBufferCreateFd(fd, NULL);
100         xmlSaveFileTo(buf, doc->ptr, NULL);
101 }
102
103 %}
104
105 %typemap(in) Directive* {
106         $1 = convert_php_objects_to_directive(*$input);
107 }
108
109 XmlDocPtrWrapper XML_Template_process_file(const char *input_filename, Directive *root_directive, bool clean);
110 void output_to_fd(XmlDocPtrWrapper doc, int fd);
111