[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