librazor/iterator.c
author J. Ali Harlow <ali@juiblex.co.uk>
Thu Oct 01 20:02:12 2009 +0100 (2009-10-01)
changeset 388 6a6462ce8a08
parent 351 48b0adfe3059
child 438 fab0b8a61dcb
permissions -rw-r--r--
Implement proper locking
     1 /*
     2  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     3  * Copyright (C) 2008  Red Hat, Inc
     4  * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
     5  *
     6  * This program is free software; you can redistribute it and/or modify
     7  * it under the terms of the GNU General Public License as published by
     8  * the Free Software Foundation; either version 2 of the License, or
     9  * (at your option) any later version.
    10  *
    11  * This program is distributed in the hope that it will be useful,
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  * GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along
    17  * with this program; if not, write to the Free Software Foundation, Inc.,
    18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    19  */
    20 
    21 #define _GNU_SOURCE
    22 
    23 #include <stdarg.h>
    24 #include <string.h>
    25 #include <assert.h>
    26 
    27 #include "razor-internal.h"
    28 #include "razor.h"
    29 
    30 static struct razor_package_iterator *
    31 razor_package_iterator_create_with_index(struct razor_set *set,
    32 					 struct list *index)
    33 {
    34 	struct razor_package_iterator *pi;
    35 
    36 	pi = zalloc(sizeof *pi);
    37 	pi->set = set;
    38 	pi->index = index;
    39 
    40 	return pi;
    41 }
    42 
    43 static struct razor_package_iterator *
    44 razor_package_iterator_create_empty(struct razor_set *set)
    45 {
    46 	struct razor_package_iterator *pi;
    47 	return zalloc(sizeof *pi);
    48 }
    49 
    50 RAZOR_EXPORT struct razor_package_iterator *
    51 razor_package_iterator_create(struct razor_set *set)
    52 {
    53 	struct razor_package_iterator *pi;
    54 
    55 	assert (set != NULL);
    56 
    57 	pi = zalloc(sizeof *pi);
    58 	pi->set = set;
    59 	pi->end = set->packages.data + set->packages.size;
    60 	pi->package = set->packages.data;
    61 
    62 	return pi;
    63 }
    64 
    65 RAZOR_EXPORT void
    66 razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
    67 					 struct razor_set *set,
    68 					 struct razor_property *property)
    69 {
    70 	assert (pi != NULL);
    71 	assert (set != NULL);
    72 	assert (property != NULL);
    73 
    74 	memset(pi, 0, sizeof *pi);
    75 	pi->set = set;
    76 	pi->index = list_first(&property->packages, &set->package_pool);
    77 }
    78 
    79 RAZOR_EXPORT struct razor_package_iterator *
    80 razor_package_iterator_create_for_property(struct razor_set *set,
    81 					   struct razor_property *property)
    82 {
    83 	struct list *index;
    84 
    85 	assert (set != NULL);
    86 	assert (property != NULL);
    87 
    88 	index = list_first(&property->packages, &set->package_pool);
    89 	return razor_package_iterator_create_with_index(set, index);
    90 }
    91 
    92 RAZOR_EXPORT struct razor_package_iterator *
    93 razor_package_iterator_create_for_file(struct razor_set *set,
    94 				       const char *filename)
    95 {
    96 	struct razor_entry *entry;
    97 	struct list *index;
    98 
    99 	assert (set != NULL);
   100 	assert (filename != NULL);
   101 
   102 	entry = razor_set_find_entry(set, set->files.data, filename);
   103 	if (entry == NULL)
   104 		return razor_package_iterator_create_empty(set);
   105 
   106 	index = list_first(&entry->packages, &set->package_pool);
   107 	return razor_package_iterator_create_with_index(set, index);
   108 }
   109 
   110 /**
   111  * razor_package_iterator_next:
   112  * @pi: a %razor_package_iterator
   113  * @package: a %razor_package
   114  *
   115  * Gets the next iteratr along with any vararg data.
   116  * The vararg must be terminated with %RAZOR_DETAIL_LAST.
   117  *
   118  * Example: razor_package_iterator_next (pi, package,
   119  *					 RAZOR_DETAIL_NAME, &name,
   120  *					 RAZOR_DETAIL_LAST);
   121  **/
   122 RAZOR_EXPORT int
   123 razor_package_iterator_next(struct razor_package_iterator *pi,
   124 			    struct razor_package **package, ...)
   125 {
   126 	va_list args;
   127 	int valid;
   128 	struct razor_package *p, *packages;
   129 
   130 	assert (pi != NULL);
   131 
   132 	if (pi->package) {
   133 		p = pi->package++;
   134 		valid = p < pi->end;
   135 	} else if (pi->index) {
   136 		packages = pi->set->packages.data;
   137 		p = &packages[pi->index->data];
   138 		pi->index = list_next(pi->index);
   139 		valid = 1;
   140 	} else
   141 		valid = 0;
   142 
   143 	if (valid == 0) {
   144 		*package = NULL;
   145 		goto out;
   146 	}
   147 
   148 	*package = p;
   149 
   150 	va_start(args, NULL);
   151 	razor_package_get_details_varg (pi->set, p, args);
   152 	va_end (args);
   153 out:
   154 	return valid;
   155 }
   156 
   157 RAZOR_EXPORT void
   158 razor_package_iterator_destroy(struct razor_package_iterator *pi)
   159 {
   160 	assert (pi != NULL);
   161 
   162 	if (pi->free_index)
   163 		free(pi->index);
   164 
   165 	free(pi);
   166 }
   167 
   168 RAZOR_EXPORT struct razor_property_iterator *
   169 razor_property_iterator_create(struct razor_set *set,
   170 			       struct razor_package *package)
   171 {
   172 	struct razor_property_iterator *pi;
   173 
   174 	assert (set != NULL);
   175 
   176 	pi = zalloc(sizeof *pi);
   177 	pi->set = set;
   178 
   179 	if (package) {
   180 		pi->index = list_first(&package->properties,
   181 				       &set->property_pool);
   182 	} else {
   183 		pi->property = set->properties.data;
   184 		pi->end = set->properties.data + set->properties.size;
   185 	}
   186 
   187 	return pi;
   188 }
   189 
   190 RAZOR_EXPORT int
   191 razor_property_iterator_next(struct razor_property_iterator *pi,
   192 			     struct razor_property **property,
   193 			     const char **name,
   194 			     uint32_t *flags,
   195 			     const char **version)
   196 {
   197 	char *pool;
   198 	int valid;
   199 	struct razor_property *p, *properties;
   200 
   201 	assert (pi != NULL);
   202 
   203 	if (pi->property) {
   204 		p = pi->property++;
   205 		valid = p < pi->end;
   206 	} else if (pi->index) {
   207 		properties = pi->set->properties.data;
   208 		p = &properties[pi->index->data];
   209 		pi->index = list_next(pi->index);
   210 		valid = 1;
   211 	} else
   212 		valid = 0;
   213 
   214 	if (valid) {
   215 		pool = pi->set->string_pool.data;
   216 		*property = p;
   217 		*name = &pool[p->name];
   218 		*flags = p->flags;
   219 		*version = &pool[p->version];
   220 	} else {
   221 		*property = NULL;
   222 	}
   223 
   224 	return valid;
   225 }
   226 
   227 RAZOR_EXPORT void
   228 razor_property_iterator_destroy(struct razor_property_iterator *pi)
   229 {
   230 	free(pi);
   231 }
   232 
   233 RAZOR_EXPORT struct razor_file_iterator *
   234 razor_file_iterator_create(struct razor_set *set, struct razor_package *package,
   235 			   int post_order)
   236 {
   237 	struct razor_file_iterator *fi;
   238 
   239 	assert (set != NULL);
   240 	assert (package != NULL);
   241 
   242 	fi = zalloc(sizeof *fi);
   243 	fi->set = set;
   244 	fi->post_order = post_order;
   245 	if (post_order)
   246 		fi->index = list_last(&package->files, &set->file_pool);
   247 	else
   248 		fi->index = list_first(&package->files, &set->file_pool);
   249 	array_init(&fi->path);
   250 
   251 	return fi;
   252 }
   253 
   254 RAZOR_EXPORT int
   255 razor_file_iterator_next(struct razor_file_iterator *fi,
   256 			 const char **name)
   257 {
   258 	struct razor_entry *e, *dir, *entries;
   259 	char *pool, *s, *f;
   260 
   261 	assert (fi != NULL);
   262 
   263 	if (!fi->index) {
   264 		*name = NULL;
   265 		return 0;
   266 	}
   267 
   268 	entries = (struct razor_entry *) fi->set->files.data;
   269 	pool = fi->set->file_string_pool.data;
   270 
   271 	dir = entries;
   272 	fi->path.size = 0;
   273 	for(;;) {
   274 		e = dir;
   275 		do {
   276 			if (entries + fi->index->data == e) {
   277 				f = pool + e->name;
   278 				s = array_add(&fi->path, strlen(f) + 1);
   279 				strcpy(s, f);
   280 				if (fi->path.size == 1) {
   281 					array_add(&fi->path, 1);
   282 					strcpy(fi->path.data, "/");
   283 				}
   284 				*name = fi->path.data;
   285 				if (fi->post_order)
   286 					fi->index = list_prev(fi->index);
   287 				else
   288 					fi->index = list_next(fi->index);
   289 				return 1;
   290 			}
   291 		} while (!((e++)->flags & RAZOR_ENTRY_LAST));
   292 		for(e--; e >= dir; e--)
   293 			if (e->start && fi->index->data >= e->start)
   294 				break;
   295 		if (e < dir)
   296 			break;
   297 		f = pool + e->name;
   298 		s = array_add(&fi->path, strlen(f) + 1);
   299 		strcpy(s, f);
   300 		s += strlen(f);
   301 		*s = '/';
   302 		dir = entries + e->start;
   303 	}
   304 
   305 	printf("file_iterator_next: Failed to find file %d\n",fi->index->data);
   306 	*name = NULL;
   307 	return 0;
   308 }
   309 
   310 RAZOR_EXPORT void razor_file_iterator_destroy(struct razor_file_iterator *fi)
   311 {
   312 	assert (fi != NULL);
   313 
   314 	array_release(&fi->path);
   315 	free(fi);
   316 }
   317 
   318 struct razor_package_query {
   319 	struct razor_set *set;
   320 	char *vector;
   321 	int count;
   322 };
   323 
   324 RAZOR_EXPORT struct razor_package_query *
   325 razor_package_query_create(struct razor_set *set)
   326 {
   327 	struct razor_package_query *pq;
   328 	int count;
   329 
   330 	assert (set != NULL);
   331 
   332 	pq = zalloc(sizeof *pq);
   333 	pq->set = set;
   334 	count = set->packages.size / sizeof(struct razor_package);
   335 	pq->vector = zalloc(count * sizeof(char));
   336 
   337 	return pq;
   338 }
   339 
   340 RAZOR_EXPORT void
   341 razor_package_query_add_package(struct razor_package_query *pq,
   342 				struct razor_package *p)
   343 {
   344 	struct razor_package *packages;
   345 
   346 	assert (pq != NULL);
   347 	assert (p != NULL);
   348 
   349 	packages = pq->set->packages.data;
   350 	pq->count += pq->vector[p - packages] ^ 1;
   351 	pq->vector[p - packages] = 1;
   352 }
   353 
   354 RAZOR_EXPORT void
   355 razor_package_query_add_iterator(struct razor_package_query *pq,
   356 				 struct razor_package_iterator *pi)
   357 {
   358 	struct razor_package *packages, *p;
   359 
   360 	assert (pq != NULL);
   361 	assert (pi != NULL);
   362 
   363 	packages = pq->set->packages.data;
   364 	while (razor_package_iterator_next(pi, &p, RAZOR_DETAIL_LAST)) {
   365 		pq->count += pq->vector[p - packages] ^ 1;
   366 		pq->vector[p - packages] = 1;
   367 	}
   368 }
   369 
   370 RAZOR_EXPORT struct razor_package_iterator *
   371 razor_package_query_finish(struct razor_package_query *pq)
   372 {
   373 	struct razor_package_iterator *pi;
   374 	struct razor_set *set;
   375 	struct list *index;
   376 	int i, j;
   377 
   378 	assert (pq != NULL);
   379 
   380 	set = pq->set;
   381 	if (pq->count > 0)
   382 		index = zalloc(pq->count * sizeof *index);
   383 	else
   384 		index = NULL;
   385 
   386 	for (i = 0, j = 0; j < pq->count; i++) {
   387 		if (!pq->vector[i])
   388 			continue;
   389 
   390 		index[j].data = i;
   391 		if (j == pq->count - 1)
   392 			index[j].flags = 0x80;
   393 		j++;
   394 	}
   395 
   396 	free(pq->vector);
   397 	free(pq);
   398 
   399 	pi = razor_package_iterator_create_with_index(set, index);
   400 	pi->free_index = 1;
   401 
   402 	return pi;
   403 }