Uniqueify requires and provides after import.
1.1 --- a/razor.c Thu Sep 06 15:11:49 2007 -0400
1.2 +++ b/razor.c Thu Sep 06 17:01:01 2007 -0400
1.3 @@ -107,6 +107,7 @@
1.4 struct razor_property {
1.5 unsigned long name;
1.6 unsigned long version;
1.7 + unsigned long packages;
1.8 };
1.9
1.10 struct razor_set {
1.11 @@ -201,6 +202,8 @@
1.12 free(set->buckets.data);
1.13 free(set->string_pool.data);
1.14 free(set->packages.data);
1.15 + free(set->requires.data);
1.16 + free(set->provides.data);
1.17 }
1.18
1.19 free(set);
1.20 @@ -267,7 +270,7 @@
1.21 unsigned int hash = 0;
1.22
1.23 for (p = key; *p; p++)
1.24 - hash = (hash << 2) ^ *p;
1.25 + hash = (hash * 617) ^ *p;
1.26
1.27 return hash;
1.28 }
1.29 @@ -409,48 +412,15 @@
1.30 return razor_set_insert(set, string);
1.31 }
1.32
1.33 -static struct razor_set *qsort_set;
1.34 -
1.35 -static int
1.36 -compare_packages(const void *p1, const void *p2)
1.37 -{
1.38 - const struct razor_package *pkg1 = p1, *pkg2 = p2;
1.39 - char *pool = qsort_set->string_pool.data;
1.40 -
1.41 - return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
1.42 -}
1.43 -
1.44 -static int
1.45 -compare_properties(const void *p1, const void *p2)
1.46 -{
1.47 - const struct razor_property *prop1 = p1, *prop2 = p2;
1.48 - char *pool = qsort_set->string_pool.data;
1.49 -
1.50 - return strcmp(&pool[prop1->name], &pool[prop2->name]);
1.51 -}
1.52 -
1.53 -static void
1.54 -razor_set_sort(struct razor_set *set)
1.55 -{
1.56 - qsort_set = set;
1.57 - qsort(set->packages.data,
1.58 - set->packages.size / sizeof(struct razor_package),
1.59 - sizeof(struct razor_package), compare_packages);
1.60 - qsort(set->requires.data,
1.61 - set->requires.size / sizeof(struct razor_property),
1.62 - sizeof(struct razor_property), compare_properties);
1.63 - qsort(set->provides.data,
1.64 - set->provides.size / sizeof(struct razor_property),
1.65 - sizeof(struct razor_property), compare_properties);
1.66 -}
1.67 -
1.68 -struct parsing_context {
1.69 +struct import_context {
1.70 struct razor_set *set;
1.71 - int pkg_id;
1.72 + struct array requires;
1.73 + struct array provides;
1.74 + unsigned long package;
1.75 };
1.76
1.77 static void
1.78 -parse_package(struct parsing_context *ctx, const char **atts)
1.79 +parse_package(struct import_context *ctx, const char **atts, void *data)
1.80 {
1.81 unsigned long name = 0, version = 0;
1.82 int i;
1.83 @@ -468,75 +438,57 @@
1.84 return;
1.85 }
1.86
1.87 - ctx->pkg_id = razor_set_add_package(ctx->set, name, version);
1.88 + ctx->package = razor_set_add_package(ctx->set, name, version);
1.89
1.90 return;
1.91 }
1.92
1.93 static void
1.94 -parse_requires(struct parsing_context *ctx, const char **atts)
1.95 +parse_property(struct import_context *ctx, const char **atts, void *data)
1.96 {
1.97 unsigned long name = 0, version = 0;
1.98 + struct razor_property *p;
1.99 + struct array *array = data;
1.100 int i;
1.101
1.102 for (i = 0; atts[i]; i += 2) {
1.103 if (strcmp(atts[i], "name") == 0)
1.104 name = razor_set_tokenize(ctx->set, atts[i + 1]);
1.105 + if (strcmp(atts[i], "version") == 0)
1.106 + version = razor_set_tokenize(ctx->set, atts[i + 1]);
1.107 }
1.108
1.109 if (name == 0) {
1.110 - fprintf(stderr, "invalid requires tag, "
1.111 - "missing name attribute\n");
1.112 + fprintf(stderr, "invalid tag, missing name attribute\n");
1.113 return;
1.114 }
1.115
1.116 - ctx->pkg_id = razor_set_add_requires(ctx->set, name, version);
1.117 -}
1.118 -
1.119 -static void
1.120 -parse_provides(struct parsing_context *ctx, const char **atts)
1.121 -{
1.122 - unsigned long name = 0, version = 0;
1.123 - int i;
1.124 -
1.125 - for (i = 0; atts[i]; i += 2) {
1.126 - if (strcmp(atts[i], "name") == 0)
1.127 - name = razor_set_tokenize(ctx->set, atts[i + 1]);
1.128 - }
1.129 -
1.130 - if (name == 0) {
1.131 - fprintf(stderr, "invalid provides tag, "
1.132 - "missing name attribute\n");
1.133 - return;
1.134 - }
1.135 -
1.136 - ctx->pkg_id = razor_set_add_provides(ctx->set, name, version);
1.137 + p = array_add(array, sizeof *p);
1.138 + p->name = name;
1.139 + p->version = version;
1.140 + p->packages = ctx->package;
1.141 }
1.142
1.143 static void
1.144 start_element(void *data, const char *name, const char **atts)
1.145 {
1.146 - struct parsing_context *ctx = data;
1.147 - int i;
1.148 + struct import_context *ctx = data;
1.149
1.150 if (strcmp(name, "package") == 0)
1.151 - parse_package(ctx, atts);
1.152 + parse_package(ctx, atts, NULL);
1.153 else if (strcmp(name, "requires") == 0)
1.154 - parse_requires(ctx, atts);
1.155 + parse_property(ctx, atts, &ctx->requires);
1.156 else if (strcmp(name, "provides") == 0)
1.157 - parse_provides(ctx, atts);
1.158 -
1.159 - for (i = 0; atts[i]; i += 2)
1.160 - razor_set_tokenize(ctx->set, atts[i + 1]);
1.161 + parse_property(ctx, atts, &ctx->provides);
1.162 }
1.163
1.164 static void
1.165 end_element (void *data, const char *name)
1.166 {
1.167 - struct parsing_context *ctx = data;
1.168 + struct import_context *ctx = data;
1.169
1.170 if (strcmp(name, "package") == 0)
1.171 - ctx->pkg_id = 0;
1.172 + ctx->package = 0;
1.173 }
1.174
1.175 static char *
1.176 @@ -558,12 +510,18 @@
1.177 return buffer;
1.178 }
1.179
1.180 +static void
1.181 +razor_set_prepare_import(struct razor_set *set, struct import_context *ctx)
1.182 +{
1.183 + memset(ctx, 0, sizeof *ctx);
1.184 + ctx->set = set;
1.185 +}
1.186 +
1.187 static int
1.188 -razor_set_import(struct razor_set *set, const char *filename)
1.189 +razor_set_import(struct import_context *ctx, const char *filename)
1.190 {
1.191 SHA_CTX sha1;
1.192 XML_Parser parser;
1.193 - struct parsing_context ctx;
1.194 int fd;
1.195 void *p;
1.196 struct stat stat;
1.197 @@ -578,8 +536,7 @@
1.198 return -1;
1.199
1.200 parser = XML_ParserCreate(NULL);
1.201 - ctx.set = set;
1.202 - XML_SetUserData(parser, &ctx);
1.203 + XML_SetUserData(parser, ctx);
1.204 XML_SetElementHandler(parser, start_element, end_element);
1.205 if (XML_Parse(parser, p, stat.st_size, 1) == XML_STATUS_ERROR) {
1.206 fprintf(stderr,
1.207 @@ -606,6 +563,70 @@
1.208 return 0;
1.209 }
1.210
1.211 +static struct razor_set *qsort_set;
1.212 +
1.213 +static int
1.214 +compare_packages(const void *p1, const void *p2)
1.215 +{
1.216 + const struct razor_package *pkg1 = p1, *pkg2 = p2;
1.217 + char *pool = qsort_set->string_pool.data;
1.218 +
1.219 + return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
1.220 +}
1.221 +
1.222 +static int
1.223 +compare_properties(const void *p1, const void *p2)
1.224 +{
1.225 + const struct razor_property *prop1 = p1, *prop2 = p2;
1.226 + char *pool = qsort_set->string_pool.data;
1.227 +
1.228 + return strcmp(&pool[prop1->name], &pool[prop2->name]);
1.229 +}
1.230 +
1.231 +static void
1.232 +uniqueify_properties(struct array *in, struct array *out)
1.233 +{
1.234 + struct razor_property *p, *q, *end;
1.235 +
1.236 + qsort(in->data, in->size / sizeof(struct razor_property),
1.237 + sizeof(struct razor_property), compare_properties);
1.238 +
1.239 + q = NULL;
1.240 + end = in->data + in->size;
1.241 + for (p = in->data; p < end && p->name; p++) {
1.242 + if (q == NULL ||
1.243 + p->name != q->name || p->version != q->version) {
1.244 + q = array_add(out, sizeof *q);
1.245 + q->name = p->name;
1.246 + q->version = p->version;
1.247 +
1.248 + }
1.249 + }
1.250 +}
1.251 +
1.252 +static void
1.253 +razor_set_finish_import(struct import_context *ctx)
1.254 +{
1.255 + qsort_set = ctx->set;
1.256 + qsort(ctx->set->packages.data,
1.257 + ctx->set->packages.size / sizeof(struct razor_package),
1.258 + sizeof(struct razor_package), compare_packages);
1.259 +
1.260 + uniqueify_properties(&ctx->requires, &ctx->set->requires);
1.261 + uniqueify_properties(&ctx->provides, &ctx->set->provides);
1.262 +
1.263 + free(ctx->requires.data);
1.264 + free(ctx->provides.data);
1.265 +
1.266 + fprintf(stderr, "parsed %d requires, %d unique\n",
1.267 + ctx->requires.size / sizeof(struct razor_property),
1.268 + ctx->set->requires.size / sizeof(struct razor_property));
1.269 + fprintf(stderr, "parsed %d provides, %d unique\n",
1.270 + ctx->provides.size / sizeof(struct razor_property),
1.271 + ctx->set->provides.size / sizeof(struct razor_property));
1.272 +}
1.273 +
1.274 +
1.275 void
1.276 razor_set_list(struct razor_set *set)
1.277 {
1.278 @@ -688,6 +709,7 @@
1.279 int i;
1.280 struct razor_set *set;
1.281 struct stat statbuf;
1.282 + struct import_context ctx;
1.283
1.284 if (argc < 2) {
1.285 usage();
1.286 @@ -699,15 +721,17 @@
1.287
1.288 set = razor_set_create();
1.289
1.290 + razor_set_prepare_import(set, &ctx);
1.291 +
1.292 for (i = 2; i < argc; i++) {
1.293 - if (razor_set_import(set, argv[i]) < 0) {
1.294 + if (razor_set_import(&ctx, argv[i]) < 0) {
1.295 fprintf(stderr, "failed to import %s\n",
1.296 argv[i]);
1.297 exit(-1);
1.298 }
1.299 }
1.300
1.301 - razor_set_sort(set);
1.302 + razor_set_finish_import(&ctx);
1.303
1.304 /* FIXME: We add a sentinel package here, but we
1.305 * should probably just have a size field in the