librazor/iterator.c
author J. Ali Harlow <ali@juiblex.co.uk>
Thu Jan 08 15:18:01 2009 +0000 (2009-01-08)
changeset 330 2af301268803
parent 307 95b6bcadd6c4
child 351 48b0adfe3059
permissions -rw-r--r--
Only include sys/wait.h on platforms that have it.
     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 %RAZOR_DETAIL_LAST.
   116  *
   117  * Example: razor_package_iterator_next (pi, package,
   118  *					 RAZOR_DETAIL_NAME, &name,
   119  *					 RAZOR_DETAIL_LAST);
   120  **/
   121 RAZOR_EXPORT int
   122 razor_package_iterator_next(struct razor_package_iterator *pi,
   123 			    struct razor_package **package, ...)
   124 {
   125 	va_list args;
   126 	int valid;
   127 	struct razor_package *p, *packages;
   128 
   129 	assert (pi != NULL);
   130 
   131 	if (pi->package) {
   132 		p = pi->package++;
   133 		valid = p < pi->end;
   134 	} else if (pi->index) {
   135 		packages = pi->set->packages.data;
   136 		p = &packages[pi->index->data];
   137 		pi->index = list_next(pi->index);
   138 		valid = 1;
   139 	} else
   140 		valid = 0;
   141 
   142 	if (valid == 0) {
   143 		*package = NULL;
   144 		goto out;
   145 	}
   146 
   147 	*package = p;
   148 
   149 	va_start(args, NULL);
   150 	razor_package_get_details_varg (pi->set, p, args);
   151 	va_end (args);
   152 out:
   153 	return valid;
   154 }
   155 
   156 RAZOR_EXPORT void
   157 razor_package_iterator_destroy(struct razor_package_iterator *pi)
   158 {
   159 	assert (pi != NULL);
   160 
   161 	if (pi->free_index)
   162 		free(pi->index);
   163 
   164 	free(pi);
   165 }
   166 
   167 RAZOR_EXPORT struct razor_property_iterator *
   168 razor_property_iterator_create(struct razor_set *set,
   169 			       struct razor_package *package)
   170 {
   171 	struct razor_property_iterator *pi;
   172 
   173 	assert (set != NULL);
   174 
   175 	pi = zalloc(sizeof *pi);
   176 	pi->set = set;
   177 
   178 	if (package) {
   179 		pi->index = list_first(&package->properties,
   180 				       &set->property_pool);
   181 	} else {
   182 		pi->property = set->properties.data;
   183 		pi->end = set->properties.data + set->properties.size;
   184 	}
   185 
   186 	return pi;
   187 }
   188 
   189 RAZOR_EXPORT int
   190 razor_property_iterator_next(struct razor_property_iterator *pi,
   191 			     struct razor_property **property,
   192 			     const char **name,
   193 			     uint32_t *flags,
   194 			     const char **version)
   195 {
   196 	char *pool;
   197 	int valid;
   198 	struct razor_property *p, *properties;
   199 
   200 	assert (pi != NULL);
   201 
   202 	if (pi->property) {
   203 		p = pi->property++;
   204 		valid = p < pi->end;
   205 	} else if (pi->index) {
   206 		properties = pi->set->properties.data;
   207 		p = &properties[pi->index->data];
   208 		pi->index = list_next(pi->index);
   209 		valid = 1;
   210 	} else
   211 		valid = 0;
   212 
   213 	if (valid) {
   214 		pool = pi->set->string_pool.data;
   215 		*property = p;
   216 		*name = &pool[p->name];
   217 		*flags = p->flags;
   218 		*version = &pool[p->version];
   219 	} else {
   220 		*property = NULL;
   221 	}
   222 
   223 	return valid;
   224 }
   225 
   226 RAZOR_EXPORT void
   227 razor_property_iterator_destroy(struct razor_property_iterator *pi)
   228 {
   229 	free(pi);
   230 }
   231 
   232 struct razor_package_query {
   233 	struct razor_set *set;
   234 	char *vector;
   235 	int count;
   236 };
   237 
   238 RAZOR_EXPORT struct razor_package_query *
   239 razor_package_query_create(struct razor_set *set)
   240 {
   241 	struct razor_package_query *pq;
   242 	int count;
   243 
   244 	assert (set != NULL);
   245 
   246 	pq = zalloc(sizeof *pq);
   247 	pq->set = set;
   248 	count = set->packages.size / sizeof(struct razor_package);
   249 	pq->vector = zalloc(count * sizeof(char));
   250 
   251 	return pq;
   252 }
   253 
   254 RAZOR_EXPORT void
   255 razor_package_query_add_package(struct razor_package_query *pq,
   256 				struct razor_package *p)
   257 {
   258 	struct razor_package *packages;
   259 
   260 	assert (pq != NULL);
   261 	assert (p != NULL);
   262 
   263 	packages = pq->set->packages.data;
   264 	pq->count += pq->vector[p - packages] ^ 1;
   265 	pq->vector[p - packages] = 1;
   266 }
   267 
   268 RAZOR_EXPORT void
   269 razor_package_query_add_iterator(struct razor_package_query *pq,
   270 				 struct razor_package_iterator *pi)
   271 {
   272 	struct razor_package *packages, *p;
   273 
   274 	assert (pq != NULL);
   275 	assert (pi != NULL);
   276 
   277 	packages = pq->set->packages.data;
   278 	while (razor_package_iterator_next(pi, &p, RAZOR_DETAIL_LAST)) {
   279 		pq->count += pq->vector[p - packages] ^ 1;
   280 		pq->vector[p - packages] = 1;
   281 	}
   282 }
   283 
   284 RAZOR_EXPORT struct razor_package_iterator *
   285 razor_package_query_finish(struct razor_package_query *pq)
   286 {
   287 	struct razor_package_iterator *pi;
   288 	struct razor_set *set;
   289 	struct list *index;
   290 	int i, j;
   291 
   292 	assert (pq != NULL);
   293 
   294 	set = pq->set;
   295 	if (pq->count > 0)
   296 		index = zalloc(pq->count * sizeof *index);
   297 	else
   298 		index = NULL;
   299 
   300 	for (i = 0, j = 0; j < pq->count; i++) {
   301 		if (!pq->vector[i])
   302 			continue;
   303 
   304 		index[j].data = i;
   305 		if (j == pq->count - 1)
   306 			index[j].flags = 0x80;
   307 		j++;
   308 	}
   309 
   310 	free(pq->vector);
   311 	free(pq);
   312 
   313 	pi = razor_package_iterator_create_with_index(set, index);
   314 	pi->free_index = 1;
   315 
   316 	return pi;
   317 }