%module XML_Template_SWIG %{ #include "../c++11/xml-template.h" bool is_associative_array(HashTable *ht) { if (ht->nNumOfElements == 0) { return true; } for (unsigned i = 0; i < ht->nNumOfElements; ++i) { char buf[32]; sprintf(buf, "%u", i); if (!zend_hash_exists(ht, buf, strlen(buf))) { 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 { printf("ARRAY\n"); } break; } case IS_STRING: { char *str = Z_STRVAL_P(obj); return new Replace(str); } default: printf("WARNING: Unknown type %d!\n", Z_TYPE_P(obj)); break; } return NULL; } %} %typemap(in) Directive* { $1 = convert_php_objects_to_directive(*$input); } xmlDocPtr process_file(const char *input_filename, Directive *root_directive, bool clean); void output_to_fd_and_free(xmlDocPtr doc, int fd);