razor.c
changeset 48 458b03594baf
parent 46 8de578466ece
child 49 c66fd9a1eabe
     1.1 --- a/razor.c	Sun Oct 07 14:25:06 2007 -0400
     1.2 +++ b/razor.c	Sun Oct 21 21:57:22 2007 -0400
     1.3 @@ -41,6 +41,7 @@
     1.4  #define RAZOR_PACKAGE_POOL 4
     1.5  #define RAZOR_REQUIRES_POOL 5
     1.6  #define RAZOR_PROVIDES_POOL 6
     1.7 +#define RAZOR_FILE_TREE 7
     1.8  
     1.9  struct razor_package {
    1.10  	unsigned long name;
    1.11 @@ -55,6 +56,12 @@
    1.12  	unsigned long packages;
    1.13  };
    1.14  
    1.15 +struct razor_entry {
    1.16 +	unsigned long name;
    1.17 +	unsigned long count;
    1.18 +	unsigned long start;
    1.19 +};
    1.20 +
    1.21  struct razor_set {
    1.22  	struct array string_pool;
    1.23   	struct array packages;
    1.24 @@ -63,6 +70,7 @@
    1.25   	struct array provides;
    1.26   	struct array requires_pool;
    1.27   	struct array provides_pool;
    1.28 + 	struct array file_tree;
    1.29  	struct razor_set_header *header;
    1.30  };
    1.31  
    1.32 @@ -77,6 +85,7 @@
    1.33  	struct import_property_context requires;
    1.34  	struct import_property_context provides;
    1.35  	struct razor_package *package;
    1.36 +	struct array files;
    1.37  };
    1.38  
    1.39  static void
    1.40 @@ -154,6 +163,7 @@
    1.41  	{ RAZOR_PACKAGE_POOL,	offsetof(struct razor_set, package_pool) },
    1.42  	{ RAZOR_REQUIRES_POOL,	offsetof(struct razor_set, requires_pool) },
    1.43  	{ RAZOR_PROVIDES_POOL,	offsetof(struct razor_set, provides_pool) },
    1.44 +	{ RAZOR_FILE_TREE,	offsetof(struct razor_set, file_tree) },
    1.45  };
    1.46  
    1.47  struct razor_set *
    1.48 @@ -453,6 +463,10 @@
    1.49  void
    1.50  razor_importer_add_file(struct razor_importer *importer, const char *name)
    1.51  {
    1.52 +	char **p;
    1.53 +
    1.54 +	p = array_add(&importer->files, sizeof *p);
    1.55 +	*p = strdup(name);
    1.56  }
    1.57  
    1.58  struct razor_importer *
    1.59 @@ -682,6 +696,147 @@
    1.60  			*p = map[*p];
    1.61  }
    1.62  
    1.63 +static int
    1.64 +compare_filenames(const void *p1, const void *p2, void *data)
    1.65 +{
    1.66 +	char *f1 = *(char **) p1;
    1.67 +	char *f2 = *(char **) p2;
    1.68 +
    1.69 +	return strcmp(f1, f2);
    1.70 +}
    1.71 +
    1.72 +struct directory {
    1.73 +	unsigned long name, count;
    1.74 +	struct array files;
    1.75 +	struct directory *last;
    1.76 +};
    1.77 +
    1.78 +static void
    1.79 +count_entries(struct directory *d)
    1.80 +{
    1.81 +	struct directory *p, *end;
    1.82 +
    1.83 +	p = d->files.data;
    1.84 +	end = d->files.data + d->files.size;
    1.85 +	d->count = 0;
    1.86 +	while (p < end) {
    1.87 +		count_entries(p);
    1.88 +		d->count += p->count + 1;
    1.89 +		p++;
    1.90 +	}		
    1.91 +}
    1.92 +
    1.93 +static void
    1.94 +serialize_files(struct directory *d, struct array *array)
    1.95 +{
    1.96 +	struct directory *p, *end;
    1.97 +	struct razor_entry *e;
    1.98 +	unsigned long s;
    1.99 +
   1.100 +	p = d->files.data;
   1.101 +	end = d->files.data + d->files.size;
   1.102 +	s = array->size / sizeof *e + d->files.size / sizeof *p;
   1.103 +	while (p < end) {
   1.104 +		e = array_add(array, sizeof *e);
   1.105 +		e->name = p->name;
   1.106 +		e->count = p->files.size / sizeof *p;
   1.107 +		e->start = s;
   1.108 +		s += p->count;
   1.109 +		p++;
   1.110 +	}		
   1.111 +
   1.112 +	p = d->files.data;
   1.113 +	end = d->files.data + d->files.size;
   1.114 +	while (p < end) {
   1.115 +		serialize_files(p, array);
   1.116 +		p++;
   1.117 +	}
   1.118 +}
   1.119 +
   1.120 +static void
   1.121 +build_file_tree(struct razor_importer *importer)
   1.122 +{
   1.123 +	int count, i, length;
   1.124 +	char **filenames, *f, *end;
   1.125 +	unsigned long name;
   1.126 +	char dirname[256];
   1.127 +	struct directory *d, root;
   1.128 +	struct razor_entry *e;
   1.129 +
   1.130 +	count = importer->files.size / sizeof (char *);
   1.131 +	qsort_with_data(importer->files.data,
   1.132 +			count,
   1.133 +			sizeof (char *),
   1.134 +			compare_filenames,
   1.135 +			NULL);
   1.136 +
   1.137 +	root.name = razor_importer_tokenize(importer, "");
   1.138 +	array_init(&root.files);
   1.139 +	root.last = NULL;
   1.140 +
   1.141 +	filenames = importer->files.data;
   1.142 +	for (i = 0; i < count; i++) {
   1.143 +		f = filenames[i];
   1.144 +		if (*f != '/')
   1.145 +			continue;
   1.146 +
   1.147 +		d = &root;
   1.148 +		while (*f) {
   1.149 +			end = strchr(f + 1, '/');
   1.150 +			if (end == NULL)
   1.151 +				end = f + strlen(f);
   1.152 +			length = end - (f + 1);
   1.153 +			memcpy(dirname, f + 1, length);
   1.154 +			dirname[length] ='\0';
   1.155 +			name = razor_importer_tokenize(importer, dirname);
   1.156 +			if (d->last == NULL || d->last->name != name) {
   1.157 +				d->last = array_add(&d->files, sizeof *d);
   1.158 +				d->last->name = name;
   1.159 +				d->last->last = NULL;
   1.160 +				array_init(&d->last->files);
   1.161 +			}
   1.162 +			d = d->last;				
   1.163 +			f = end;
   1.164 +		}
   1.165 +
   1.166 +		free(filenames[i]);
   1.167 +	}
   1.168 +
   1.169 +	count_entries(&root);
   1.170 +	array_init(&importer->set->file_tree);
   1.171 +
   1.172 +	e = array_add(&importer->set->file_tree, sizeof *e);
   1.173 +	e->name = root.name;
   1.174 +	e->count = root.files.size / sizeof *d;
   1.175 +	e->start = 1;
   1.176 +
   1.177 +	serialize_files(&root, &importer->set->file_tree);
   1.178 +
   1.179 +	array_release(&importer->files);
   1.180 +}
   1.181 +
   1.182 +static void
   1.183 +list_dir(struct razor_set *set, struct razor_entry *e, int indent)
   1.184 +{
   1.185 +	struct razor_entry *c;
   1.186 +	char *pool = set->string_pool.data;
   1.187 +	int i;
   1.188 +
   1.189 +	for (i = 0; i < indent; i++)
   1.190 +		putchar(' ');
   1.191 +	printf("%s\n", pool + e->name);
   1.192 +	for (i = 0; i < e->count; i++) {
   1.193 +		c = (struct razor_entry *) set->file_tree.data + e->start + i;
   1.194 +		list_dir(set, c, indent + 2);
   1.195 +	}
   1.196 +}
   1.197 +
   1.198 +void
   1.199 +razor_set_list_files(struct razor_set *set)
   1.200 +{
   1.201 +	list_dir(set, set->file_tree.data, 2);
   1.202 +}
   1.203 +
   1.204  struct razor_set *
   1.205  razor_importer_finish(struct razor_importer *importer)
   1.206  {
   1.207 @@ -712,6 +867,8 @@
   1.208  	free(map);
   1.209  	free(rmap);
   1.210  
   1.211 +	build_file_tree(importer);
   1.212 +
   1.213  	set = importer->set;
   1.214  	array_release(&importer->buckets);
   1.215  	free(importer);