X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=php5-swig%2Fxml-template.swig;fp=php5-swig%2Fxml-template.swig;h=0000000000000000000000000000000000000000;hb=3c53a0b7306711683492be3bd0c84bcb92902d4f;hp=458296ef994e6d782a6f854854d57c921816298d;hpb=7d1da52761b9ec9747c4400609658a379a34392c;p=xml-template diff --git a/php5-swig/xml-template.swig b/php5-swig/xml-template.swig deleted file mode 100644 index 458296e..0000000 --- a/php5-swig/xml-template.swig +++ /dev/null @@ -1,253 +0,0 @@ -%module XML_Template_SWIG -%include - -struct XmlDocPtrWrapper { - ~XmlDocPtrWrapper(); -}; - -%{ - -#include -#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_LONG: { - char str[256]; - snprintf(str, sizeof(str), "%ld", Z_LVAL_P(obj)); - return new Replace(str); - } - case IS_DOUBLE: { - char str[256]; - snprintf(str, sizeof(str), "%f", Z_DVAL_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)->ptr, 1)); - } - case IS_NULL: - return new Replace { "" }; - default: - printf("WARNING: Unknown type %d!\n", Z_TYPE_P(obj)); - break; - } - - return NULL; -} - -XmlDocPtrWrapper XML_Template_process_file(const std::string &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 XML_Template_process(XmlDocPtrWrapper doc, Directive *root_directive, bool clean) -{ - root_directive->process(xmlDocGetRootElement(doc->ptr), clean); - delete root_directive; -} - -namespace { - -int write_to_string(void *context, const char *buffer, int len) -{ - std::string *str = reinterpret_cast(context); - str->append(buffer, len); - return len; -} - -int close_string(void *context) -{ - return 0; -} - -} // namespace - -std::string XML_Template_convert_doc_to_string(XmlDocPtrWrapper doc, bool prettyprint) -{ - xmlIndentTreeOutput = prettyprint; - std::string ret; - xmlOutputBufferPtr buf = xmlOutputBufferCreateIO(write_to_string, close_string, &ret, NULL); - xmlSaveFormatFileTo(buf, doc->ptr, "UTF-8", prettyprint); - return ret; -} - -namespace { - -// Remove document fragments (ie. move their content up in the parent node) -// and combine neighboring text nodes into one. -void normalize_node(xmlNodePtr node) -{ - xmlNode *next_child; - for (xmlNode *child = node->children; child != NULL; child = next_child) { - next_child = child->next; - if (child->type == XML_DOCUMENT_FRAG_NODE) { - while (child->children != NULL) { - xmlAddPrevSibling(child, child->children); - } - - xmlUnlinkNode(child); - xmlFreeNode(child); - } - } - - // xmlAddPrevSibling merges adjacent text nodes, but many other things - // (including xmlUnlinkNode) do not, so make an extra pass. - for (xmlNode *child = node->children; child != NULL; child = child->next) { - while (child->type == XML_TEXT_NODE && (child->next != NULL && child->next->type == XML_TEXT_NODE)) { - xmlNode *next_child = child->next; - - xmlChar *content = xmlNodeGetContent(next_child); - xmlNodeAddContent(child, content); - xmlFree(content); - - xmlUnlinkNode(next_child); - xmlFreeNode(next_child); - } - normalize_node(child); - } -} - -// Clean the page of non-necessary whitespace. Leaves whitespace alone if and -// only if xml:space="preserve" on the element. (IOW, it doesn't parse the DTDs, -// nor the CSS.) -void clean_node(xmlNodePtr node, bool preserve_whitespace, bool aggressive) -{ - if (node->type == XML_TEXT_NODE) { - std::string content = reinterpret_cast(xmlNodeGetContent(node)); - if (!preserve_whitespace) { - unsigned dstpos = 0; - for (unsigned srcpos = 0; srcpos < content.size(); ++srcpos, ++dstpos) { - if (content[srcpos] == '\n' || - content[srcpos] == '\t' || - content[srcpos] == ' ') { - content[dstpos] = ' '; - - // compress double spaces - if (dstpos > 0 && content[dstpos - 1] == ' ') { - --dstpos; - } - } else { - content[dstpos] = content[srcpos]; - } - } - content.resize(dstpos); - } - if (content.empty() || (aggressive && content == " ")) { - xmlUnlinkNode(node); - xmlFreeNode(node); - } else { - xmlNodeSetContentLen(node, reinterpret_cast(content.data()), content.size()); - } - } else { - if (node->type == XML_ELEMENT_NODE) { - xmlChar *space = xmlGetProp(node, reinterpret_cast("xml:space")); - preserve_whitespace = (space != NULL && strcmp(reinterpret_cast(space), "preserve") == 0); - } - - xmlNode *next_child; - for (xmlNode *child = node->children; child != NULL; child = next_child) { - next_child = child->next; - clean_node(child, preserve_whitespace, aggressive); - } - - if (node->type == XML_ELEMENT_NODE && node->children == NULL) { - std::string tag = reinterpret_cast(node->name); - - // These are the only elements allowed in XHTML to be EMPTY, - // so insert dummy nodes to prevent the output from using - // the syntax where not appropriate. - if (tag != "base" && tag != "meta" && tag != "link" && tag != "hr" && - tag != "br" && tag != "param" && tag != "img" && tag != "area" && - tag != "input" && tag != "col") { - xmlNode *text = xmlNewText(reinterpret_cast("")); - xmlAddChild(node, text); - } - } - } -} - -} // namespace - -void XML_Template_clean_whitespace(XmlDocPtrWrapper doc, bool aggressive) -{ - normalize_node(xmlDocGetRootElement(doc->ptr)); - clean_node(xmlDocGetRootElement(doc->ptr), false, aggressive); -} - -%} - -%typemap(in) Directive* { - $1 = convert_php_objects_to_directive(*$input); -} - -XmlDocPtrWrapper XML_Template_process_file(const std::string &input_filename, Directive *root_directive, bool clean); -void XML_Template_process(XmlDocPtrWrapper doc, Directive *root_directive, bool clean); -void XML_Template_clean_whitespace(XmlDocPtrWrapper doc, bool aggressive); -std::string XML_Template_convert_doc_to_string(XmlDocPtrWrapper doc, bool prettyprint); -