summaryrefslogtreecommitdiff
path: root/src/database.c
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2023-03-04 13:54:54 +0200
committerTimo Teräs <timo.teras@iki.fi>2023-04-11 20:47:43 +0300
commit67f5a753e50da8737dc28b0ea2c2194b21d76fdd (patch)
tree657a81a529d2733eecae1837cc48ac25abe73357 /src/database.c
parentefb55ce650d3cac9a607560d840f95c1127e68f5 (diff)
downloadapk-tools-67f5a753e50da8737dc28b0ea2c2194b21d76fdd.tar.gz
apk-tools-67f5a753e50da8737dc28b0ea2c2194b21d76fdd.tar.bz2
apk-tools-67f5a753e50da8737dc28b0ea2c2194b21d76fdd.tar.xz
apk-tools-67f5a753e50da8737dc28b0ea2c2194b21d76fdd.zip
db, apps: sort display results based on package names
Diffstat (limited to 'src/database.c')
-rw-r--r--src/database.c137
1 files changed, 107 insertions, 30 deletions
diff --git a/src/database.c b/src/database.c
index a4c7f97..3dc72f2 100644
--- a/src/database.c
+++ b/src/database.c
@@ -221,6 +221,7 @@ struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name)
apk_name_array_init(&pn->rdepends);
apk_name_array_init(&pn->rinstall_if);
apk_hash_insert_hashed(&db->available.names, pn, hash);
+ db->sorted_names = 0;
return pn;
}
@@ -1515,6 +1516,7 @@ void apk_db_init(struct apk_database *db)
list_init(&db->installed.triggers);
apk_dependency_array_init(&db->world);
apk_protected_path_array_init(&db->protected_paths);
+ apk_name_array_init(&db->available.sorted_names);
db->permanent = 1;
db->root_fd = -1;
}
@@ -1836,6 +1838,7 @@ void apk_db_close(struct apk_database *db)
apk_dependency_array_free(&db->world);
+ apk_name_array_free(&db->available.sorted_names);
apk_hash_free(&db->available.packages);
apk_hash_free(&db->available.names);
apk_hash_free(&db->installed.files);
@@ -2986,8 +2989,7 @@ ret_r:
struct match_ctx {
struct apk_database *db;
struct apk_string_array *filter;
- unsigned int match;
- void (*cb)(struct apk_database *db, const char *match, struct apk_name *name, void *ctx);
+ apk_db_foreach_name_cb cb;
void *cb_ctx;
};
@@ -2995,16 +2997,9 @@ static int match_names(apk_hash_item item, void *pctx)
{
struct match_ctx *ctx = (struct match_ctx *) pctx;
struct apk_name *name = (struct apk_name *) item;
- unsigned int genid = ctx->match & APK_FOREACH_GENID_MASK;
char **pmatch;
- if (genid) {
- if (name->foreach_genid >= genid)
- return 0;
- name->foreach_genid = genid;
- }
-
- if (ctx->filter->num == 0) {
+ if (!ctx->filter->num) {
ctx->cb(ctx->db, NULL, name, ctx->cb_ctx);
return 0;
}
@@ -3012,50 +3007,132 @@ static int match_names(apk_hash_item item, void *pctx)
foreach_array_item(pmatch, ctx->filter) {
if (fnmatch(*pmatch, name->name, 0) == 0) {
ctx->cb(ctx->db, *pmatch, name, ctx->cb_ctx);
- if (genid)
- break;
+ break;
}
}
return 0;
}
-void apk_name_foreach_matching(struct apk_database *db, struct apk_string_array *filter, unsigned int match,
- void (*cb)(struct apk_database *db, const char *match, struct apk_name *name, void *ctx),
- void *ctx)
+int apk_db_foreach_matching_name(struct apk_database *db, struct apk_string_array *filter,
+ apk_db_foreach_name_cb cb, void *ctx)
{
char **pmatch;
- unsigned int genid = match & APK_FOREACH_GENID_MASK;
struct apk_name *name;
struct match_ctx mctx = {
.db = db,
.filter = filter,
- .match = match,
.cb = cb,
.cb_ctx = ctx,
};
+ int r;
+
+ if (!filter || !filter->num) return 0;
- if (filter == NULL || filter->num == 0) {
- if (!(match & APK_FOREACH_NULL_MATCHES_ALL))
- return;
- apk_string_array_init(&mctx.filter);
- goto all;
- }
foreach_array_item(pmatch, filter)
if (strchr(*pmatch, '*') != NULL)
goto all;
foreach_array_item(pmatch, filter) {
name = (struct apk_name *) apk_hash_get(&db->available.names, APK_BLOB_STR(*pmatch));
- if (genid && name) {
- if (name->foreach_genid >= genid)
+ r = cb(db, *pmatch, name, ctx);
+ if (r) return r;
+ }
+ return 0;
+
+all:
+ return apk_hash_foreach(&db->available.names, match_names, &mctx);
+}
+
+static int cmp_name(const void *a, const void *b)
+{
+ const struct apk_name * const* na = a, * const* nb = b;
+ return apk_name_cmp_display(*na, *nb);
+}
+
+struct add_name_ctx {
+ struct apk_name_array *a;
+ size_t i;
+};
+
+static int add_name(apk_hash_item item, void *ctx)
+{
+ struct apk_name *name = (struct apk_name *) item;
+ struct add_name_ctx *a = ctx;
+ a->a->item[a->i++] = name;
+ return 0;
+}
+
+static struct apk_name_array *apk_db_sorted_names(struct apk_database *db)
+{
+ if (!db->sorted_names) {
+ apk_name_array_resize(&db->available.sorted_names, db->available.names.num_items);
+
+ struct add_name_ctx ctx = { .a = db->available.sorted_names, .i = 0 };
+ apk_hash_foreach(&db->available.names, add_name, &ctx);
+
+ qsort(db->available.sorted_names->item, db->available.sorted_names->num,
+ sizeof(db->available.sorted_names->item[0]), cmp_name);
+ db->sorted_names = 1;
+ }
+ return db->available.sorted_names;
+}
+
+int apk_db_foreach_sorted_name(struct apk_database *db, struct apk_string_array *filter,
+ apk_db_foreach_name_cb cb, void *cb_ctx)
+{
+ int walk_all = 0;
+ char **pmatch;
+ struct apk_name *name;
+ struct apk_name *results[128], **res;
+ size_t i, num_res = 0;
+ int r;
+
+ if (filter && filter->num) {
+ foreach_array_item(pmatch, filter) {
+ name = (struct apk_name *) apk_hash_get(&db->available.names, APK_BLOB_STR(*pmatch));
+ if (strchr(*pmatch, '*')) {
+ walk_all = 1;
+ continue;
+ }
+ if (!name) {
+ cb(db, *pmatch, NULL, cb_ctx);
+ continue;
+ }
+ if (walk_all) continue;
+ if (num_res >= ARRAY_SIZE(results)) {
+ walk_all = 1;
continue;
- name->foreach_genid = genid;
+ }
+ results[num_res++] = name;
}
- cb(db, *pmatch, name, ctx);
+ } else {
+ walk_all = 1;
+ filter = NULL;
}
- return;
-all:
- apk_hash_foreach(&db->available.names, match_names, &mctx);
+ if (walk_all) {
+ struct apk_name_array *a = apk_db_sorted_names(db);
+ res = a->item;
+ num_res = a->num;
+ } else {
+ qsort(results, num_res, sizeof results[0], cmp_name);
+ res = results;
+ }
+
+ for (i = 0; i < num_res; i++) {
+ name = res[i];
+ if (!filter || !filter->num) {
+ cb(db, NULL, name, cb_ctx);
+ continue;
+ }
+ foreach_array_item(pmatch, filter) {
+ if (fnmatch(*pmatch, name->name, 0) == 0) {
+ r = cb(db, *pmatch, name, cb_ctx);
+ break;
+ }
+ }
+ if (r) return r;
+ }
+ return 0;
}