librazor/iterator.c
author J. Ali Harlow <ali@juiblex.co.uk>
Wed Apr 29 17:00:01 2009 +0100 (2009-04-29)
changeset 361 2523d03a840e
parent 308 f4761f529b9e
child 377 5549419824b4
permissions -rw-r--r--
Add support for preloading lua modules. This is useful both when
providing lua bindings to applications based on librazor and when
producing static binaries using librazor (where otherwise the lua
POSIX library would need to be included as an additional dynamic
object).
     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 }