libxml2_globals::~libxml2_globals() { // Restore the old libxml2 callback functions. xmlRegisterNodeDefault(old_register_node_fn_); xmlDeregisterNodeDefault(old_deregister_node_fn_); xmlThrDefRegisterNodeDefault(old_thr_def_register_node_fn_); xmlThrDefDeregisterNodeDefault(old_thr_def_deregister_node_fn_); // // According to the libxml2 document on xmlCleanupParser(): // // This function... does not clean up parser state, it cleans up memory allocated by the // library itself. It is a cleanup function for the XML library. It tries to reclaim all // related global memory allocated for the library processing. It doesn't deallocate any // document related memory. One should call xmlCleanupParser() only when the process has // finished using the library and all XML/HTML documents built with it. // ... // WARNING: if your application is multi-threaded or has plugin support, calling this may // crash the application if another thread or a plugin is still using libxml2... In case of // doubt abstain from calling this function or do it just before calling exit() to avoid // leak reports from Valgrind! // if (cleanup_parser_) { xmlCleanupParser(); } }
static void dealloc(xmlDocPtr doc) { NOKOGIRI_DEBUG_START(doc); st_table *node_hash = DOC_UNLINKED_NODE_HASH(doc); xmlDeregisterNodeFunc func = xmlDeregisterNodeDefault(NULL); st_foreach(node_hash, dealloc_node_i, (st_data_t)doc); st_free_table(node_hash); free(doc->_private); doc->_private = NULL; xmlFreeDoc(doc); xmlDeregisterNodeDefault(func); NOKOGIRI_DEBUG_END(doc); }
//#if !EPUB_COMPILER(MSVC) //__attribute__((destructor)) //#endif void __resetLibXMLOverrides(void) { xmlRegisterNodeDefault(defNodeRegister); xmlThrDefRegisterNodeDefault(defThrNodeRegister); xmlDeregisterNodeDefault(defNodeDeregister); xmlThrDefDeregisterNodeDefault(defThrNodeDeregister); xmlSubstituteEntitiesDefault(0); xmlLoadExtDtdDefaultValue = 0; }
//------------------------------------------------------------------------------ LibXmlSentry::LibXmlSentry() { if (use_count == 0) { xmlInitParser(); xmlRegisterNodeDefault(wrap_node); xmlDeregisterNodeDefault(free_wrapper); xmlThrDefRegisterNodeDefault(wrap_node); xmlThrDefDeregisterNodeDefault(free_wrapper); } use_count++; }
//INITIALIZER(__setupLibXML) void __setupLibXML(void) { xmlInitGlobals(); defNodeRegister = xmlRegisterNodeDefault(&__registerNode); defThrNodeDeregister = xmlThrDefRegisterNodeDefault(&__registerNodeThr); defNodeDeregister = xmlDeregisterNodeDefault(&__deregisterNode); defThrNodeDeregister = xmlThrDefDeregisterNodeDefault(&__deregisterNodeThr); xmlSubstituteEntitiesDefault(1); xmlLoadExtDtdDefaultValue = 1; //#if EPUB_COMPILER(MSVC) // atexit(__resetLibXMLOverrides); //#endif }
static void dealloc(xmlDocPtr doc) { NOKOGIRI_DEBUG_START(doc); nokogiriTuplePtr tuple = doc->_private; xmlNodeSetPtr node_set = tuple->unlinkedNodes; xmlDeregisterNodeFunc func = xmlDeregisterNodeDefault(NULL); int j ; for(j = 0 ; j < node_set->nodeNr ; j++) { xmlNodePtr node = node_set->nodeTab[j]; switch(node->type) { case XML_ATTRIBUTE_NODE: xmlFreePropList((xmlAttrPtr)node); break; default: if(node->parent == NULL) { xmlAddChild((xmlNodePtr)doc, node); } } } if (node_set->nodeTab != NULL) xmlFree(node_set->nodeTab); xmlFree(node_set); free(doc->_private); doc->_private = NULL; xmlFreeDoc(doc); xmlDeregisterNodeDefault(func); NOKOGIRI_DEBUG_END(doc); }
libxml2_globals::libxml2_globals(): old_register_node_fn_(0) , old_deregister_node_fn_(0) , old_thr_def_register_node_fn_(0) , old_thr_def_deregister_node_fn_(0) , cleanup_parser_(false) { // Initialize libxml2 resources. LIBXML_TEST_VERSION; xmlInitParser(); // Register libxml2 callback functions, and save the old ones. old_register_node_fn_ = xmlRegisterNodeDefault(&on_node_construct); old_deregister_node_fn_ = xmlDeregisterNodeDefault(&on_node_destruct); old_thr_def_register_node_fn_ = xmlThrDefRegisterNodeDefault(&on_node_construct); old_thr_def_deregister_node_fn_ = xmlThrDefDeregisterNodeDefault(&on_node_destruct); // Libxml2 global initialization. xmlSubstituteEntitiesDefault(1); xmlLoadExtDtdDefaultValue = 1; }
/** * Loop through array of operations and perform them */ static void edProcess(xmlDocPtr doc, const XmlEdAction* ops, int ops_count) { int k; xmlXPathContextPtr ctxt = xmlXPathNewContext(doc); /* NOTE: later registrations override earlier ones */ registerXstarNs(ctxt); /* variables */ previous_insertion = xmlXPathNodeSetCreate(NULL); registerXstarVariable(ctxt, "prev", xmlXPathWrapNodeSet(previous_insertion)); xmlDeregisterNodeDefault(&removeNodeFromPrev); #if HAVE_EXSLT_XPATH_REGISTER /* register extension functions */ exsltDateXpathCtxtRegister(ctxt, BAD_CAST "date"); exsltMathXpathCtxtRegister(ctxt, BAD_CAST "math"); exsltSetsXpathCtxtRegister(ctxt, BAD_CAST "set"); exsltStrXpathCtxtRegister(ctxt, BAD_CAST "str"); #endif /* namespaces from doc */ extract_ns_defs(doc, ctxt); /* namespaces from command line */ nsarr_xpath_register(ctxt); for (k = 0; k < ops_count; k++) { xmlXPathObjectPtr res; xmlNodeSetPtr nodes; /* NOTE: to make relative paths match as if from "/", set context to document; setting to root would match as if from "/node()/" */ ctxt->node = (xmlNodePtr) doc; if (ops[k].op == XML_ED_VAR) { res = xmlXPathEvalExpression(BAD_CAST ops[k].arg2, ctxt); xmlXPathRegisterVariable(ctxt, BAD_CAST ops[k].arg1, res); continue; } res = xmlXPathEvalExpression(BAD_CAST ops[k].arg1, ctxt); if (!res || res->type != XPATH_NODESET || !res->nodesetval) continue; nodes = res->nodesetval; switch (ops[k].op) { case XML_ED_DELETE: edDelete(doc, nodes); break; case XML_ED_MOVE: { xmlXPathObjectPtr res_to; ctxt->node = (xmlNodePtr) doc; res_to = xmlXPathEvalExpression(BAD_CAST ops[k].arg2, ctxt); if (!res_to || res_to->type != XPATH_NODESET || res_to->nodesetval->nodeNr != 1) { fprintf(stderr, "move destination is not a single node\n"); continue; } edMove(doc, nodes, res_to->nodesetval->nodeTab[0]); xmlXPathFreeObject(res_to); break; } case XML_ED_UPDATE: edUpdate(doc, nodes, ops[k].arg2, ops[k].type, ctxt); break; case XML_ED_RENAME: edRename(doc, nodes, ops[k].arg2, ops[k].type); break; case XML_ED_INSERT: edInsert(doc, nodes, ops[k].arg2, ops[k].arg3, ops[k].type, -1); break; case XML_ED_APPEND: edInsert(doc, nodes, ops[k].arg2, ops[k].arg3, ops[k].type, 1); break; case XML_ED_SUBNODE: edInsert(doc, nodes, ops[k].arg2, ops[k].arg3, ops[k].type, 0); break; default: break; } xmlXPathFreeObject(res); } /* NOTE: free()ing ctxt also free()s previous_insertion */ previous_insertion = NULL; xmlDeregisterNodeDefault(NULL); xmlXPathFreeContext(ctxt); }