]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
Allow to build with libxml2 instead of libexpat
authorMichael Schroeder <mls@suse.de>
Fri, 24 Feb 2017 14:20:40 +0000 (15:20 +0100)
committerMichael Schroeder <mls@suse.de>
Fri, 24 Feb 2017 14:20:40 +0000 (15:20 +0100)
libxml2 seems to be a tiny bit faster...

CMakeLists.txt
ext/solv_xmlparser.c

index 615538b237614fdc032bb414fb530c1453fdeefc..0da4da6d0c7e1cb380822eab4e0b8dd1e27d9b52 100644 (file)
@@ -32,6 +32,8 @@ OPTION (MULTI_SEMANTICS "Build with support for multiple distribution types?" OF
 OPTION (ENABLE_LZMA_COMPRESSION "Build with lzma/xz compression support?" OFF)
 OPTION (ENABLE_BZIP2_COMPRESSION "Build with bzip2 compression support?" OFF)
 
+OPTION (ENABLE_LIBXML2 "Build with libxml2 instead of libexpat?" OFF)
+
 #IF(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERISION} GREATER 2.4)
 #ENDIF(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERISION} GREATER 2.4)
 
@@ -159,8 +161,13 @@ SET (ENABLE_LZMA_COMPRESSION ON)
 ENDIF (ENABLE_ARCHREPO)
 
 IF (ENABLE_RPMMD OR ENABLE_SUSEREPO OR ENABLE_APPDATA OR ENABLE_COMPS OR ENABLE_HELIXREPO OR ENABLE_MDKREPO)
+IF (ENABLE_LIBXML2)
+FIND_PACKAGE (LibXml2 REQUIRED)
+INCLUDE_DIRECTORIES (${LIBXML2_INCLUDE_DIR})
+ELSE(ENABLE_LIBXML2)
 FIND_PACKAGE (EXPAT REQUIRED)
 INCLUDE_DIRECTORIES (${EXPAT_INCLUDE_DIRS})
+ENDIF (ENABLE_LIBXML2)
 ENDIF (ENABLE_RPMMD OR ENABLE_SUSEREPO OR ENABLE_APPDATA OR ENABLE_COMPS OR ENABLE_HELIXREPO OR ENABLE_MDKREPO)
 
 IF (ENABLE_ZLIB_COMPRESSION)
@@ -258,7 +265,7 @@ ENDIF (${CMAKE_MAJOR_VERSION} GREATER 2)
 
 # should create config.h with #cmakedefine instead...
 FOREACH (VAR HAVE_STRCHRNUL HAVE_FOPENCOOKIE HAVE_FUNOPEN WORDS_BIGENDIAN
-  HAVE_RPM_DB_H HAVE_PGPDIGGETPARAMS)
+  HAVE_RPM_DB_H HAVE_PGPDIGGETPARAMS ENABLE_LIBXML2)
   IF(${VAR})
     ADD_DEFINITIONS (-D${VAR}=1)
     SET (SWIG_FLAGS ${SWIG_FLAGS} -D${VAR})
@@ -367,7 +374,12 @@ set (CMAKE_C_FLAGS_DEBUG     "${CMAKE_C_FLAGS} -g3 -O0")
 # set system libraries
 SET (SYSTEM_LIBRARIES "")
 IF (ENABLE_RPMMD OR ENABLE_SUSEREPO OR ENABLE_APPDATA OR ENABLE_COMPS OR ENABLE_HELIXREPO OR ENABLE_MDKREPO)
+IF (ENABLE_LIBXML2)
+SET (SYSTEM_LIBRARIES ${SYSTEM_LIBRARIES} ${LIBXML2_LIBRARIES})
+ELSE (ENABLE_LIBXML2)
 SET (SYSTEM_LIBRARIES ${SYSTEM_LIBRARIES} ${EXPAT_LIBRARY})
+ENDIF (ENABLE_LIBXML2)
+
 ENDIF (ENABLE_RPMMD OR ENABLE_SUSEREPO OR ENABLE_APPDATA OR ENABLE_COMPS OR ENABLE_HELIXREPO OR ENABLE_MDKREPO)
 IF (ENABLE_ZLIB_COMPRESSION)
 SET (SYSTEM_LIBRARIES ${SYSTEM_LIBRARIES} ${ZLIB_LIBRARY})
