krh@248: /* krh@248: * Copyright (C) 2008 Kristian Høgsberg krh@248: * Copyright (C) 2008 Red Hat, Inc ali@351: * Copyright (C) 2009 J. Ali Harlow krh@248: * krh@248: * This program is free software; you can redistribute it and/or modify krh@248: * it under the terms of the GNU General Public License as published by krh@248: * the Free Software Foundation; either version 2 of the License, or krh@248: * (at your option) any later version. krh@248: * krh@248: * This program is distributed in the hope that it will be useful, krh@248: * but WITHOUT ANY WARRANTY; without even the implied warranty of krh@248: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the krh@248: * GNU General Public License for more details. krh@248: * krh@248: * You should have received a copy of the GNU General Public License along krh@248: * with this program; if not, write to the Free Software Foundation, Inc., krh@248: * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. krh@248: */ krh@248: krh@248: #define _GNU_SOURCE krh@248: ali@438: #include "config.h" richard@302: #include krh@248: #include richard@301: #include richard@301: krh@248: #include "razor-internal.h" krh@248: #include "razor.h" krh@248: krh@248: static struct razor_package_iterator * krh@248: razor_package_iterator_create_with_index(struct razor_set *set, krh@248: struct list *index) krh@248: { krh@248: struct razor_package_iterator *pi; krh@248: krh@248: pi = zalloc(sizeof *pi); krh@248: pi->set = set; krh@248: pi->index = index; krh@248: krh@248: return pi; krh@248: } krh@248: jbowes@278: static struct razor_package_iterator * jbowes@278: razor_package_iterator_create_empty(struct razor_set *set) jbowes@278: { jbowes@278: struct razor_package_iterator *pi; jbowes@278: return zalloc(sizeof *pi); jbowes@278: } jbowes@278: krh@269: RAZOR_EXPORT struct razor_package_iterator * krh@248: razor_package_iterator_create(struct razor_set *set) krh@248: { krh@248: struct razor_package_iterator *pi; krh@248: richard@301: assert (set != NULL); richard@301: krh@248: pi = zalloc(sizeof *pi); krh@248: pi->set = set; krh@248: pi->end = set->packages.data + set->packages.size; krh@248: pi->package = set->packages.data; krh@248: krh@248: return pi; krh@248: } krh@248: krh@269: RAZOR_EXPORT void krh@248: razor_package_iterator_init_for_property(struct razor_package_iterator *pi, krh@248: struct razor_set *set, krh@248: struct razor_property *property) krh@248: { richard@301: assert (pi != NULL); richard@301: assert (set != NULL); richard@301: assert (property != NULL); richard@301: krh@248: memset(pi, 0, sizeof *pi); krh@248: pi->set = set; krh@248: pi->index = list_first(&property->packages, &set->package_pool); krh@248: } krh@248: krh@269: RAZOR_EXPORT struct razor_package_iterator * krh@248: razor_package_iterator_create_for_property(struct razor_set *set, krh@248: struct razor_property *property) krh@248: { krh@248: struct list *index; krh@248: richard@301: assert (set != NULL); richard@301: assert (property != NULL); richard@301: krh@248: index = list_first(&property->packages, &set->package_pool); krh@248: return razor_package_iterator_create_with_index(set, index); krh@248: } krh@248: krh@269: RAZOR_EXPORT struct razor_package_iterator * krh@248: razor_package_iterator_create_for_file(struct razor_set *set, krh@248: const char *filename) krh@248: { krh@248: struct razor_entry *entry; krh@248: struct list *index; krh@248: richard@301: assert (set != NULL); richard@301: assert (filename != NULL); richard@301: krh@248: entry = razor_set_find_entry(set, set->files.data, filename); krh@248: if (entry == NULL) jbowes@278: return razor_package_iterator_create_empty(set); krh@248: krh@248: index = list_first(&entry->packages, &set->package_pool); krh@248: return razor_package_iterator_create_with_index(set, index); krh@248: } krh@248: richard@302: /** richard@302: * razor_package_iterator_next: richard@302: * @pi: a %razor_package_iterator richard@302: * @package: a %razor_package richard@302: * richard@302: * Gets the next iteratr along with any vararg data. krh@308: * The vararg must be terminated with %RAZOR_DETAIL_LAST. richard@302: * richard@307: * Example: razor_package_iterator_next (pi, package, richard@307: * RAZOR_DETAIL_NAME, &name, richard@307: * RAZOR_DETAIL_LAST); richard@302: **/ krh@269: RAZOR_EXPORT int krh@248: razor_package_iterator_next(struct razor_package_iterator *pi, richard@302: struct razor_package **package, ...) krh@248: { richard@302: va_list args; krh@248: int valid; krh@248: struct razor_package *p, *packages; krh@248: richard@301: assert (pi != NULL); richard@301: krh@248: if (pi->package) { krh@248: p = pi->package++; krh@248: valid = p < pi->end; krh@248: } else if (pi->index) { krh@248: packages = pi->set->packages.data; krh@248: p = &packages[pi->index->data]; krh@248: pi->index = list_next(pi->index); krh@248: valid = 1; krh@248: } else krh@248: valid = 0; krh@248: richard@302: if (valid == 0) { krh@248: *package = NULL; richard@302: goto out; krh@248: } krh@248: richard@302: *package = p; richard@302: richard@302: va_start(args, NULL); richard@302: razor_package_get_details_varg (pi->set, p, args); richard@302: va_end (args); richard@302: out: krh@248: return valid; krh@248: } krh@248: krh@269: RAZOR_EXPORT void krh@248: razor_package_iterator_destroy(struct razor_package_iterator *pi) krh@248: { richard@301: assert (pi != NULL); richard@301: krh@248: if (pi->free_index) krh@248: free(pi->index); krh@248: krh@248: free(pi); krh@248: } krh@248: krh@269: RAZOR_EXPORT struct razor_property_iterator * krh@248: razor_property_iterator_create(struct razor_set *set, krh@248: struct razor_package *package) krh@248: { krh@248: struct razor_property_iterator *pi; krh@248: richard@301: assert (set != NULL); richard@301: krh@248: pi = zalloc(sizeof *pi); krh@248: pi->set = set; krh@248: krh@248: if (package) { krh@248: pi->index = list_first(&package->properties, krh@248: &set->property_pool); krh@248: } else { krh@248: pi->property = set->properties.data; krh@248: pi->end = set->properties.data + set->properties.size; krh@248: } krh@248: krh@248: return pi; krh@248: } krh@248: krh@269: RAZOR_EXPORT int krh@248: razor_property_iterator_next(struct razor_property_iterator *pi, krh@248: struct razor_property **property, krh@248: const char **name, krh@248: uint32_t *flags, krh@248: const char **version) krh@248: { krh@248: char *pool; krh@248: int valid; krh@248: struct razor_property *p, *properties; krh@248: richard@301: assert (pi != NULL); richard@301: krh@248: if (pi->property) { krh@248: p = pi->property++; krh@248: valid = p < pi->end; krh@248: } else if (pi->index) { krh@248: properties = pi->set->properties.data; krh@248: p = &properties[pi->index->data]; krh@248: pi->index = list_next(pi->index); krh@248: valid = 1; krh@248: } else krh@248: valid = 0; krh@248: krh@248: if (valid) { krh@248: pool = pi->set->string_pool.data; krh@248: *property = p; krh@248: *name = &pool[p->name]; krh@248: *flags = p->flags; krh@248: *version = &pool[p->version]; krh@248: } else { krh@248: *property = NULL; krh@248: } krh@248: krh@248: return valid; krh@248: } krh@248: krh@269: RAZOR_EXPORT void krh@248: razor_property_iterator_destroy(struct razor_property_iterator *pi) krh@248: { krh@248: free(pi); krh@248: } krh@248: ali@351: RAZOR_EXPORT struct razor_file_iterator * ali@377: razor_file_iterator_create(struct razor_set *set, struct razor_package *package, ali@377: int post_order) ali@351: { ali@351: struct razor_file_iterator *fi; ali@351: ali@351: assert (set != NULL); ali@351: assert (package != NULL); ali@351: ali@351: fi = zalloc(sizeof *fi); ali@351: fi->set = set; ali@377: fi->post_order = post_order; ali@377: if (post_order) ali@377: fi->index = list_last(&package->files, &set->file_pool); ali@377: else ali@377: fi->index = list_first(&package->files, &set->file_pool); ali@351: array_init(&fi->path); ali@351: ali@351: return fi; ali@351: } ali@351: ali@351: RAZOR_EXPORT int ali@351: razor_file_iterator_next(struct razor_file_iterator *fi, ali@351: const char **name) ali@351: { ali@351: struct razor_entry *e, *dir, *entries; ali@351: char *pool, *s, *f; ali@351: ali@351: assert (fi != NULL); ali@351: ali@351: if (!fi->index) { ali@351: *name = NULL; ali@351: return 0; ali@351: } ali@351: ali@351: entries = (struct razor_entry *) fi->set->files.data; ali@351: pool = fi->set->file_string_pool.data; ali@351: ali@351: dir = entries; ali@351: fi->path.size = 0; ali@351: for(;;) { ali@351: e = dir; ali@351: do { ali@351: if (entries + fi->index->data == e) { ali@351: f = pool + e->name; ali@351: s = array_add(&fi->path, strlen(f) + 1); ali@351: strcpy(s, f); ali@351: if (fi->path.size == 1) { ali@351: array_add(&fi->path, 1); ali@351: strcpy(fi->path.data, "/"); ali@351: } ali@351: *name = fi->path.data; ali@377: if (fi->post_order) ali@377: fi->index = list_prev(fi->index); ali@377: else ali@377: fi->index = list_next(fi->index); ali@351: return 1; ali@351: } ali@351: } while (!((e++)->flags & RAZOR_ENTRY_LAST)); ali@351: for(e--; e >= dir; e--) ali@351: if (e->start && fi->index->data >= e->start) ali@351: break; ali@351: if (e < dir) ali@351: break; ali@351: f = pool + e->name; ali@351: s = array_add(&fi->path, strlen(f) + 1); ali@351: strcpy(s, f); ali@351: s += strlen(f); ali@351: *s = '/'; ali@351: dir = entries + e->start; ali@351: } ali@351: ali@351: printf("file_iterator_next: Failed to find file %d\n",fi->index->data); ali@351: *name = NULL; ali@351: return 0; ali@351: } ali@351: ali@351: RAZOR_EXPORT void razor_file_iterator_destroy(struct razor_file_iterator *fi) ali@351: { ali@351: assert (fi != NULL); ali@351: ali@351: array_release(&fi->path); ali@351: free(fi); ali@351: } ali@351: krh@248: struct razor_package_query { krh@248: struct razor_set *set; krh@248: char *vector; krh@248: int count; krh@248: }; krh@248: krh@269: RAZOR_EXPORT struct razor_package_query * krh@248: razor_package_query_create(struct razor_set *set) krh@248: { krh@248: struct razor_package_query *pq; krh@248: int count; krh@248: richard@301: assert (set != NULL); richard@301: krh@248: pq = zalloc(sizeof *pq); krh@248: pq->set = set; krh@248: count = set->packages.size / sizeof(struct razor_package); krh@248: pq->vector = zalloc(count * sizeof(char)); krh@248: krh@248: return pq; krh@248: } krh@248: krh@269: RAZOR_EXPORT void krh@248: razor_package_query_add_package(struct razor_package_query *pq, krh@248: struct razor_package *p) krh@248: { krh@248: struct razor_package *packages; krh@248: richard@301: assert (pq != NULL); richard@301: assert (p != NULL); richard@301: krh@248: packages = pq->set->packages.data; krh@248: pq->count += pq->vector[p - packages] ^ 1; krh@248: pq->vector[p - packages] = 1; krh@248: } krh@248: krh@269: RAZOR_EXPORT void krh@248: razor_package_query_add_iterator(struct razor_package_query *pq, krh@248: struct razor_package_iterator *pi) krh@248: { krh@248: struct razor_package *packages, *p; krh@248: richard@301: assert (pq != NULL); richard@301: assert (pi != NULL); richard@301: krh@248: packages = pq->set->packages.data; richard@307: while (razor_package_iterator_next(pi, &p, RAZOR_DETAIL_LAST)) { krh@248: pq->count += pq->vector[p - packages] ^ 1; krh@248: pq->vector[p - packages] = 1; krh@248: } krh@248: } krh@248: krh@269: RAZOR_EXPORT struct razor_package_iterator * krh@248: razor_package_query_finish(struct razor_package_query *pq) krh@248: { krh@248: struct razor_package_iterator *pi; krh@248: struct razor_set *set; krh@248: struct list *index; krh@251: int i, j; krh@248: richard@301: assert (pq != NULL); richard@301: krh@248: set = pq->set; krh@251: if (pq->count > 0) krh@251: index = zalloc(pq->count * sizeof *index); krh@251: else krh@251: index = NULL; krh@248: krh@267: for (i = 0, j = 0; j < pq->count; i++) { krh@248: if (!pq->vector[i]) krh@248: continue; krh@248: krh@248: index[j].data = i; krh@248: if (j == pq->count - 1) krh@248: index[j].flags = 0x80; krh@248: j++; krh@248: } krh@248: krh@251: free(pq->vector); krh@248: free(pq); krh@248: krh@248: pi = razor_package_iterator_create_with_index(set, index); krh@248: pi->free_index = 1; krh@248: krh@248: return pi; krh@248: }