%module XML_Template_SWIG struct XmlDocPtrWrapper { ~XmlDocPtrWrapper(); }; %{ #include #include "../c++11/xml-template.h" struct XmlDocWrapper { ~XmlDocWrapper() { xmlFreeDoc(ptr); } xmlDocPtr ptr; }; typedef std::shared_ptr XmlDocPtrWrapper; bool is_associative_array(HashTable *ht) { if (ht->nNumOfElements == 0) { return true; } for (unsigned i = 0; i < ht->nNumOfElements; ++i) { if (!zend_hash_index_exists(ht, i)) { return true; } } return false; } Directive* convert_php_objects_to_directive(zval *obj) { switch (Z_TYPE_P(obj)) { case IS_ARRAY: { HashTable *ht = Z_ARRVAL_P(obj); if (is_associative_array(ht)) { std::unordered_map my_map; for (zend_hash_internal_pointer_reset(ht); zend_hash_has_more_elements(ht) == SUCCESS; zend_hash_move_forward(ht)) { char *str_key; ulong num_key; zend_hash_get_current_key(ht, &str_key, &num_key, 0); std::string key; if (zend_hash_get_current_key_type(ht) == HASH_KEY_IS_STRING) { key = str_key; } else { char buf[32]; sprintf(buf, "%lu", num_key); key = buf; } zval **data; zend_hash_get_current_data(ht, (void **)&data); my_map.insert(make_pair(key, convert_php_objects_to_directive(*data))); } return new Substitute(my_map); } else { std::vector subdirectives; for (unsigned i = 0; i < ht->nNumOfElements; ++i) { zval **data; zend_hash_index_find(ht, i, (void **)&data); subdirectives.push_back(convert_php_objects_to_directive(*data)); } return new Clone(subdirectives); } break; } case IS_STRING: { char *str = Z_STRVAL_P(obj); return new Replace(str); } case IS_RESOURCE: { XmlDocPtrWrapper *doc; if (SWIG_ConvertPtr(obj, (void **)&doc, SWIGTYPE_p_XmlDocPtrWrapper, 0) < 0 || doc == NULL) { return NULL; } return new ReplaceInclude(xmlCopyDoc(doc->get()->ptr, 1)); } case IS_NULL: return NULL; default: printf("WARNING: Unknown type %d!\n", Z_TYPE_P(obj)); break; } return NULL; } XmlDocPtrWrapper XML_Template_process_file(const char *input_filename, Directive *root_directive, bool clean) { xmlDocPtr ret = process_file(input_filename, root_directive, clean); delete root_directive; return XmlDocPtrWrapper(new XmlDocWrapper { ret }); } void output_to_fd(XmlDocPtrWrapper doc, int fd) { xmlOutputBufferPtr buf = xmlOutputBufferCreateFd(fd, NULL); xmlSaveFileTo(buf, doc->ptr, NULL); } %} %typemap(in) Directive* { $1 = convert_php_objects_to_directive(*$input); } XmlDocPtrWrapper XML_Template_process_file(const char *input_filename, Directive *root_directive, bool clean); void output_to_fd(XmlDocPtrWrapper doc, int fd);