index f28d168daaaa4052b4e66f184c17297f0b0a325b..d80e6c5fbeb944dd36a0262161120ff5000800cd 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
+#ifdef ENABLE_LIBXML2
+#include <libxml/parser.h>
+#else
 #include <expat.h>
+#endif
 
 #include "util.h"
 #include "queue.h"
@@ -31,23 +35,31 @@ add_contentspace(struct solv_xmlparser *xmlp, int l)
     }    
 }
 
+
+#ifdef ENABLE_LIBXML2
+static void
+character_data(void *userData, const xmlChar *s, int len)
+#else
 static void XMLCALL
-characterData(void *userData, const XML_Char *s, int len) 
+character_data(void *userData, const XML_Char *s, int len) 
+#endif
 {
   struct solv_xmlparser *xmlp = userData;
-  char *c;
 
-  if (!xmlp->docontent)
+  if (!xmlp->docontent || !len)
     return;
   add_contentspace(xmlp, len);
-  c = xmlp->content + xmlp->lcontent;
+  memcpy(xmlp->content + xmlp->lcontent, s, len);
   xmlp->lcontent += len; 
-  while (len-- > 0) 
-    *c++ = *s++;
 }
 
+#ifdef ENABLE_LIBXML2
+static void
+start_element(void *userData, const xmlChar *name, const xmlChar **atts)
+#else
 static void XMLCALL
