librazor/iterator.c
author J. Ali Harlow <ali@juiblex.co.uk>
Mon Jul 04 10:48:18 2016 +0100 (2016-07-04)
changeset 475 008c75a5e08d
parent 458 3f841a46eab5
permissions -rw-r--r--
Switch to a URI-based API
     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 "config.h"
    24 #include <stdarg.h>
    25 #include <string.h>
    26 #include <assert.h>
    27 #include <stdio.h>
    28 
    29 #include "razor-internal.h"
    30 #include "razor.h"
    31 
    32 static struct razor_package_iterator *
    33 razor_package_iterator_create_with_index(struct razor_set *set,
    34 					 struct list *index)
    35 {
    36 	struct razor_package_iterator *pi;
    37 
    38 	pi = zalloc(sizeof *pi);
    39 	pi->set = set;
    40 	pi->index = index;
    41 
    42 	return pi;
    43 }
    44 
    45 static struct razor_package_iterator *
    46 razor_package_iterator_create_empty(struct razor_set *set)
    47 {
    48 	struct razor_package_iterator *pi;
    49 	return zalloc(sizeof *pi);
    50 }
    51 
    52 RAZOR_EXPORT struct razor_package_iterator *
    53 razor_package_iterator_create(struct razor_set *set)
    54 {
    55 	struct razor_package_iterator *pi;
    56 
    57 	assert (set != NULL);
    58 
    59 	pi = zalloc(sizeof *pi);
    60 	pi->set = set;
    61 	pi->end = set->packages.data + set->packages.size;
    62 	pi->package = set->packages.data;
    63 
    64 	return pi;
    65 }
    66 
    67 RAZOR_EXPORT void
    68 razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
    69 					 struct razor_set *set,
    70 					 struct razor_property *property)
    71 {
    72 	assert (pi != NULL);
    73 	assert (set != NULL);
    74 	assert (property != NULL);
    75 
    76 	memset(pi, 0, sizeof *pi);
    77 	pi->set = set;
    78 	pi->index = list_first(&property->packages, &set->package_pool);
    79 }
    80 
    81 RAZOR_EXPORT struct razor_package_iterator *
    82 razor_package_iterator_create_for_property(struct razor_set *set,
    83 					   struct razor_property *property)
    84 {
    85 	struct list *index;
    86 
    87 	assert (set != NULL);
    88 	assert (property != NULL);
    89 
    90 	index = list_first(&property->packages, &set->package_pool);
    91 	return razor_package_iterator_create_with_index(set, index);
    92 }
    93 
    94 RAZOR_EXPORT struct razor_package_iterator *
    95 razor_package_iterator_create_for_file(struct razor_set *set,
    96 				       const char *filename)
    97 {
    98 	struct razor_entry *entry;
    99 	struct list *index;
   100 
   101 	assert (set != NULL);
   102 	assert (filename != NULL);
   103 
   104 	entry = razor_set_find_entry(set, set->files.data, filename);
   105 	if (entry == NULL)
   106 		return razor_package_iterator_create_empty(set);
   107 
   108 	index = list_first(&entry->packages, &set->package_pool);
   109 	return razor_package_iterator_create_with_index(set, index);
   110 }
   111 
   112 /**
   113  * razor_package_iterator_next:
   114  * @pi: a %razor_package_iterator
   115  * @package: a %razor_package
   116  *
   117  * Gets the next iteratr along with any vararg data.
   118  * The vararg must be terminated with %RAZOR_DETAIL_LAST.
   119  *
   120  * Example: razor_package_iterator_next (pi, package,
   121  *					 RAZOR_DETAIL_NAME, &name,
   122  *					 RAZOR_DETAIL_LAST);
   123  **/
   124 RAZOR_EXPORT int
   125 razor_package_iterator_next(struct razor_package_iterator *pi,
   126 			    struct razor_package **package, ...)
   127 {
   128 	va_list args;
   129 	int valid;
   130 	struct razor_package *p, *packages;
   131 
   132 	assert (pi != NULL);
   133 
   134 	if (pi->package) {
   135 		p = pi->package++;
   136 		valid = p < pi->end;
   137 	} else if (pi->index) {
   138 		packages = pi->set->packages.data;
   139 		p = &packages[pi->index->data];
   140 		pi->index = list_next(pi->index);
   141 		valid = 1;
   142 	} else
   143 		valid = 0;
   144 
   145 	if (valid == 0) {
   146 		*package = NULL;
   147 		goto out;
   148 	}
   149 
   150 	*package = p;
   151 
   152 	va_start(args, NULL);
   153 	razor_package_get_details_varg (pi->set, p, args);
   154 	va_end (args);
   155 out:
   156 	return valid;
   157 }
   158 
   159 RAZOR_EXPORT void
   160 razor_package_iterator_destroy(struct razor_package_iterator *pi)
   161 {
   162 	assert (pi != NULL);
   163 
   164 	if (pi->alloced_index)
   165 		free(pi->alloced_index);
   166 
   167 	free(pi);
   168 }
   169 
   170 RAZOR_EXPORT struct razor_property_iterator *
   171 razor_property_iterator_create(struct razor_set *set,
   172 			       struct razor_package *package)
   173 {
   174 	struct razor_property_iterator *pi;
   175 
   176 	assert (set != NULL);
   177 
   178 	pi = zalloc(sizeof *pi);
   179 	pi->set = set;
   180 
   181 	if (package) {
   182 		pi->index = list_first(&package->properties,
   183 				       &set->property_pool);
   184 	} else {
   185 		pi->property = set->properties.data;
   186 		pi->end = set->properties.data + set->properties.size;
   187 	}
   188 
   189 	return pi;
   190 }
   191 
   192 RAZOR_EXPORT int
   193 razor_property_iterator_next(struct razor_property_iterator *pi,
   194 			     struct razor_property **property,
   195 			     const char **name,
   196 			     uint32_t *flags,
   197 			     const char **version)
   198 {
   199 	char *pool;
   200 	int valid;
   201 	struct razor_property *p, *properties;
   202 
   203 	assert (pi != NULL);
   204 
   205 	if (pi->property) {
   206 		p = pi->property++;
   207 		valid = p < pi->end;
   208 	} else if (pi->index) {
   209 		properties = pi->set->properties.data;
   210 		p = &properties[pi->index->data];
   211 		pi->index = list_next(pi->index);
   212 		valid = 1;
   213 	} else
   214 		valid = 0;
   215 
   216 	if (valid) {
   217 		pool = pi->set->string_pool.data;
   218 		*property = p;
   219 		*name = &pool[p->name];
   220 		*flags = p->flags;
   221 		*version = &pool[p->version];
   222 	} else {
   223 		*property = NULL;
   224 	}
   225 
   226 	return valid;
   227 }
   228 
   229 RAZOR_EXPORT void
   230 razor_property_iterator_destroy(struct razor_property_iterator *pi)
   231 {
   232 	free(pi);
   233 }
   234 
   235 RAZOR_EXPORT struct razor_file_iterator *
   236 razor_file_iterator_create(struct razor_set *set, struct razor_package *package,
   237 			   int post_order)
   238 {
   239 	struct razor_file_iterator *fi;
   240 
   241 	assert (set != NULL);
   242 	assert (package != NULL);
   243 
   244 	fi = zalloc(sizeof *fi);
   245 	fi->set = set;
   246 	fi->post_order = post_order;
   247 	if (post_order)
   248 		fi->index = list_last(&package->files, &set->file_pool);
   249 	else
   250 		fi->index = list_first(&package->files, &set->file_pool);
   251 	array_init(&fi->path);
   252 
   253 	return fi;
   254 }
   255 
   256 RAZOR_EXPORT int
   257 razor_file_iterator_next(struct razor_file_iterator *fi,
   258 			 const char **name)
   259 {
   260 	struct razor_entry *e, *dir, *entries;
   261 	char *pool, *s, *f;
   262 
   263 	assert (fi != NULL);
   264 
   265 	if (!fi->index) {
   266 		*name = NULL;
   267 		return 0;
   268 	}
   269 
   270 	entries = (struct razor_entry *) fi->set->files.data;
   271 	pool = fi->set->file_string_pool.data;
   272 
   273 	dir = entries;
   274 	fi->path.size = 0;
   275 	for(;;) {
   276 		e = dir;
   277 		do {
   278 			if (entries + fi->index->data == e) {
   279 				f = pool + e->name;
   280 				s = array_add(&fi->path, strlen(f) + 1);
   281 				strcpy(s, f);
   282 				if (fi->path.size == 1) {
   283 					array_add(&fi->path, 1);
   284 					strcpy(fi->path.data, "/");
   285 				}
   286 				*name = fi->path.data;
   287 				if (fi->post_order)
   288 					fi->index = list_prev(fi->index);
   289 				else
   290 					fi->index = list_next(fi->index);
   291 				return 1;
   292 			}
   293 		} while (!((e++)->flags & RAZOR_ENTRY_LAST));
   294 		for(e--; e >= dir; e--)
   295 			if (e->start && fi->index->data >= e->start)
   296 				break;
   297 		if (e < dir)
   298 			break;
   299 		f = pool + e->name;
   300 		s = array_add(&fi->path, strlen(f) + 1);
   301 		strcpy(s, f);
   302 		s += strlen(f);
   303 		*s = '/';
   304 		dir = entries + e->start;
   305 	}
   306 
   307 	printf("file_iterator_next: Failed to find file %d\n",fi->index->data);
   308 	*name = NULL;
   309 	return 0;
   310 }
   311 
   312 RAZOR_EXPORT void razor_file_iterator_destroy(struct razor_file_iterator *fi)
   313 {
   314 	assert (fi != NULL);
   315 
   316 	array_release(&fi->path);
   317 	free(fi);
   318 }
   319 
   320 RAZOR_EXPORT struct razor_string_iterator *
   321 razor_install_prefix_iterator_create(struct razor_set *set,
   322 				     struct razor_package *package)
   323 {
   324 	struct razor_string_iterator *si;
   325 
   326 	assert (set != NULL);
   327 	assert (package != NULL);
   328 
   329 	si = zalloc(sizeof *si);
   330 	si->set = set;
   331 
   332 	si->index = list_first(&package->install_prefixes,
   333 			       &set->prefix_pool);
   334 
   335 	return si;
   336 }
   337 
   338 RAZOR_EXPORT int
   339 razor_string_iterator_next(struct razor_string_iterator *si,
   340 			   const char **string)
   341 {
   342 	char *pool;
   343 	int valid;
   344 
   345 	assert (si != NULL);
   346 
   347 	if (si->index) {
   348 		pool = si->set->string_pool.data;
   349 		*string = &pool[si->index->data];
   350 		si->index = list_next(si->index);
   351 		valid = 1;
   352 	} else {
   353 		*string = NULL;
   354 		valid = 0;
   355 	}
   356 
   357 	return valid;
   358 }
   359 
   360 RAZOR_EXPORT void
   361 razor_string_iterator_destroy(struct razor_string_iterator *si)
   362 {
   363 	free(si);
   364 }
   365 
   366 struct razor_package_query {
   367 	struct razor_set *set;
   368 	char *vector;
   369 	int count;
   370 };
   371 
   372 RAZOR_EXPORT struct razor_package_query *
   373 razor_package_query_create(struct razor_set *set)
   374 {
   375 	struct razor_package_query *pq;
   376 	int count;
   377 
   378 	assert (set != NULL);
   379 
   380 	pq = zalloc(sizeof *pq);
   381 	pq->set = set;
   382 	count = set->packages.size / sizeof(struct razor_package);
   383 	pq->vector = zalloc(count * sizeof(char));
   384 
   385 	return pq;
   386 }
   387 
   388 RAZOR_EXPORT void
   389 razor_package_query_add_package(struct razor_package_query *pq,
   390 				struct razor_package *p)
   391 {
   392 	struct razor_package *packages;
   393 
   394 	assert (pq != NULL);
   395 	assert (p != NULL);
   396 
   397 	packages = pq->set->packages.data;
   398 	pq->count += pq->vector[p - packages] ^ 1;
   399 	pq->vector[p - packages] = 1;
   400 }
   401 
   402 RAZOR_EXPORT void
   403 razor_package_query_add_iterator(struct razor_package_query *pq,
   404 				 struct razor_package_iterator *pi)
   405 {
   406 	struct razor_package *packages, *p;
   407 
   408 	assert (pq != NULL);
   409 	assert (pi != NULL);
   410 
   411 	packages = pq->set->packages.data;
   412 	while (razor_package_iterator_next(pi, &p, RAZOR_DETAIL_LAST)) {
   413 		pq->count += pq->vector[p - packages] ^ 1;
   414 		pq->vector[p - packages] = 1;
   415 	}
   416 }
   417 
   418 RAZOR_EXPORT struct razor_package_iterator *
   419 razor_package_query_finish(struct razor_package_query *pq)
   420 {
   421 	struct razor_package_iterator *pi;
   422 	struct razor_set *set;
   423 	struct list *index;
   424 	int i, j;
   425 
   426 	assert (pq != NULL);
   427 
   428 	set = pq->set;
   429 	if (pq->count > 0)
   430 		index = zalloc(pq->count * sizeof *index);
   431 	else
   432 		index = NULL;
   433 
   434 	for (i = 0, j = 0; j < pq->count; i++) {
   435 		if (!pq->vector[i])
   436 			continue;
   437 
   438 		index[j].data = i;
   439 		if (j == pq->count - 1)
   440 			index[j].flags = 0x80;
   441 		j++;
   442 	}
   443 
   444 	free(pq->vector);
   445 	free(pq);
   446 
   447 	pi = razor_package_iterator_create_with_index(set, index);
   448 	pi->alloced_index = index;
   449 
   450 	return pi;
   451 }