[Yum-devel] [PATCH 2/5] Add xml parsing for primary delta files

James Bowes jbowes at redhat.com
Mon Jun 11 12:16:32 UTC 2007


Primary delta xml files are of the form:

<metadata packages="TOTAL CHANGED">
  <additions>
    PACKAGE_DATA_FROM_PRIMARY
  </additions>
  <removals>
    <package pkgid="ID" name="NAME" arch="ARCH" />
    ...
  </removals>
</metadata>
---
 xml-parser.c |  201 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 xml-parser.h |    7 ++
 2 files changed, 205 insertions(+), 3 deletions(-)

diff --git a/xml-parser.c b/xml-parser.c
index 32d6d53..7668c48 100644
--- a/xml-parser.c
+++ b/xml-parser.c
@@ -587,9 +587,6 @@ yum_xml_parse_primary (const char *filename,
     g_string_free (sctx.text_buffer, TRUE);
 }
 
-/*****************************************************************************/
-
-
 static void
 parse_package (const char **attrs, Package *p)
 {
@@ -611,6 +608,204 @@ parse_package (const char **attrs, Package *p)
 }
 
 typedef enum {
+    DELTA_PARSER_TOPLEVEL = 0,
+    DELTA_PARSER_ADDITIONS,
+    DELTA_PARSER_REMOVALS,
+} DeltaSAXContextState;
+
+typedef struct {
+    PrimarySAXContext pctx;
+    DeltaSAXContextState state;
+    PackageFn package_removal_fn;
+} PrimaryDeltaSAXContext;
+
+static void
+primary_delta_parser_toplevel_start (PrimaryDeltaSAXContext *ctx,
+                                     const char *name,
+                                     const char **attrs)
+{
+    SAXContext *sctx = &(&ctx->pctx)->sctx;
+
+    if (!strcmp (name, "additions")) {
+        ctx->state = DELTA_PARSER_ADDITIONS;
+    }
+    else if (!strcmp (name, "removals")) {
+        ctx->state = DELTA_PARSER_REMOVALS;
+    }
+
+    else if (sctx->count_fn && !strcmp (name, "metadata")) {
+        int i;
+        const char *attr;
+        const char *value;
+
+        for (i = 0; attrs && attrs[i]; i++) {
+            attr = attrs[i];
+            value = attrs[++i];
+
+            if (!strcmp (attr, "packages")) {
+                sctx->count_fn (string_to_guint32_with_default (value, 0),
+                               sctx->user_data);
+                break;
+            }
+        }
+    }
+}
+
+static void
+delta_parser_removals_start (SAXContext *sctx,
+                             const char *name,
+                             const char **attrs)
+{
+    if (!strcmp (name, "package")) {
+        sctx->current_package = package_new ();
+        parse_package (attrs, sctx->current_package);
+    }
+}
+
+static void
+primary_delta_sax_start_element (void *data, const char *name,
+                                 const char **attrs)
+{
+    PrimaryDeltaSAXContext *ctx = (PrimaryDeltaSAXContext *) data;
+    SAXContext *sctx = &(&ctx->pctx)->sctx;
+
+    if (sctx->text_buffer->len)
+        g_string_truncate (sctx->text_buffer, 0);
+
+    switch (ctx->state) {
+    case DELTA_PARSER_TOPLEVEL:
+        primary_delta_parser_toplevel_start (ctx, name, attrs);
+        break;
+    case DELTA_PARSER_REMOVALS:
+        delta_parser_removals_start (sctx, name, attrs);
+        break;
+    case DELTA_PARSER_ADDITIONS:
+        primary_sax_start_element (&ctx->pctx, name, attrs);
+        break;
+    default:
+        break;
+    }
+}
+
+static void
+primary_delta_parser_removals_end (PrimaryDeltaSAXContext *ctx,
+                                   const char *name)
+{
+    if (!strcmp (name, "package")) {
+        SAXContext *sctx = &(&ctx->pctx)->sctx;
+
+        Package *p = sctx->current_package;
+        g_assert (p != NULL);
+
+        if (ctx->package_removal_fn && !*sctx->error)
+            ctx->package_removal_fn (p, sctx->user_data);
+
+        package_free (p);
+        sctx->current_package = NULL;
+
+        sctx->want_text = FALSE;
+    }
+    else if (!strcmp (name, "removals")) {
+        ctx->state = DELTA_PARSER_TOPLEVEL;
+    }
+}
+
+static void
+primary_delta_sax_end_element (void *data, const char *name)
+{
+    PrimaryDeltaSAXContext *ctx = (PrimaryDeltaSAXContext *) data;
+    SAXContext *sctx = &(&ctx->pctx)->sctx;
+
+    switch (ctx->state) {
+    case DELTA_PARSER_ADDITIONS:
+        if (ctx->pctx.state == PRIMARY_PARSER_TOPLEVEL) {
+            if (!strcmp (name, "additions"))
+                ctx->state = DELTA_PARSER_TOPLEVEL;
+        }
+        else
+            primary_sax_end_element (&ctx->pctx, name);
+        break;
+    case DELTA_PARSER_REMOVALS:
+        primary_delta_parser_removals_end (ctx, name);
+        break;
+    default:
+        break;
+    }
+
+    g_string_truncate (sctx->text_buffer, 0);
+}
+
+static xmlSAXHandler primary_delta_sax_handler = {
+    NULL,      /* internalSubset */
+    NULL,      /* isStandalone */
+    NULL,      /* hasInternalSubset */
+    NULL,      /* hasExternalSubset */
+    NULL,      /* resolveEntity */
+    NULL,      /* getEntity */
+    NULL,      /* entityDecl */
+    NULL,      /* notationDecl */
+    NULL,      /* attributeDecl */
+    NULL,      /* elementDecl */
+    NULL,      /* unparsedEntityDecl */
+    NULL,      /* setDocumentLocator */
+    NULL,      /* startDocument */
+    NULL,      /* endDocument */
+    (startElementSAXFunc) primary_delta_sax_start_element, /* startElement */
+    (endElementSAXFunc) primary_delta_sax_end_element,     /* endElement */
+    NULL,      /* reference */
+    (charactersSAXFunc) sax_characters,      /* characters */
+    NULL,      /* ignorableWhitespace */
+    NULL,      /* processingInstruction */
+    NULL,      /* comment */
+    sax_warning,      /* warning */
+    sax_error,      /* error */
+    sax_error,      /* fatalError */
+};
+
+void
+yum_xml_parse_primary_delta (const char *filename,
+                             CountFn count_callback,
+                             PackageFn package_addition_callback,
+                             PackageFn package_removal_callback,
+                             gpointer user_data,
+                             GError **err)
+{
+    PrimaryDeltaSAXContext ctx;
+    PrimarySAXContext pctx;
+    SAXContext sctx;
+    int rc;
+
+    sctx.md_type = "primary-delta.xml";
+    sctx.error = err;
+    sctx.count_fn = count_callback;
+    sctx.package_fn = package_addition_callback;
+    sctx.user_data = user_data;
+    sctx.current_package = NULL;
+    sctx.want_text = FALSE;
+    sctx.text_buffer = g_string_sized_new (PACKAGE_FIELD_SIZE);
+
+    pctx.current_dep_list = NULL;
+    pctx.current_file = NULL;
+    pctx.state = PRIMARY_PARSER_TOPLEVEL;
+    pctx.sctx = sctx;
+
+    ctx.state = DELTA_PARSER_TOPLEVEL;
+    ctx.package_removal_fn = package_removal_callback;
+    ctx.pctx = pctx;
+
+    xmlSubstituteEntitiesDefault (1);
+    rc = xmlSAXUserParseFile (&primary_delta_sax_handler, &ctx, filename);
+
+    if (sctx.current_package) {
+        g_warning ("Incomplete package lost");
+        package_free (sctx.current_package);
+    }
+
+    g_string_free (sctx.text_buffer, TRUE);
+}
+/*****************************************************************************/
+
+typedef enum {
     FILELIST_PARSER_TOPLEVEL = 0,
     FILELIST_PARSER_PACKAGE,
 } FilelistSAXContextState;
diff --git a/xml-parser.h b/xml-parser.h
index fa2c07d..6461628 100644
--- a/xml-parser.h
+++ b/xml-parser.h
@@ -32,6 +32,13 @@ yum_xml_parse_primary (const char *filename,
                        gpointer user_data,
                        GError **err);
 
+void yum_xml_parse_primary_delta (const char *filename,
+                                  CountFn count_callback,
+                                  PackageFn package_addition_callback,
+                                  PackageFn package_removal_callback,
+                                  gpointer user_data,
+                                  GError **err);
+
 void
 yum_xml_parse_filelists (const char *filename,
                          CountFn count_callback,
-- 
1.5.2.1.938.gac3b4




More information about the Yum-devel mailing list