librazor/iterator.c
author Richard Hughes <richard@hughsie.com>
Mon Jun 30 08:51:26 2008 +0100 (2008-06-30)
changeset 302 9b71b537d175
parent 301 4124c37fd953
child 303 2d450078e46e
permissions -rw-r--r--
convert razor_package_get_details() and razor_package_iterator_next() to varargs

The functions for getting package details about a package were limited to a few
things, when in the future we will want to support much more about a package.
The iterator was also limited to name,version,arch when most of the time we
didn't need all this data.
     1 /*
     2  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     3  * Copyright (C) 2008  Red Hat, Inc
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation; either version 2 of the License, or
     8  * (at your option) any later version.
     9  *
    10  * This program is distributed in the hope that it will be useful,
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  * GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along
    16  * with this program; if not, write to the Free Software Foundation, Inc.,
    17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    18  */
    19 
    20 #define _GNU_SOURCE
    21 
    22 #include <stdarg.h>
    23 #include <string.h>
    24 #include <assert.h>
    25 
    26 #include "razor-internal.h"
    27 #include "razor.h"
    28 
    29 static struct razor_package_iterator *
    30 razor_package_iterator_create_with_index(struct razor_set *set,
    31 					 struct list *index)
    32 {
    33 	struct razor_package_iterator *pi;
    34 
    35 	pi = zalloc(sizeof *pi);
    36 	pi->set = set;
    37 	pi->index = index;
    38 
    39 	return pi;
    40 }
    41 
    42 static struct razor_package_iterator *
    43 razor_package_iterator_create_empty(struct razor_set *set)
    44 {
    45 	struct razor_package_iterator *pi;
    46 	return zalloc(sizeof *pi);
    47 }
    48 
    49 RAZOR_EXPORT struct razor_package_iterator *
    50 razor_package_iterator_create(struct razor_set *set)
    51 {
    52 	struct razor_package_iterator *pi;
    53 
    54 	assert (set != NULL);
    55 
    56 	pi = zalloc(sizeof *pi);
    57 	pi->set = set;
    58 	pi->end = set->packages.data + set->packages.size;
    59 	pi->package = set->packages.data;
    60 
    61 	return pi;
    62 }
    63 
    64 RAZOR_EXPORT void
    65 razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
    66 					 struct razor_set *set,
    67 					 struct razor_property *property)
    68 {
    69 	assert (pi != NULL);
    70 	assert (set != NULL);
    71 	assert (property != NULL);
    72 
    73 	memset(pi, 0, sizeof *pi);
    74 	pi->set = set;
    75 	pi->index = list_first(&property->packages, &set->package_pool);
    76 }
    77 
    78 RAZOR_EXPORT struct razor_package_iterator *
    79 razor_package_iterator_create_for_property(struct razor_set *set,
    80 					   struct razor_property *property)
    81 {
    82 	struct list *index;
    83 
    84 	assert (set != NULL);
    85 	assert (property != NULL);
    86 
    87 	index = list_first(&property->packages, &set->package_pool);
    88 	return razor_package_iterator_create_with_index(set, index);
    89 }
    90 
    91 RAZOR_EXPORT struct razor_package_iterator *
    92 razor_package_iterator_create_for_file(struct razor_set *set,
    93 				       const char *filename)
    94 {
    95 	struct razor_entry *entry;
    96 	struct list *index;
    97 
    98 	assert (set != NULL);
    99 	assert (filename != NULL);
   100 
   101 	entry = razor_set_find_entry(set, set->files.data, filename);
   102 	if (entry == NULL)
   103 		return razor_package_iterator_create_empty(set);
   104 
   105 	index = list_first(&entry->packages, &set->package_pool);
   106 	return razor_package_iterator_create_with_index(set, index);
   107 }
   108 
   109 /**
   110  * razor_package_iterator_next:
   111  * @pi: a %razor_package_iterator
   112  * @package: a %razor_package
   113  *
   114  * Gets the next iteratr along with any vararg data.
   115  * The vararg must be terminated with zero.
   116  *
   117  * Example: razor_package_iterator_next (pi, package, RAZOR_DETAIL_NAME, &name, 0);
   118  **/
   119 RAZOR_EXPORT int
   120 razor_package_iterator_next(struct razor_package_iterator *pi,
   121 			    struct razor_package **package, ...)
   122 {
   123 	va_list args;
   124 	int valid;
   125 	struct razor_package *p, *packages;
   126 
   127 	assert (pi != NULL);
   128 
   129 	if (pi->package) {
   130 		p = pi->package++;
   131 		valid = p < pi->end;
   132 	} else if (pi->index) {
   133 		packages = pi->set->packages.data;
   134 		p = &packages[pi->index->data];
   135 		pi->index = list_next(pi->index);
   136 		valid = 1;
   137 	} else
   138 		valid = 0;
   139 
   140 	if (valid == 0) {
   141 		*package = NULL;
   142 		goto out;
   143 	}
   144 
   145 	*package = p;
   146 
   147 	va_start(args, NULL);
   148 	razor_package_get_details_varg (pi->set, p, args);
   149 	va_end (args);
   150 out:
   151 	return valid;
   152 }
   153 
   154 RAZOR_EXPORT void
   155 razor_package_iterator_destroy(struct razor_package_iterator *pi)
   156 {
   157 	assert (pi != NULL);
   158 
   159 	if (pi->free_index)
   160 		free(pi->index);
   161 
   162 	free(pi);
   163 }
   164 
   165 RAZOR_EXPORT struct razor_property_iterator *
   166 razor_property_iterator_create(struct razor_set *set,
   167 			       struct razor_package *package)
   168 {
   169 	struct razor_property_iterator *pi;
   170 
   171 	assert (set != NULL);
   172 	assert (package != NULL);
   173 
   174 	pi = zalloc(sizeof *pi);
   175 	pi->set = set;
   176 
   177 	if (package) {
   178 		pi->index = list_first(&package->properties,
   179 				       &set->property_pool);
   180 	} else {
   181 		pi->property = set->properties.data;
   182 		pi->end = set->properties.data + set->properties.size;
   183 	}
   184 
   185 	return pi;
   186 }
   187 
   188 RAZOR_EXPORT int
   189 razor_property_iterator_next(struct razor_property_iterator *pi,
   190 			     struct razor_property **property,
   191 			     const char **name,
   192 			     uint32_t *flags,
   193 			     const char **version)
   194 {
   195 	char *pool;
   196 	int valid;
   197 	struct razor_property *p, *properties;
   198 
   199 	assert (pi != NULL);
   200 
   201 	if (pi->property) {
   202 		p = pi->property++;
   203 		valid = p < pi->end;
   204 	} else if (pi->index) {
   205 		properties = pi->set->properties.data;
   206 		p = &properties[pi->index->data];
   207 		pi->index = list_next(pi->index);
   208 		valid = 1;
   209 	} else
   210 		valid = 0;
   211 
   212 	if (valid) {
   213 		pool = pi->set->string_pool.data;
   214 		*property = p;
   215 		*name = &pool[p->name];
   216 		*flags = p->flags;
   217 		*version = &pool[p->version];
   218 	} else {
   219 		*property = NULL;
   220 	}
   221 
   222 	return valid;
   223 }
   224 
   225 RAZOR_EXPORT void
   226 razor_property_iterator_destroy(struct razor_property_iterator *pi)
   227 {
   228 	free(pi);
   229 }
   230 
   231 struct razor_package_query {
   232 	struct razor_set *set;
   233 	char *vector;
   234 	int count;
   235 };
   236 
   237 RAZOR_EXPORT struct razor_package_query *
   238 razor_package_query_create(struct razor_set *set)
   239 {
   240 	struct razor_package_query *pq;
   241 	int count;
   242 
   243 	assert (set != NULL);
   244 
   245 	pq = zalloc(sizeof *pq);
   246 	pq->set = set;
   247 	count = set->packages.size / sizeof(struct razor_package);
   248 	pq->vector = zalloc(count * sizeof(char));
   249 
   250 	return pq;
   251 }
   252 
   253 RAZOR_EXPORT void
   254 razor_package_query_add_package(struct razor_package_query *pq,
   255 				struct razor_package *p)
   256 {
   257 	struct razor_package *packages;
   258 
   259 	assert (pq != NULL);
   260 	assert (p != NULL);
   261 
   262 	packages = pq->set->packages.data;
   263 	pq->count += pq->vector[p - packages] ^ 1;
   264 	pq->vector[p - packages] = 1;
   265 }
   266 
   267 RAZOR_EXPORT void
   268 razor_package_query_add_iterator(struct razor_package_query *pq,
   269 				 struct razor_package_iterator *pi)
   270 {
   271 	struct razor_package *packages, *p;
   272 
   273 	assert (pq != NULL);
   274 	assert (pi != NULL);
   275 
   276 	packages = pq->set->packages.data;
   277 	while (razor_package_iterator_next(pi, &p, 0)) {
   278 		pq->count += pq->vector[p - packages] ^ 1;
   279 		pq->vector[p - packages] = 1;
   280 	}
   281 }
   282 
   283 RAZOR_EXPORT struct razor_package_iterator *
   284 razor_package_query_finish(struct razor_package_query *pq)
   285 {
   286 	struct razor_package_iterator *pi;
   287 	struct razor_set *set;
   288 	struct list *index;
   289 	int i, j;
   290 
   291 	assert (pq != NULL);
   292 
   293 	set = pq->set;
   294 	if (pq->count > 0)
   295 		index = zalloc(pq->count * sizeof *index);
   296 	else
   297 		index = NULL;
   298 
   299 	for (i = 0, j = 0; j < pq->count; i++) {
   300 		if (!pq->vector[i])
   301 			continue;
   302 
   303 		index[j].data = i;
   304 		if (j == pq->count - 1)
   305 			index[j].flags = 0x80;
   306 		j++;
   307 	}
   308 
   309 	free(pq->vector);
   310 	free(pq);
   311 
   312 	pi = razor_package_iterator_create_with_index(set, index);
   313 	pi->free_index = 1;
   314 
   315 	return pi;
   316 }