krh@248: /* krh@248: * Copyright (C) 2008 Kristian Høgsberg krh@248: * Copyright (C) 2008 Red Hat, Inc 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: 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: 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: }