librazor/iterator.c
author J. Ali Harlow <ali@juiblex.co.uk>
Fri May 01 16:43:37 2009 +0100 (2009-05-01)
changeset 362 cf88b5df2884
parent 308 f4761f529b9e
child 377 5549419824b4
permissions -rw-r--r--
Set RPM_INSTALL_PREFIX{n} environment variables for use in scripts
     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 {
   236 	struct razor_file_iterator *fi;
   237 
   238 	assert (set != NULL);
   239 	assert (package != NULL);
   240 
   241 	fi = zalloc(sizeof *fi);
   242 	fi->set = set;
   243 	fi->index = list_first(&package->files, &set->file_pool);
   244 	array_init(&fi->path);
   245 
   246 	return fi;
   247 }
   248 
   249 RAZOR_EXPORT int
   250 razor_file_iterator_next(struct razor_file_iterator *fi,
   251 			 const char **name)
   252 {
   253 	struct razor_entry *e, *dir, *entries;
   254 	char *pool, *s, *f;
   255 
   256 	assert (fi != NULL);
   257 
   258 	if (!fi->index) {
   259 		*name = NULL;
   260 		return 0;
   261 	}
   262 
   263 	entries = (struct razor_entry *) fi->set->files.data;
   264 	pool = fi->set->file_string_pool.data;
   265 
   266 	dir = entries;
   267 	fi->path.size = 0;
   268 	for(;;) {
   269 		e = dir;
   270 		do {
   271 			if (entries + fi->index->data == e) {
   272 				f = pool + e->name;
   273 				s = array_add(&fi->path, strlen(f) + 1);
   274 				strcpy(s, f);
   275 				if (fi->path.size == 1) {
   276 					array_add(&fi->path, 1);
   277 					strcpy(fi->path.data, "/");
   278 				}
   279 				*name = fi->path.data;
   280 				fi->index = list_next(fi->index);
   281 				return 1;
   282 			}
   283 		} while (!((e++)->flags & RAZOR_ENTRY_LAST));
   284 		for(e--; e >= dir; e--)
   285 			if (e->start && fi->index->data >= e->start)
   286 				break;
   287 		if (e < dir)
   288 			break;
   289 		f = pool + e->name;
   290 		s = array_add(&fi->path, strlen(f) + 1);
   291 		strcpy(s, f);
   292 		s += strlen(f);
   293 		*s = '/';
   294 		dir = entries + e->start;
   295 	}
   296 
   297 	printf("file_iterator_next: Failed to find file %d\n",fi->index->data);
   298 	*name = NULL;
   299 	return 0;
   300 }
   301 
   302 RAZOR_EXPORT void razor_file_iterator_destroy(struct razor_file_iterator *fi)
   303 {
   304 	assert (fi != NULL);
   305 
   306 	array_release(&fi->path);
   307 	free(fi);
   308 }
   309 
   310 struct razor_package_query {
   311 	struct razor_set *set;
   312 	char *vector;
   313 	int count;
   314 };
   315 
   316 RAZOR_EXPORT struct razor_package_query *
   317 razor_package_query_create(struct razor_set *set)
   318 {
   319 	struct razor_package_query *pq;
   320 	int count;
   321 
   322 	assert (set != NULL);
   323 
   324 	pq = zalloc(sizeof *pq);
   325 	pq->set = set;
   326 	count = set->packages.size / sizeof(struct razor_package);
   327 	pq->vector = zalloc(count * sizeof(char));
   328 
   329 	return pq;
   330 }
   331 
   332 RAZOR_EXPORT void
   333 razor_package_query_add_package(struct razor_package_query *pq,
   334 				struct razor_package *p)
   335 {
   336 	struct razor_package *packages;
   337 
   338 	assert (pq != NULL);
   339 	assert (p != NULL);
   340 
   341 	packages = pq->set->packages.data;
   342 	pq->count += pq->vector[p - packages] ^ 1;
   343 	pq->vector[p - packages] = 1;
   344 }
   345 
   346 RAZOR_EXPORT void
   347 razor_package_query_add_iterator(struct razor_package_query *pq,
   348 				 struct razor_package_iterator *pi)
   349 {
   350 	struct razor_package *packages, *p;
   351 
   352 	assert (pq != NULL);
   353 	assert (pi != NULL);
   354 
   355 	packages = pq->set->packages.data;
   356 	while (razor_package_iterator_next(pi, &p, RAZOR_DETAIL_LAST)) {
   357 		pq->count += pq->vector[p - packages] ^ 1;
   358 		pq->vector[p - packages] = 1;
   359 	}
   360 }
   361 
   362 RAZOR_EXPORT struct razor_package_iterator *
   363 razor_package_query_finish(struct razor_package_query *pq)
   364 {
   365 	struct razor_package_iterator *pi;
   366 	struct razor_set *set;
   367 	struct list *index;
   368 	int i, j;
   369 
   370 	assert (pq != NULL);
   371 
   372 	set = pq->set;
   373 	if (pq->count > 0)
   374 		index = zalloc(pq->count * sizeof *index);
   375 	else
   376 		index = NULL;
   377 
   378 	for (i = 0, j = 0; j < pq->count; i++) {
   379 		if (!pq->vector[i])
   380 			continue;
   381 
   382 		index[j].data = i;
   383 		if (j == pq->count - 1)
   384 			index[j].flags = 0x80;
   385 		j++;
   386 	}
   387 
   388 	free(pq->vector);
   389 	free(pq);
   390 
   391 	pi = razor_package_iterator_create_with_index(set, index);
   392 	pi->free_index = 1;
   393 
   394 	return pi;
   395 }