librazor/iterator.c
author Kristian H?gsberg <krh@redhat.com>
Fri Jun 20 23:13:09 2008 -0400 (2008-06-20)
changeset 257 0c3db660514d
parent 248 057933050c42
child 267 2464313cbced
permissions -rw-r--r--
When uniquifying properties, also sort them on the owning package.

This ensures that whenever two packages provide or (or require, obsolete
or conflict) the same property, they appear in the same order in the
propertys list of packages.
     1 /*
     2  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     3  * Copyright (C) 2008  Red Hat, Inc
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation; either version 2 of the License, or
     8  * (at your option) any later version.
     9  *
    10  * This program is distributed in the hope that it will be useful,
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  * GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along
    16  * with this program; if not, write to the Free Software Foundation, Inc.,
    17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    18  */
    19 
    20 #define _GNU_SOURCE
    21 
    22 #include <string.h>
    23 #include "razor-internal.h"
    24 #include "razor.h"
    25 
    26 static struct razor_package_iterator *
    27 razor_package_iterator_create_with_index(struct razor_set *set,
    28 					 struct list *index)
    29 {
    30 	struct razor_package_iterator *pi;
    31 
    32 	pi = zalloc(sizeof *pi);
    33 	pi->set = set;
    34 	pi->index = index;
    35 
    36 	return pi;
    37 }
    38 
    39 struct razor_package_iterator *
    40 razor_package_iterator_create(struct razor_set *set)
    41 {
    42 	struct razor_package_iterator *pi;
    43 
    44 	pi = zalloc(sizeof *pi);
    45 	pi->set = set;
    46 	pi->end = set->packages.data + set->packages.size;
    47 	pi->package = set->packages.data;
    48 
    49 	return pi;
    50 }
    51 
    52 void
    53 razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
    54 					 struct razor_set *set,
    55 					 struct razor_property *property)
    56 {
    57 	memset(pi, 0, sizeof *pi);
    58 	pi->set = set;
    59 	pi->index = list_first(&property->packages, &set->package_pool);
    60 }
    61 
    62 struct razor_package_iterator *
    63 razor_package_iterator_create_for_property(struct razor_set *set,
    64 					   struct razor_property *property)
    65 {
    66 	struct list *index;
    67 
    68 	index = list_first(&property->packages, &set->package_pool);
    69 	return razor_package_iterator_create_with_index(set, index);
    70 }
    71 
    72 struct razor_package_iterator *
    73 razor_package_iterator_create_for_file(struct razor_set *set,
    74 				       const char *filename)
    75 {
    76 	struct razor_entry *entry;
    77 	struct list *index;
    78 
    79 	entry = razor_set_find_entry(set, set->files.data, filename);
    80 	if (entry == NULL)
    81 		return NULL;
    82 
    83 	index = list_first(&entry->packages, &set->package_pool);
    84 	return razor_package_iterator_create_with_index(set, index);
    85 }
    86 
    87 int
    88 razor_package_iterator_next(struct razor_package_iterator *pi,
    89 			    struct razor_package **package,
    90 			    const char **name,
    91 			    const char **version,
    92 			    const char **arch)
    93 {
    94 	char *pool;
    95 	int valid;
    96 	struct razor_package *p, *packages;
    97 
    98 	if (pi->package) {
    99 		p = pi->package++;
   100 		valid = p < pi->end;
   101 	} else if (pi->index) {
   102 		packages = pi->set->packages.data;
   103 		p = &packages[pi->index->data];
   104 		pi->index = list_next(pi->index);
   105 		valid = 1;
   106 	} else
   107 		valid = 0;
   108 
   109 	if (valid) {
   110 		pool = pi->set->string_pool.data;
   111 		*package = p;
   112 		*name = &pool[p->name];
   113 		*version = &pool[p->version];
   114 		*arch = &pool[p->arch];
   115 	} else {
   116 		*package = NULL;
   117 	}
   118 
   119 	return valid;
   120 }
   121 
   122 void
   123 razor_package_iterator_destroy(struct razor_package_iterator *pi)
   124 {
   125 	if (pi->free_index)
   126 		free(pi->index);
   127 
   128 	free(pi);
   129 }
   130 
   131 struct razor_property_iterator *
   132 razor_property_iterator_create(struct razor_set *set,
   133 			       struct razor_package *package)
   134 {
   135 	struct razor_property_iterator *pi;
   136 
   137 	pi = zalloc(sizeof *pi);
   138 	pi->set = set;
   139 
   140 	if (package) {
   141 		pi->index = list_first(&package->properties,
   142 				       &set->property_pool);
   143 	} else {
   144 		pi->property = set->properties.data;
   145 		pi->end = set->properties.data + set->properties.size;
   146 	}
   147 
   148 	return pi;
   149 }
   150 
   151 int
   152 razor_property_iterator_next(struct razor_property_iterator *pi,
   153 			     struct razor_property **property,
   154 			     const char **name,
   155 			     uint32_t *flags,
   156 			     const char **version)
   157 {
   158 	char *pool;
   159 	int valid;
   160 	struct razor_property *p, *properties;
   161 
   162 	if (pi->property) {
   163 		p = pi->property++;
   164 		valid = p < pi->end;
   165 	} else if (pi->index) {
   166 		properties = pi->set->properties.data;
   167 		p = &properties[pi->index->data];
   168 		pi->index = list_next(pi->index);
   169 		valid = 1;
   170 	} else
   171 		valid = 0;
   172 
   173 	if (valid) {
   174 		pool = pi->set->string_pool.data;
   175 		*property = p;
   176 		*name = &pool[p->name];
   177 		*flags = p->flags;
   178 		*version = &pool[p->version];
   179 	} else {
   180 		*property = NULL;
   181 	}
   182 
   183 	return valid;
   184 }
   185 
   186 void
   187 razor_property_iterator_destroy(struct razor_property_iterator *pi)
   188 {
   189 	free(pi);
   190 }
   191 
   192 struct razor_package_query {
   193 	struct razor_set *set;
   194 	char *vector;
   195 	int count;
   196 };
   197 
   198 struct razor_package_query *
   199 razor_package_query_create(struct razor_set *set)
   200 {
   201 	struct razor_package_query *pq;
   202 	int count;
   203 
   204 	pq = zalloc(sizeof *pq);
   205 	pq->set = set;
   206 	count = set->packages.size / sizeof(struct razor_package);
   207 	pq->vector = zalloc(count * sizeof(char));
   208 
   209 	return pq;
   210 }
   211 
   212 void
   213 razor_package_query_add_package(struct razor_package_query *pq,
   214 				struct razor_package *p)
   215 {
   216 	struct razor_package *packages;
   217 
   218 	packages = pq->set->packages.data;
   219 	pq->count += pq->vector[p - packages] ^ 1;
   220 	pq->vector[p - packages] = 1;
   221 }
   222 
   223 void
   224 razor_package_query_add_iterator(struct razor_package_query *pq,
   225 				 struct razor_package_iterator *pi)
   226 {
   227 	struct razor_package *packages, *p;
   228 	const char *name, *version, *arch;
   229 
   230 	packages = pq->set->packages.data;
   231 	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
   232 		pq->count += pq->vector[p - packages] ^ 1;
   233 		pq->vector[p - packages] = 1;
   234 	}
   235 }
   236 
   237 struct razor_package_iterator *
   238 razor_package_query_finish(struct razor_package_query *pq)
   239 {
   240 	struct razor_package_iterator *pi;
   241 	struct razor_set *set;
   242 	struct list *index;
   243 	int i, j;
   244 
   245 	set = pq->set;
   246 	if (pq->count > 0)
   247 		index = zalloc(pq->count * sizeof *index);
   248 	else
   249 		index = NULL;
   250 
   251 	for (i = 0, j = 0; i < pq->count; i++) {
   252 		if (!pq->vector[i])
   253 			continue;
   254 
   255 		index[j].data = i;
   256 		if (j == pq->count - 1)
   257 			index[j].flags = 0x80;
   258 		j++;
   259 	}
   260 
   261 	free(pq->vector);
   262 	free(pq);
   263 
   264 	pi = razor_package_iterator_create_with_index(set, index);
   265 	pi->free_index = 1;
   266 
   267 	return pi;
   268 }