-startElement(void *userData, const char *name, const char **atts)
+start_element(void *userData, const char *name, const char **atts)
+#endif
 {
   struct solv_xmlparser *xmlp = userData;
   struct solv_xmlparser_element *elements;
@@ -64,7 +76,7 @@ startElement(void *userData, const char *name, const char **atts)
   elements = xmlp->elements;
   oldstate = xmlp->state;
   for (i = elementhelper[xmlp->nelements + oldstate]; i; i = elementhelper[i - 1])
-    if (!strcmp(elements[i - 1].element, name))
+    if (!strcmp(elements[i - 1].element, (char *)name))
       break;
   if (!i)
     {
@@ -79,12 +91,24 @@ startElement(void *userData, const char *name, const char **atts)
   xmlp->state = el->tostate;
   xmlp->docontent = el->docontent;
   xmlp->lcontent = 0;
+#ifdef ENABLE_LIBXML2
+  if (!atts)
+    {
+      static const char *nullattr;
+      atts = (const xmlChar **)&nullattr;
+    }
+#endif
   if (xmlp->state != oldstate)
-    xmlp->startelement(xmlp, xmlp->state, el->element, atts);
+    xmlp->startelement(xmlp, xmlp->state, el->element, (const char **)atts);
 }
 
+#ifdef ENABLE_LIBXML2
+static void
+end_element(void *userData, const xmlChar *name)
+#else
 static void XMLCALL
-endElement(void *userData, const char *name)
+end_element(void *userData, const char *name)
+#endif
 {
   struct solv_xmlparser *xmlp = userData;
 
@@ -148,12 +172,6 @@ solv_xmlparser_init(struct solv_xmlparser *xmlp,
   xmlp->errorhandler = errorhandler;
 }
 
-unsigned int
-solv_xmlparser_lineno(struct solv_xmlparser *xmlp)
-{
-  return (unsigned int)XML_GetCurrentLineNumber(xmlp->parser);
-}
-
 void
 solv_xmlparser_free(struct solv_xmlparser *xmlp)
 {
@@ -162,6 +180,107 @@ solv_xmlparser_free(struct solv_xmlparser *xmlp)
   xmlp->content = solv_free(xmlp->content);
 }
 
+#ifdef ENABLE_LIBXML2
+
+static inline int
+create_parser(struct solv_xmlparser *xmlp)
+{
+  /* delayed to parse_block so that we have the first bytes */
+  return 1;
+}
+
+static inline void
+free_parser(struct solv_xmlparser *xmlp)
+{
+  if (xmlp->parser)
+    xmlFreeParserCtxt(xmlp->parser);
+  xmlp->parser = 0;
+}
+
+static xmlParserCtxtPtr create_parser_ctx(struct solv_xmlparser *xmlp, char *buf, int l)
+{
+  xmlSAXHandler sax;
+  memset(&sax, 0, sizeof(sax));
+  sax.startElement = start_element;
+  sax.endElement = end_element;
+  sax.characters = character_data;
+  return xmlCreatePushParserCtxt(&sax, xmlp, buf, l, NULL);
+}
+
+static inline int
+parse_block(struct solv_xmlparser *xmlp, char *buf, int l)
+{
+  if (!xmlp->parser)
+    {
+      int l2 = l > 4 ? 4 : 0;
+      xmlp->parser = create_parser_ctx(xmlp, buf, l2);
+      if (!xmlp->parser)
+       {
+         xmlp->errorhandler(xmlp, "could not create parser", 0, 0);
+         return 0;
+       }
+      buf += l2;
+      l -= l2;
+      if (l2 && !l)
+       return 1;
+    }
+  if (xmlParseChunk(xmlp->parser, buf, l, l == 0 ? 1 : 0))
+    {
+      xmlErrorPtr err = xmlCtxtGetLastError(xmlp->parser);
+      xmlp->errorhandler(xmlp, err->message, err->line, err->int2);
+      return 0;
+    }
+  return 1;
+}
+
+unsigned int
+solv_xmlparser_lineno(struct solv_xmlparser *xmlp)
+{
+  return (unsigned int)xmlSAX2GetLineNumber(xmlp->parser);
+}
+
+#else
+
+static inline int
+create_parser(struct solv_xmlparser *xmlp)
+{
+  xmlp->parser = XML_ParserCreate(NULL);
+  if (!xmlp->parser)
+    return 0;
+  XML_SetUserData(xmlp->parser, xmlp);
+  XML_SetElementHandler(xmlp->parser, start_element, end_element);
+  XML_SetCharacterDataHandler(xmlp->parser, character_data);
+  return 1;
+}
+
+static inline void
+free_parser(struct solv_xmlparser *xmlp)
+{
+  XML_ParserFree(xmlp->parser);
+  xmlp->parser = 0;
+}
+
+static inline int
+parse_block(struct solv_xmlparser *xmlp, char *buf, int l)
+{
+  if (XML_Parse(xmlp->parser, buf, l, l == 0) == XML_STATUS_ERROR)
+    {
+      unsigned int line = XML_GetCurrentLineNumber(xmlp->parser);
+      unsigned int column = XML_GetCurrentColumnNumber(xmlp->parser);
+      xmlp->errorhandler(xmlp, XML_ErrorString(XML_GetErrorCode(xmlp->parser)), line, column);
+      return 0;
+    }
+  return 1;
+}
+
+unsigned int
+solv_xmlparser_lineno(struct solv_xmlparser *xmlp)
+{
+  return (unsigned int)XML_GetCurrentLineNumber(xmlp->parser);
+}
+
+#endif
+
 void
 solv_xmlparser_parse(struct solv_xmlparser *xmlp, FILE *fp)
 {
@@ -173,26 +292,19 @@ solv_xmlparser_parse(struct solv_xmlparser *xmlp, FILE *fp)
   xmlp->docontent = 0;
   xmlp->lcontent = 0;
   queue_empty(&xmlp->elementq);
-  xmlp->parser = XML_ParserCreate(NULL);
-  XML_SetUserData(xmlp->parser, xmlp);
-  XML_SetElementHandler(xmlp->parser, startElement, endElement);
-  XML_SetCharacterDataHandler(xmlp->parser, characterData);
 
+  if (!create_parser(xmlp))
+    {
+      xmlp->errorhandler(xmlp, "could not create xml parser", 0, 0);
+      return;
+    }
   for (;;)
     {
       l = fread(buf, 1, sizeof(buf), fp);
-      if (XML_Parse(xmlp->parser, buf, l, l == 0) == XML_STATUS_ERROR)
-       {
-         unsigned int line = XML_GetCurrentLineNumber(xmlp->parser);
-         unsigned int column = XML_GetCurrentColumnNumber(xmlp->parser);
-         xmlp->errorhandler(xmlp, XML_ErrorString(XML_GetErrorCode(xmlp->parser)), line, column);
-         break;
-       }
-      if (l == 0)
+      if (!parse_block(xmlp, buf, l) || !l)
        break;
     }
-  XML_ParserFree(xmlp->parser);
-  xmlp->parser = 0;
+  free_parser(xmlp);
 }
 
 char *