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