summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/repo_appdata.c22
-rw-r--r--ext/repo_arch.c5
-rw-r--r--ext/repo_comps.c13
-rw-r--r--ext/repo_content.c3
-rw-r--r--ext/repo_cudf.c15
-rw-r--r--ext/repo_deb.c4
-rw-r--r--ext/repo_deltainfoxml.c12
-rw-r--r--ext/repo_helix.c14
-rw-r--r--ext/repo_mdk.c15
-rw-r--r--ext/repo_products.c21
-rw-r--r--ext/repo_repomdxml.c13
-rw-r--r--ext/repo_rpmdb.c7
-rw-r--r--ext/repo_rpmmd.c12
-rw-r--r--ext/repo_updateinfoxml.c12
-rw-r--r--ext/repo_zyppdb.c20
-rw-r--r--ext/solv_jsonparser.c294
-rw-r--r--ext/solv_jsonparser.h49
-rw-r--r--ext/solv_xmlparser.c41
-rw-r--r--ext/solv_xmlparser.h12
-rw-r--r--ext/testcase.c12
20 files changed, 441 insertions, 155 deletions
diff --git a/ext/repo_appdata.c b/ext/repo_appdata.c
index 03098e2..3174968 100644
--- a/ext/repo_appdata.c
+++ b/ext/repo_appdata.c
@@ -420,19 +420,6 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
}
}
-static void
-errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
-{
- 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;
- }
-}
-
static int
repo_add_appdata_fn(Repo *repo, FILE *fp, int flags, const char *filename, Queue *owners)
{
@@ -448,8 +435,13 @@ repo_add_appdata_fn(Repo *repo, FILE *fp, int flags, const char *filename, Queue
pd.filename = filename;
pd.owners = owners;
- solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
- solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement);
+ if (solv_xmlparser_parse(&pd.xmlp, fp) != SOLV_XMLPARSER_OK)
+ {
+ pool_debug(pd.pool, SOLV_ERROR, "repo_appdata: %s at line %u:%u\n", pd.xmlp.errstr, pd.xmlp.line, pd.xmlp.column);
+ pd.ret = -1;
+ pd.solvable = solvable_free(pd.solvable, 1);
+ }
solv_xmlparser_free(&pd.xmlp);
solv_free(pd.desktop_file);
diff --git a/ext/repo_arch.c b/ext/repo_arch.c
index a0c45ce..698d506 100644
--- a/ext/repo_arch.c
+++ b/ext/repo_arch.c
@@ -444,8 +444,7 @@ repo_add_arch_pkg(Repo *repo, const char *fn, int flags)
if (s && !s->name)
{
pool_error(pool, -1, "%s: package has no name", fn);
- repo_free_solvable(repo, s - pool->solvables, 1);
- s = 0;
+ s = solvable_free(s, 1);
}
if (s)
{
@@ -728,7 +727,7 @@ finishsolvable(Repo *repo, Solvable *s)
return;
if (!s->name)
{
- repo_free_solvable(repo, s - pool->solvables, 1);
+ solvable_free(s, 1);
return;
}
if (!s->arch)
diff --git a/ext/repo_comps.c b/ext/repo_comps.c
index 255ecb1..9400e1e 100644
--- a/ext/repo_comps.c
+++ b/ext/repo_comps.c
@@ -206,14 +206,6 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
}
}
-static void
-errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
-{
- struct parsedata *pd = xmlp->userdata;
- pool_debug(pd->pool, SOLV_ERROR, "repo_comps: %s at line %u:%u\n", errstr, line, column);
-}
-
-
int
repo_add_comps(Repo *repo, FILE *fp, int flags)
{
@@ -226,8 +218,9 @@ repo_add_comps(Repo *repo, FILE *fp, int flags)
pd.repo = repo;
pd.pool = repo->pool;
pd.data = data;
- solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
- solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement);
+ if (solv_xmlparser_parse(&pd.xmlp, fp) != SOLV_XMLPARSER_OK)
+ pool_debug(pd.pool, SOLV_ERROR, "repo_comps: %s at line %u:%u\n", pd.xmlp.errstr, pd.xmlp.line, pd.xmlp.column);
solv_xmlparser_free(&pd.xmlp);
join_freemem(&pd.jd);
diff --git a/ext/repo_content.c b/ext/repo_content.c
index 68af2d5..f361900 100644
--- a/ext/repo_content.c
+++ b/ext/repo_content.c
@@ -517,8 +517,7 @@ repo_add_content(Repo *repo, FILE *fp, int flags)
if (s && !s->name)
{
pool_debug(pool, SOLV_ERROR, "repo_content: 'content' incomplete, no product solvable created!\n");
- repo_free_solvable(repo, s - pool->solvables, 1);
- s = 0;
+ s = solvable_free(s, 1);
}
if (s)
{
diff --git a/ext/repo_cudf.c b/ext/repo_cudf.c
index 14ddcc9..64bb86f 100644
--- a/ext/repo_cudf.c
+++ b/ext/repo_cudf.c
@@ -224,10 +224,7 @@ repo_add_cudf(Repo *repo, Repo *installedrepo, FILE *fp, Queue *job, int flags)
if (!*buf)
{
if (s && !repo && !isinstalled)
- {
- repo_free_solvable(repo, s - pool->solvables, 1);
- s = 0;
- }
+ s = solvable_free(s, 1);
if (s)
finishpackage(pool, s, keep, job);
s = 0;
@@ -323,10 +320,7 @@ repo_add_cudf(Repo *repo, Repo *installedrepo, FILE *fp, Queue *job, int flags)
{
isinstalled = 1;
if (!installedrepo)
- {
- repo_free_solvable(repo, s - pool->solvables, 1);
- s = 0;
- }
+ s = solvable_free(s, 1);
else if (s->repo != installedrepo)
{
copysolvabledata(pool, s, installedrepo);
@@ -371,10 +365,7 @@ repo_add_cudf(Repo *repo, Repo *installedrepo, FILE *fp, Queue *job, int flags)
}
}
if (s && !repo && !isinstalled)
- {
- repo_free_solvable(repo, s - pool->solvables, 1);
- s = 0;
- }
+ s = solvable_free(s, 1);
if (s)
finishpackage(pool, s, keep, job);
solv_free(buf);
diff --git a/ext/repo_deb.c b/ext/repo_deb.c
index 6af7f10..5dd79f4 100644
--- a/ext/repo_deb.c
+++ b/ext/repo_deb.c
@@ -499,7 +499,7 @@ repo_add_debpackages(Repo *repo, FILE *fp, int flags)
s = pool_id2solvable(pool, repo_add_solvable(repo));
control2solvable(s, data, buf);
if (!s->name)
- repo_free_solvable(repo, s - pool->solvables, 1);
+ s = solvable_free(s, 1);
if (l > ll)
memmove(buf, p + 1, l - ll);
l -= ll;
@@ -511,7 +511,7 @@ repo_add_debpackages(Repo *repo, FILE *fp, int flags)
s = pool_id2solvable(pool, repo_add_solvable(repo));
control2solvable(s, data, buf);
if (!s->name)
- repo_free_solvable(repo, s - pool->solvables, 1);
+ s = solvable_free(s, 1);
}
solv_free(buf);
if (!(flags & REPO_NO_INTERNALIZE))
diff --git a/ext/repo_deltainfoxml.c b/ext/repo_deltainfoxml.c
index 4eb340f..ad315da 100644
--- a/ext/repo_deltainfoxml.c
+++ b/ext/repo_deltainfoxml.c
@@ -306,13 +306,6 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
}
}
-void
-errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
-{
- struct parsedata *pd = xmlp->userdata;
- pd->ret = pool_error(pd->pool, -1, "repo_deltainfoxml: %s at line %u:%u", errstr, line, column);
-}
-
int
repo_add_deltainfoxml(Repo *repo, FILE *fp, int flags)
{
@@ -327,8 +320,9 @@ repo_add_deltainfoxml(Repo *repo, FILE *fp, int flags)
pd.pool = pool;
pd.repo = repo;
pd.data = data;
- solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
- solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement);
+ if (solv_xmlparser_parse(&pd.xmlp, fp) != SOLV_XMLPARSER_OK)
+ pd.ret = pool_error(pd.pool, -1, "repo_deltainfoxml: %s at line %u:%u", pd.xmlp.errstr, pd.xmlp.line, pd.xmlp.column);
solv_xmlparser_free(&pd.xmlp);
/* now commit all handles */
diff --git a/ext/repo_helix.c b/ext/repo_helix.c
index 3c2c6d1..37359bb 100644
--- a/ext/repo_helix.c
+++ b/ext/repo_helix.c
@@ -674,14 +674,6 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
}
}
-static void
-errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
-{
- struct parsedata *pd = xmlp->userdata;
- pd->ret = pool_error(pd->pool, -1, "%s at line %u", errstr, line);
-}
-
-
/*-------------------------------------------------------------------*/
/*
@@ -706,14 +698,14 @@ repo_add_helix(Repo *repo, FILE *fp, int flags)
pd.pool = pool;
pd.repo = repo;
pd.data = data;
- solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
pd.evrspace = (char *)solv_malloc(256);
pd.aevrspace = 256;
pd.levrspace = 1;
- solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
- solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement);
+ if (solv_xmlparser_parse(&pd.xmlp, fp) != SOLV_XMLPARSER_OK)
+ pd.ret = pool_error(pd.pool, -1, "repo_helix: %s at line %u", pd.xmlp.errstr, pd.xmlp.line);
solv_xmlparser_free(&pd.xmlp);
solv_free(pd.evrspace);
diff --git a/ext/repo_mdk.c b/ext/repo_mdk.c
index 418bc61..4d3e102 100644
--- a/ext/repo_mdk.c
+++ b/ext/repo_mdk.c
@@ -230,7 +230,7 @@ repo_add_mdk(Repo *repo, FILE *fp, int flags)
if (s)
{
pool_debug(pool, SOLV_ERROR, "unclosed package at EOF\n");
- repo_free_solvable(s->repo, s - pool->solvables, 1);
+ s = solvable_free(s, 1);
}
solv_free(buf);
if (!(flags & REPO_NO_INTERNALIZE))
@@ -437,14 +437,6 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
}
}
-static void
-errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
-{
- struct parsedata *pd = xmlp->userdata;
- pool_debug(pd->pool, SOLV_ERROR, "%s at line %u:%u\n", errstr, line, column);
-}
-
-
int
repo_add_mdk_info(Repo *repo, FILE *fp, int flags)
{
@@ -463,9 +455,10 @@ repo_add_mdk_info(Repo *repo, FILE *fp, int flags)
pd.repo = repo;
pd.pool = repo->pool;
pd.data = data;
- solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement);
pd.joinhash = joinhash_init(repo, &pd.joinhashmask);
- solv_xmlparser_parse(&pd.xmlp, fp);
+ if (solv_xmlparser_parse(&pd.xmlp, fp) != SOLV_XMLPARSER_OK)
+ pool_debug(pd.pool, SOLV_ERROR, "%s at line %u:%u\n", pd.xmlp.errstr, pd.xmlp.line, pd.xmlp.column);
solv_xmlparser_free(&pd.xmlp);
solv_free(pd.joinhash);
if (!(flags & REPO_NO_INTERNALIZE))
diff --git a/ext/repo_products.c b/ext/repo_products.c
index 154a909..edf15bf 100644
--- a/ext/repo_products.c
+++ b/ext/repo_products.c
@@ -291,19 +291,6 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
}
}
-static void
-errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
-{
- struct parsedata *pd = xmlp->userdata;
- pool_debug(pd->pool, SOLV_ERROR, "%s: %s at line %u:%u\n", pd->filename, errstr, line, column);
- if (pd->solvable)
- {
- repo_free_solvable(pd->repo, pd->solvable - pd->pool->solvables, 1);
- pd->solvable = 0;
- }
-}
-
-
int
repo_add_code11_products(Repo *repo, const char *dirpath, int flags)
{
@@ -318,7 +305,7 @@ repo_add_code11_products(Repo *repo, const char *dirpath, int flags)
pd.pool = repo->pool;
pd.data = data;
- solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement);
if (flags & REPO_USE_ROOTDIR)
dirpath = pool_prepend_rootdir(repo->pool, dirpath);
@@ -358,7 +345,11 @@ repo_add_code11_products(Repo *repo, const char *dirpath, int flags)
pd.ctime = (unsigned int)st.st_ctime;
pd.filename = fullpath;
pd.basename = entry->d_name;
- solv_xmlparser_parse(&pd.xmlp, fp);
+ if (solv_xmlparser_parse(&pd.xmlp, fp) != SOLV_XMLPARSER_OK)
+ {
+ pool_debug(pd.pool, SOLV_ERROR, "%s: %s at line %u:%u\n", pd.filename, pd.xmlp.errstr, pd.xmlp.line, pd.xmlp.column);
+ pd.solvable = solvable_free(pd.solvable, 1);
+ }
fclose(fp);
}
closedir(dir);
diff --git a/ext/repo_repomdxml.c b/ext/repo_repomdxml.c
index 760d481..fd46272 100644
--- a/ext/repo_repomdxml.c
+++ b/ext/repo_repomdxml.c
@@ -329,13 +329,6 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
}
}
-static void
-errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
-{
- struct parsedata *pd = xmlp->userdata;
- pd->ret = pool_error(pd->pool, -1, "repo_repomdxml: %s at line %u:%u", errstr, line, column);
-}
-
int
repo_add_repomdxml(Repo *repo, FILE *fp, int flags)
{
@@ -350,9 +343,9 @@ repo_add_repomdxml(Repo *repo, FILE *fp, int flags)
pd.pool = pool;
pd.repo = repo;
pd.data = data;
- solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
-
- solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement);
+ if (solv_xmlparser_parse(&pd.xmlp, fp) != SOLV_XMLPARSER_OK)
+ pd.ret = pool_error(pd.pool, -1, "repo_repomdxml: %s at line %u:%u", pd.xmlp.errstr, pd.xmlp.line, pd.xmlp.column);
solv_xmlparser_free(&pd.xmlp);
if (!(flags & REPO_NO_INTERNALIZE))
diff --git a/ext/repo_rpmdb.c b/ext/repo_rpmdb.c
index a2d518f..9acb400 100644
--- a/ext/repo_rpmdb.c
+++ b/ext/repo_rpmdb.c
@@ -1661,9 +1661,8 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags)
if (s)
{
/* oops, could not reuse. free it instead */
- repo_free_solvable(repo, s - pool->solvables, 1);
+ s = solvable_free(s, 1);
solvend--;
- s = 0;
}
/* now sort all solvables in the new solvstart..solvend block */
if (solvend - solvstart > 1)
@@ -2044,7 +2043,7 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
s = pool_id2solvable(pool, repo_add_solvable(repo));
if (!rpmhead2solv(pool, repo, data, s, state.rpmhead, flags & ~(RPM_ADD_WITH_HDRID | RPM_ADD_WITH_PKGID)))
{
- repo_free_solvable(repo, s - pool->solvables, 1);
+ s = solvable_free(s, 1);
solv_chksum_free(chksumh, 0);
headfree(state.rpmhead);
return 0;
@@ -2096,7 +2095,7 @@ repo_add_rpm_handle(Repo *repo, void *rpmhandle, int flags)
s = pool_id2solvable(pool, repo_add_solvable(repo));
if (!rpmhead2solv(pool, repo, data, s, rpmhead, flags))
{
- repo_free_solvable(repo, s - pool->solvables, 1);
+ s = solvable_free(s, 1);
return 0;
}
if (!(flags & REPO_NO_INTERNALIZE))
diff --git a/ext/repo_rpmmd.c b/ext/repo_rpmmd.c
index 9f49bd3..9bb50a0 100644
--- a/ext/repo_rpmmd.c
+++ b/ext/repo_rpmmd.c
@@ -1091,13 +1091,6 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
}
}
-static void
-errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
-{
- struct parsedata *pd = xmlp->userdata;
- pd->ret = pool_error(pd->pool, -1, "repo_rpmmd: %s at line %u:%u", errstr, line, column);
-}
-
/*-----------------------------------------------*/
@@ -1135,8 +1128,9 @@ repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags)
fill_cshash_from_repo(&pd);
}
- solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
- solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement);
+ if (solv_xmlparser_parse(&pd.xmlp, fp) != SOLV_XMLPARSER_OK)
+ pd.ret = pool_error(pool, -1, "repo_rpmmd: %s at line %u:%u", pd.xmlp.errstr, pd.xmlp.line, pd.xmlp.column);
solv_xmlparser_free(&pd.xmlp);
solv_free(pd.lastdirstr);
diff --git a/ext/repo_updateinfoxml.c b/ext/repo_updateinfoxml.c
index 7ba0062..ff84d32 100644
--- a/ext/repo_updateinfoxml.c
+++ b/ext/repo_updateinfoxml.c
@@ -427,13 +427,6 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
}
}
-static void
-errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
-{
- struct parsedata *pd = xmlp->userdata;
- pd->ret = pool_error(pd->pool, -1, "repo_updateinfoxml: %s at line %u:%u", errstr, line, column);
-}
-
int
repo_add_updateinfoxml(Repo *repo, FILE *fp, int flags)
{
@@ -447,8 +440,9 @@ repo_add_updateinfoxml(Repo *repo, FILE *fp, int flags)
pd.pool = pool;
pd.repo = repo;
pd.data = data;
- solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
- solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement);
+ if (solv_xmlparser_parse(&pd.xmlp, fp) != SOLV_XMLPARSER_OK)
+ pd.ret = pool_error(pool, -1, "repo_updateinfoxml: %s at line %u:%u", pd.xmlp.errstr, pd.xmlp.line, pd.xmlp.column);
solv_xmlparser_free(&pd.xmlp);
join_freemem(&pd.jd);
diff --git a/ext/repo_zyppdb.c b/ext/repo_zyppdb.c
index d73a900..f6e2bfa 100644
--- a/ext/repo_zyppdb.c
+++ b/ext/repo_zyppdb.c
@@ -138,18 +138,6 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
}
}
-static void
-errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
-{
- struct parsedata *pd = xmlp->userdata;
- pool_debug(pd->pool, SOLV_ERROR, "repo_zyppdb: %s: %s at line %u:%u\n", pd->filename, errstr, line, column);
- if (pd->solvable)
- {
- repo_free_solvable(pd->repo, pd->solvable - pd->pool->solvables, 1);
- pd->solvable = 0;
- }
-}
-
/*
* read all installed products
@@ -172,7 +160,7 @@ repo_add_zyppdb_products(Repo *repo, const char *dirpath, int flags)
pd.repo = repo;
pd.pool = repo->pool;
pd.data = data;
- solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement);
if (flags & REPO_USE_ROOTDIR)
dirpath = pool_prepend_rootdir(repo->pool, dirpath);
@@ -190,7 +178,11 @@ repo_add_zyppdb_products(Repo *repo, const char *dirpath, int flags)
continue;
}
pd.filename = entry->d_name;
- solv_xmlparser_parse(&pd.xmlp, fp);
+ if (solv_xmlparser_parse(&pd.xmlp, fp) != SOLV_XMLPARSER_OK)
+ {
+ pool_debug(pd.pool, SOLV_ERROR, "repo_zyppdb: %s: %s at line %u:%u\n", pd.filename, pd.xmlp.errstr, pd.xmlp.line, pd.xmlp.column);
+ pd.solvable = solvable_free(pd.solvable, 1);
+ }
fclose(fp);
}
}
diff --git a/ext/solv_jsonparser.c b/ext/solv_jsonparser.c
new file mode 100644
index 0000000..053ee6f
--- /dev/null
+++ b/ext/solv_jsonparser.c
@@ -0,0 +1,294 @@
+/*
+ * solv_jsonparser.c
+ *
+ * Simple JSON stream parser
+ *
+ * Copyright (c) 2018, SUSE LLC
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "util.h"
+#include "solv_jsonparser.h"
+
+struct solv_jsonparser *
+jsonparser_init(struct solv_jsonparser *jp, FILE *fp)
+{
+ memset(jp, 0, sizeof(*jp));
+ jp->fp = fp;
+ jp->state = JP_START;
+ jp->line = jp->nextline = 1;
+ jp->nextc = ' ';
+ queue_init(&jp->stateq);
+ return jp;
+}
+
+struct solv_jsonparser *
+jsonparser_free(struct solv_jsonparser *jp)
+{
+ queue_free(&jp->stateq);
+ return 0;
+}
+
+static void
+savec(struct solv_jsonparser *jp, char c)
+{
+ if (jp->nspace == jp->aspace)
+ {
+ jp->aspace += 256;
+ jp->space = solv_realloc(jp->space, jp->aspace);
+ }
+ jp->space[jp->nspace++] = c;
+}
+
+static void
+saveutf8(struct solv_jsonparser *jp, int c)
+{
+ int i;
+ if (c < 0x80)
+ {
+ savec(jp, c);
+ return;
+ }
+ i = c < 0x800 ? 1 : c < 0x10000 ? 2 : 3;
+ savec(jp, (0x1f80 >> i) | (c >> (6 * i)));
+ while (--i >= 0)
+ savec(jp, 0x80 | ((c >> (6 * i)) & 0x3f));
+}
+
+static inline int
+nextc(struct solv_jsonparser *jp)
+{
+ int c = getc(jp->fp);
+ if (c == '\n')
+ jp->nextline++;
+ return c;
+}
+
+static int
+skipspace(struct solv_jsonparser *jp)
+{
+ int c = jp->nextc;
+ while (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+ c = nextc(jp);
+ jp->line = jp->nextline;
+ return (jp->nextc = c);
+}
+
+static int
+parseliteral(struct solv_jsonparser *jp)
+{
+ size_t nspace = jp->nspace;
+ int c;
+ savec(jp, jp->nextc);
+ for (;;)
+ {
+ c = nextc(jp);
+ if (c < 'a' || c > 'z')
+ break;
+ savec(jp, c);
+ }
+ jp->nextc = c;
+ savec(jp, 0);
+ if (!strcmp(jp->space + nspace, "true"))
+ return JP_BOOL;
+ if (!strcmp(jp->space + nspace, "false"))
+ return JP_BOOL;
+ if (!strcmp(jp->space + nspace, "null"))
+ return JP_NULL;
+ return JP_ERROR;
+}
+
+static int
+parsenumber(struct solv_jsonparser *jp)
+{
+ int c;
+ savec(jp, jp->nextc);
+ for (;;)
+ {
+ c = nextc(jp);
+ if ((c < '0' || c > '9') && c != '+' && c != '-' && c != '.' && c != 'e' && c != 'E')
+ break;
+ savec(jp, c);
+ }
+ jp->nextc = c;
+ savec(jp, 0);
+ return JP_NUMBER;
+}
+
+static int
+parseutf8(struct solv_jsonparser *jp, int surrogate)
+{
+ int c, i, r = 0;
+ /* parse 4-digit hex */
+ for (i = 0; i < 4; i++)
+ {
+ c = nextc(jp);
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'f')
+ c -= 'a' - 10;
+ else if (c >= 'A' && c <= 'F')
+ c -= 'A' - 10;
+ else
+ return -1;
+ r = (r << 4) | c;
+ }
+ if (!surrogate && r >= 0xd800 && r < 0xdc00)
+ {
+ /* utf16 surrogate pair encodes 0x10000 - 0x10ffff */
+ int r2;
+ if (nextc(jp) != '\\' || nextc(jp) != 'u' || (r2 = parseutf8(jp, 1)) < 0xdc00 || r2 >= 0xe000)
+ return -1;
+ r = 0x10000 + ((r & 0x3ff) << 10 | (r2 & 0x3ff));
+ }
+ return r;
+}
+
+static int
+parsestring(struct solv_jsonparser *jp)
+{
+ int c;
+ for (;;)
+ {
+ if ((c = nextc(jp)) < 32)
+ return JP_ERROR;
+ if (c == '"')
+ break;
+ if (c == '\\')
+ {
+ switch (c = nextc(jp))
+ {
+ case '"':
+ case '\\':
+ case '/':
+ case '\n':
+ break;
+ case 'b':
+ c = '\b';
+ break;
+ case 'f':
+ c = '\f';
+ break;
+ case 'n':
+ c = '\n';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case 't':
+ c = '\t';
+ break;
+ case 'u':
+ if ((c = parseutf8(jp, 0)) < 0)
+ return JP_ERROR;
+ saveutf8(jp, c);
+ continue;
+ default:
+ return JP_ERROR;
+ }
+ }
+ savec(jp, c);
+ }
+ jp->nextc = ' ';
+ savec(jp, 0);
+ return JP_STRING;
+}
+
+static int
+parsevalue(struct solv_jsonparser *jp)
+{
+ int c = skipspace(jp);
+ if (c == '"')
+ return parsestring(jp);
+ if ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.')
+ return parsenumber(jp);
+ if ((c >= 'a' && c <= 'z'))
+ return parseliteral(jp);
+ jp->nextc = ' ';
+ if (c == '[')
+ return JP_ARRAY;
+ if (c == '{')
+ return JP_OBJECT;
+ if (c == ']')
+ return JP_ARRAY_END;
+ if (c == '}')
+ return JP_OBJECT_END;
+ return JP_ERROR;
+}
+
+int
+jsonparser_parse(struct solv_jsonparser *jp)
+{
+ int type;
+ size_t nspace;
+
+ jp->depth = jp->stateq.count;
+ jp->key = jp->value = 0;
+ jp->keylen = jp->valuelen = 0;
+ nspace = jp->nspace = 0;
+
+ if (jp->state == JP_END)
+ return JP_END;
+ if (jp->state == JP_START)
+ jp->state = JP_END;
+ type = parsevalue(jp);
+ if (type <= 0)
+ return JP_ERROR;
+ if (type == JP_OBJECT_END || type == JP_ARRAY_END)
+ {
+ if (jp->state != type - 1)
+ return JP_ERROR;
+ jp->state = queue_pop(&jp->stateq);
+ }
+ else if (jp->state == JP_OBJECT)
+ {
+ nspace = jp->nspace;
+ if (type != JP_STRING)
+ return JP_ERROR;
+ if (skipspace(jp) != ':')
+ return JP_ERROR;
+ jp->nextc = ' ';
+ type = parsevalue(jp);
+ if (type == JP_OBJECT_END || type == JP_ARRAY_END)
+ return JP_ERROR;
+ jp->key = jp->space;
+ jp->keylen = nspace - 1;
+ }
+ if (type == JP_STRING || type == JP_NUMBER || type == JP_BOOL || type == JP_NULL)
+ {
+ jp->value = jp->space + nspace;
+ jp->valuelen = jp->nspace - nspace - 1;
+ }
+ if (type == JP_ARRAY || type == JP_OBJECT)
+ {
+ queue_push(&jp->stateq, jp->state);
+ jp->state = type;
+ }
+ else if (jp->state == JP_OBJECT || jp->state == JP_ARRAY)
+ {
+ int c = skipspace(jp);
+ if (c == ',')
+ jp->nextc = ' ';
+ else if (c != (jp->state == JP_OBJECT ? '}' : ']'))
+ return JP_ERROR;
+ }
+ return type;
+}
+
+int
+jsonparser_skip(struct solv_jsonparser *jp, int type)
+{
+ if (type == JP_ARRAY || type == JP_OBJECT)
+ {
+ int depth = jp->depth + 1, endtype = type + 1;
+ while (type > 0 && (type != endtype || jp->depth != depth))
+ type = jsonparser_parse(jp);
+ }
+ return type;
+}
+
diff --git a/ext/solv_jsonparser.h b/ext/solv_jsonparser.h
new file mode 100644
index 0000000..d58d9e3
--- /dev/null
+++ b/ext/solv_jsonparser.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018, SUSE LLC
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+#ifndef SOLV_JSONPARSER_H
+#define SOLV_JSONPARSER_H
+
+#include "queue.h"
+
+struct solv_jsonparser {
+ FILE *fp;
+ int line;
+ int depth;
+
+ char *key;
+ size_t keylen;
+ char *value;
+ size_t valuelen;
+
+ int state;
+ Queue stateq;
+ int nextc;
+ int nextline;
+ char *space;
+ size_t nspace;
+ size_t aspace;
+};
+
+#define JP_ERROR -1
+#define JP_END 0
+#define JP_START 1
+#define JP_STRING 2
+#define JP_NUMBER 3
+#define JP_BOOL 4
+#define JP_NULL 5
+#define JP_OBJECT 6
+#define JP_OBJECT_END 7
+#define JP_ARRAY 8
+#define JP_ARRAY_END 9
+
+struct solv_jsonparser *jsonparser_init(struct solv_jsonparser *jp, FILE *fp);
+struct solv_jsonparser *jsonparser_free(struct solv_jsonparser *jp);
+int jsonparser_parse(struct solv_jsonparser *jp);
+int jsonparser_skip(struct solv_jsonparser *jp, int type);
+
+#endif /* SOLV_JSONPARSER_H */
diff --git a/ext/solv_xmlparser.c b/ext/solv_xmlparser.c
index 170520f..6292663 100644
--- a/ext/solv_xmlparser.c
+++ b/ext/solv_xmlparser.c
@@ -132,8 +132,7 @@ solv_xmlparser_init(struct solv_xmlparser *xmlp,
struct solv_xmlparser_element *elements,
void *userdata,
void (*startelement)(struct solv_xmlparser *, int state, const char *name, const char **atts),
- void (*endelement)(struct solv_xmlparser *, int state, char *content),
- void (*errorhandler)(struct solv_xmlparser *, const char *errstr, unsigned int line, unsigned int column))
+ void (*endelement)(struct solv_xmlparser *, int state, char *content))
{
int i, nstates, nelements;
struct solv_xmlparser_element *el;
@@ -169,7 +168,6 @@ solv_xmlparser_init(struct solv_xmlparser *xmlp,
xmlp->userdata = userdata;
xmlp->startelement = startelement;
xmlp->endelement = endelement;
- xmlp->errorhandler = errorhandler;
}
void
@@ -178,6 +176,16 @@ solv_xmlparser_free(struct solv_xmlparser *xmlp)
xmlp->elementhelper = solv_free(xmlp->elementhelper);
queue_free(&xmlp->elementq);
xmlp->content = solv_free(xmlp->content);
+ xmlp->errstr = solv_free(xmlp->errstr);
+}
+
+static void
+set_error(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
+{
+ solv_free(xmlp->errstr);
+ xmlp->errstr = solv_strdup(errstr);
+ xmlp->line = line;
+ xmlp->column = column;
}
#ifdef WITH_LIBXML2
@@ -197,7 +205,8 @@ free_parser(struct solv_xmlparser *xmlp)
xmlp->parser = 0;
}
-static xmlParserCtxtPtr create_parser_ctx(struct solv_xmlparser *xmlp, char *buf, int l)
+static xmlParserCtxtPtr
+create_parser_ctx(struct solv_xmlparser *xmlp, char *buf, int l)
{
xmlSAXHandler sax;
memset(&sax, 0, sizeof(sax));
@@ -216,7 +225,7 @@ parse_block(struct solv_xmlparser *xmlp, char *buf, int l)
xmlp->parser = create_parser_ctx(xmlp, buf, l2);
if (!xmlp->parser)
{
- xmlp->errorhandler(xmlp, "could not create parser", 0, 0);
+ set_error(xmlp, "could not create parser", 0, 0);
return 0;
}
buf += l2;
@@ -227,7 +236,7 @@ parse_block(struct solv_xmlparser *xmlp, char *buf, int l)
if (xmlParseChunk(xmlp->parser, buf, l, l == 0 ? 1 : 0))
{
xmlErrorPtr err = xmlCtxtGetLastError(xmlp->parser);
- xmlp->errorhandler(xmlp, err->message, err->line, err->int2);
+ set_error(xmlp, err->message, err->line, err->int2);
return 0;
}
return 1;
@@ -265,9 +274,7 @@ 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);
+ set_error(xmlp, XML_ErrorString(XML_GetErrorCode(xmlp->parser)), XML_GetCurrentLineNumber(xmlp->parser), XML_GetCurrentColumnNumber(xmlp->parser));
return 0;
}
return 1;
@@ -281,11 +288,11 @@ solv_xmlparser_lineno(struct solv_xmlparser *xmlp)
#endif
-void
+int
solv_xmlparser_parse(struct solv_xmlparser *xmlp, FILE *fp)
{
char buf[8192];
- int l;
+ int l, ret = SOLV_XMLPARSER_OK;
xmlp->state = 0;
xmlp->unknowncnt = 0;
@@ -295,16 +302,22 @@ solv_xmlparser_parse(struct solv_xmlparser *xmlp, FILE *fp)
if (!create_parser(xmlp))
{
- xmlp->errorhandler(xmlp, "could not create xml parser", 0, 0);
- return;
+ set_error(xmlp, "could not create parser", 0, 0);
+ return SOLV_XMLPARSER_ERROR;
}
for (;;)
{
l = fread(buf, 1, sizeof(buf), fp);
- if (!parse_block(xmlp, buf, l) || !l)
+ if (!parse_block(xmlp, buf, l))
+ {
+ ret = SOLV_XMLPARSER_ERROR;
+ break;
+ }
+ if (!l)
break;
}
free_parser(xmlp);
+ return ret;
}
char *
diff --git a/ext/solv_xmlparser.h b/ext/solv_xmlparser.h
index 9fb342f..ced0571 100644
--- a/ext/solv_xmlparser.h
+++ b/ext/solv_xmlparser.h
@@ -8,6 +8,9 @@ struct solv_xmlparser_element {
struct solv_xmlparser {
void *userdata;
+ char *errstr;
+ unsigned int line;
+ unsigned int column;
int state;
int docontent;
@@ -24,12 +27,14 @@ struct solv_xmlparser {
void (*startelement)(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts);
void (*endelement)(struct solv_xmlparser *xmlp, int state, char *content);
- void (*errorhandler)(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column);
Id *elementhelper;
void *parser;
};
+#define SOLV_XMLPARSER_OK 0
+#define SOLV_XMLPARSER_ERROR -1
+
static inline const char *
solv_xmlparser_find_attr(const char *txt, const char **atts)
{
@@ -41,11 +46,10 @@ solv_xmlparser_find_attr(const char *txt, const char **atts)
extern void solv_xmlparser_init(struct solv_xmlparser *xmlp, struct solv_xmlparser_element *elements, void *userdata,
void (*startelement)(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts),
- void (*endelement)(struct solv_xmlparser *xmlp, int state, char *content),
- void (*errorhandler)(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column));
+ void (*endelement)(struct solv_xmlparser *xmlp, int state, char *content));
extern void solv_xmlparser_free(struct solv_xmlparser *xmlp);
-extern void solv_xmlparser_parse(struct solv_xmlparser *xmlp, FILE *fp);
+extern int solv_xmlparser_parse(struct solv_xmlparser *xmlp, FILE *fp);
unsigned int solv_xmlparser_lineno(struct solv_xmlparser *xmlp);
char *solv_xmlparser_contentspace(struct solv_xmlparser *xmlp, int l);
diff --git a/ext/testcase.c b/ext/testcase.c
index ffc8b8a..b815c56 100644
--- a/ext/testcase.c
+++ b/ext/testcase.c
@@ -15,6 +15,7 @@
#include "pool.h"
#include "poolarch.h"
#include "poolvendor.h"
+#include "evr.h"
#include "repo.h"
#include "repo_solv.h"
#include "solver.h"
@@ -121,6 +122,7 @@ static struct solverflags2str {
{ SOLVER_FLAG_FOCUS_BEST, "focusbest", 0 },
{ SOLVER_FLAG_STRONG_RECOMMENDS, "strongrecommends", 0 },
{ SOLVER_FLAG_INSTALL_ALSO_UPDATES, "installalsoupdates", 0 },
+ { SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED, "onlynamespacerecommended", 0 },
{ 0, 0, 0 }
};
@@ -1071,7 +1073,7 @@ testcase_str2job(Pool *pool, const char *str, Id *whatp)
Queue q;
job |= SOLVER_SOLVABLE_ONE_OF;
queue_init(&q);
- if (npieces > 3 && strcmp(pieces[2], "nothing") != 0)
+ if (npieces > 2 && strcmp(pieces[2], "nothing") != 0)
{
for (i = 2; i < npieces; i++)
{
@@ -2966,6 +2968,14 @@ testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **res
}
queue_push(&autoinstq, pool_str2id(pool, pieces[2], 1));
}
+ else if (!strcmp(pieces[0], "evrcmp") && npieces == 3)
+ {
+ Id evr1 = pool_str2id(pool, pieces[1], 1);
+ Id evr2 = pool_str2id(pool, pieces[2], 1);
+ int r = pool_evrcmp(pool, evr1, evr2, EVRCMP_COMPARE);
+ r = r < 0 ? REL_LT : r > 0 ? REL_GT : REL_EQ;
+ queue_push2(job, SOLVER_NOOP | SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, evr1, evr2, r, 1));
+ }
else
{
pool_error(pool, 0, "testcase_read: cannot parse command '%s'", pieces[0]);