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