summaryrefslogtreecommitdiff
path: root/ext/repo_appdata.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/repo_appdata.c')
-rw-r--r--ext/repo_appdata.c293
1 files changed, 79 insertions, 214 deletions
diff --git a/ext/repo_appdata.c b/ext/repo_appdata.c
index 2b9844e..62faf2d 100644
--- a/ext/repo_appdata.c
+++ b/ext/repo_appdata.c
@@ -14,20 +14,17 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <dirent.h>
-#include <expat.h>
#include <errno.h>
#include "pool.h"
#include "repo.h"
#include "util.h"
+#include "solv_xmlparser.h"
#include "repo_appdata.h"
@@ -53,15 +50,8 @@ enum state {
NUMSTATES
};
-struct stateswitch {
- enum state from;
- char *ename;
- enum state to;
- int docontent;
-};
-/* !! must be sorted by first column !! */
-static struct stateswitch stateswitches[] = {
+static struct solv_xmlparser_element stateswitches[] = {
{ STATE_START, "applications", STATE_START, 0 },
{ STATE_START, "components", STATE_START, 0 },
{ STATE_START, "application", STATE_APPLICATION, 0 },
@@ -86,23 +76,15 @@ static struct stateswitch stateswitches[] = {
};
struct parsedata {
- int depth;
- enum state state;
- int statedepth;
- char *content;
- int lcontent;
- int acontent;
- int docontent;
Pool *pool;
Repo *repo;
Repodata *data;
-
- struct stateswitch *swtab[NUMSTATES];
- enum state sbtab[NUMSTATES];
+ int ret;
Solvable *solvable;
Id handle;
+ int skiplang;
char *description;
int licnt;
int skip_depth;
@@ -111,74 +93,30 @@ struct parsedata {
int havesummary;
const char *filename;
Queue *owners;
-};
-
-static inline const char *
-find_attr(const char *txt, const char **atts)
-{
- for (; *atts; atts += 2)
- if (!strcmp(*atts, txt))
- return atts[1];
- return 0;
-}
+ struct solv_xmlparser xmlp;
+};
-static void XMLCALL
-startElement(void *userData, const char *name, const char **atts)
+static void
+startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
Solvable *s = pd->solvable;
- struct stateswitch *sw;
const char *type;
-#if 0
- fprintf(stderr, "start: [%d]%s\n", pd->state, name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth++;
- return;
- }
-
- pd->depth++;
- if (!pd->swtab[pd->state]) /* no statetable -> no substates */
- {
-#if 0
- fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state);
-#endif
- return;
- }
- for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */
- if (!strcmp(sw->ename, name))
- break;
-
- if (sw->from != pd->state)
- {
-#if 0
- fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state);
-#endif
- return;
- }
- pd->state = sw->to;
- pd->docontent = sw->docontent;
- pd->statedepth = pd->depth;
- pd->lcontent = 0;
- *pd->content = 0;
-
- if (!pd->skip_depth && find_attr("xml:lang", atts))
- pd->skip_depth = pd->depth;
- if (pd->skip_depth)
+ /* ignore all language tags */
+ if (pd->skiplang || solv_xmlparser_find_attr("xml:lang", atts))
{
- pd->docontent = 0;
+ pd->skiplang++;
return;
}
- switch(pd->state)
+ switch(state)
{
case STATE_APPLICATION:
- type = find_attr("type", atts);
+ type = solv_xmlparser_find_attr("type", atts);
if (!type || !*type)
type = "desktop";
if (strcmp(type, "desktop") != 0)
@@ -206,51 +144,55 @@ startElement(void *userData, const char *name, const char **atts)
/* replace whitespace with one space/newline */
/* also strip starting/ending whitespace */
-static void
+static char *
wsstrip(struct parsedata *pd)
{
+ struct solv_xmlparser *xmlp = &pd->xmlp;
int i, j;
int ws = 0;
- for (i = j = 0; pd->content[i]; i++)
+ for (i = j = 0; xmlp->content[i]; i++)
{
- if (pd->content[i] == ' ' || pd->content[i] == '\t' || pd->content[i] == '\n')
+ if (xmlp->content[i] == ' ' || xmlp->content[i] == '\t' || xmlp->content[i] == '\n')
{
- ws |= pd->content[i] == '\n' ? 2 : 1;
+ ws |= xmlp->content[i] == '\n' ? 2 : 1;
continue;
}
if (ws && j)
- pd->content[j++] = (ws & 2) ? '\n' : ' ';
+ xmlp->content[j++] = (ws & 2) ? '\n' : ' ';
ws = 0;
- pd->content[j++] = pd->content[i];
+ xmlp->content[j++] = xmlp->content[i];
}
- pd->content[j] = 0;
- pd->lcontent = j;
+ xmlp->content[j] = 0;
+ xmlp->lcontent = j;
+ return xmlp->content;
}
/* indent all lines */
-static void
+static char *
indent(struct parsedata *pd, int il)
{
+ struct solv_xmlparser *xmlp = &pd->xmlp;
int i, l;
- for (l = 0; pd->content[l]; )
+ for (l = 0; xmlp->content[l]; )
{
- if (pd->content[l] == '\n')
+ if (xmlp->content[l] == '\n')
{
l++;
continue;
}
- if (pd->lcontent + il + 1 > pd->acontent)
+ if (xmlp->lcontent + il + 1 > xmlp->acontent)
{
- pd->acontent = pd->lcontent + il + 256;
- pd->content = realloc(pd->content, pd->acontent);
+ xmlp->acontent = xmlp->lcontent + il + 256;
+ xmlp->content = realloc(xmlp->content, xmlp->acontent);
}
- memmove(pd->content + l + il, pd->content + l, pd->lcontent - l + 1);
+ memmove(xmlp->content + l + il, xmlp->content + l, xmlp->lcontent - l + 1);
for (i = 0; i < il; i++)
- pd->content[l + i] = ' ';
- pd->lcontent += il;
- while (pd->content[l] && pd->content[l] != '\n')
+ xmlp->content[l + i] = ' ';
+ xmlp->lcontent += il;
+ while (xmlp->content[l] && xmlp->content[l] != '\n')
l++;
}
+ return xmlp->content;
}
static void
@@ -346,47 +288,23 @@ guess_filename_from_id(Pool *pool, const char *id)
return r;
}
-static void XMLCALL
-endElement(void *userData, const char *name)
+static void
+endElement(struct solv_xmlparser *xmlp, int state, char *content)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
Solvable *s = pd->solvable;
Id id;
-#if 0
- fprintf(stderr, "end: [%d]%s\n", pd->state, name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth--;
-#if 0
- fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth);
-#endif
- return;
- }
-
- pd->depth--;
- pd->statedepth--;
-
- if (pd->skip_depth && pd->depth + 1 >= pd->skip_depth)
+ if (pd->skiplang)
{
- if (pd->depth + 1 == pd->skip_depth)
- pd->skip_depth = 0;
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
+ pd->skiplang--;
return;
}
- pd->skip_depth = 0;
-
if (!s)
- {
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
- return;
- }
+ return;
- switch (pd->state)
+ switch (state)
{
case STATE_APPLICATION:
if (!s->arch)
@@ -434,26 +352,26 @@ endElement(void *userData, const char *name)
pd->desktop_file = solv_free(pd->desktop_file);
break;
case STATE_ID:
- pd->desktop_file = solv_strdup(pd->content);
+ pd->desktop_file = solv_strdup(content);
break;
case STATE_NAME:
- s->name = pool_str2id(pd->pool, pool_tmpjoin(pool, "application:", pd->content, 0), 1);
+ s->name = pool_str2id(pd->pool, pool_tmpjoin(pool, "application:", content, 0), 1);
break;
case STATE_LICENCE:
- repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_LICENSE, pd->content);
+ repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_LICENSE, content);
break;
case STATE_SUMMARY:
pd->havesummary = 1;
- repodata_set_str(pd->data, pd->handle, SOLVABLE_SUMMARY, pd->content);
+ repodata_set_str(pd->data, pd->handle, SOLVABLE_SUMMARY, content);
break;
case STATE_URL:
- repodata_set_str(pd->data, pd->handle, SOLVABLE_URL, pd->content);
+ repodata_set_str(pd->data, pd->handle, SOLVABLE_URL, content);
break;
case STATE_GROUP:
- repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_GROUP, pd->content);
+ repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_GROUP, content);
break;
case STATE_EXTENDS:
- repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_EXTENDS, pd->content);
+ repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_EXTENDS, content);
break;
case STATE_DESCRIPTION:
if (pd->description)
@@ -466,83 +384,60 @@ endElement(void *userData, const char *name)
}
break;
case STATE_P:
- wsstrip(pd);
- pd->description = solv_dupappend(pd->description, pd->content, "\n\n");
+ content = wsstrip(pd);
+ pd->description = solv_dupappend(pd->description, content, "\n\n");
break;
case STATE_UL_LI:
wsstrip(pd);
- indent(pd, 4);
- pd->content[2] = '-';
- pd->description = solv_dupappend(pd->description, pd->content, "\n");
+ content = indent(pd, 4);
+ content[2] = '-';
+ pd->description = solv_dupappend(pd->description, content, "\n");
break;
case STATE_OL_LI:
wsstrip(pd);
- indent(pd, 4);
+ content = indent(pd, 4);
if (++pd->licnt >= 10)
- pd->content[0] = '0' + (pd->licnt / 10) % 10;
- pd->content[1] = '0' + pd->licnt % 10;
- pd->content[2] = '.';
- pd->description = solv_dupappend(pd->description, pd->content, "\n");
+ content[0] = '0' + (pd->licnt / 10) % 10;
+ content[1] = '0' + pd->licnt % 10;
+ content[2] = '.';
+ pd->description = solv_dupappend(pd->description, content, "\n");
break;
case STATE_UL:
case STATE_OL:
pd->description = solv_dupappend(pd->description, "\n", 0);
break;
case STATE_PKGNAME:
- id = pool_str2id(pd->pool, pd->content, 1);
+ id = pool_str2id(pd->pool, content, 1);
s->requires = repo_addid_dep(pd->repo, s->requires, id, 0);
- id = pool_str2id(pd->pool, pool_tmpjoin(pd->pool, "application-appdata(", pd->content, ")"), 1);
+ id = pool_str2id(pd->pool, pool_tmpjoin(pd->pool, "application-appdata(", content, ")"), 1);
s->provides = repo_addid_dep(pd->repo, s->provides, id, 0);
break;
case STATE_KEYWORD:
- repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_KEYWORDS, pd->content);
+ repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_KEYWORDS, content);
break;
default:
break;
}
-
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
-
-#if 0
- fprintf(stderr, "end: [%s] -> %d\n", name, pd->state);
-#endif
}
-
-static void XMLCALL
-characterData(void *userData, const XML_Char *s, int len)
+static void
+errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
{
- struct parsedata *pd = userData;
- int l;
- char *c;
- if (!pd->docontent)
- return;
- l = pd->lcontent + len + 1;
- if (l > pd->acontent)
- {
- pd->acontent = l + 256;
- pd->content = realloc(pd->content, pd->acontent);
+ struct parsedata *pd = xmlp->userdata;
+ pool_debug(pd->pool, SOLV_ERROR, "repo_appdata: %s at line %u:%u\n", errstr, line, column);
+ pd->ret = -1;
+ if (pd->solvable)
+ {
+ repo_free_solvable(pd->repo, pd->solvable - pd->pool->solvables, 1);
+ pd->solvable = 0;
}
- c = pd->content + pd->lcontent;
- pd->lcontent += len;
- while (len-- > 0)
- *c++ = *s++;
- *c = 0;
}
-#define BUFF_SIZE 8192
-
static int
repo_add_appdata_fn(Repo *repo, FILE *fp, int flags, const char *filename, Queue *owners)
{
- Pool *pool = repo->pool;
- struct parsedata pd;
- struct stateswitch *sw;
Repodata *data;
- char buf[BUFF_SIZE];
- int i, l;
- int ret = 0;
+ struct parsedata pd;
data = repo_add_repodata(repo, flags);
memset(&pd, 0, sizeof(pd));
@@ -553,47 +448,17 @@ repo_add_appdata_fn(Repo *repo, FILE *fp, int flags, const char *filename, Queue
pd.filename = filename;
pd.owners = owners;
- pd.content = malloc(256);
- pd.acontent = 256;
-
- for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
- {
- if (!pd.swtab[sw->from])
- pd.swtab[sw->from] = sw;
- pd.sbtab[sw->to] = sw->from;
- }
-
- XML_Parser parser = XML_ParserCreate(NULL);
- XML_SetUserData(parser, &pd);
- XML_SetElementHandler(parser, startElement, endElement);
- XML_SetCharacterDataHandler(parser, characterData);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
+ solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_free(&pd.xmlp);
- for (;;)
- {
- l = fread(buf, 1, sizeof(buf), fp);
- if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
- {
- pool_error(pool, -1, "repo_appdata: %s at line %u:%u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser));
- if (pd.solvable)
- {
- repo_free_solvable(repo, pd.solvable - pd.pool->solvables, 1);
- pd.solvable = 0;
- }
- ret = -1;
- break;
- }
- if (l == 0)
- break;
- }
- XML_ParserFree(parser);
+ solv_free(pd.desktop_file);
+ solv_free(pd.description);
if (!(flags & REPO_NO_INTERNALIZE))
repodata_internalize(data);
- solv_free(pd.content);
- solv_free(pd.desktop_file);
- solv_free(pd.description);
- return ret;
+ return pd.ret;
}
int