diff pwfile.c @ 3:1cc98a5677d9

Refactor the creation of the record and group list Simplify the list allocation.
author Guido Berhoerster <guido+pwm@berhoerster.name>
date Sat, 04 Feb 2017 22:06:15 +0100
parents 5cd0debdb7d8
children b5c4267a7182
line wrap: on
line diff
--- a/pwfile.c	Sat Feb 04 21:04:47 2017 +0100
+++ b/pwfile.c	Sat Feb 04 22:06:15 2017 +0100
@@ -38,8 +38,6 @@
 #include "pwfile.h"
 #include "util.h"
 
-#define	MIN_ARRAY_SIZE	1024
-
 struct record_id_entry {
 	RB_ENTRY(record_id_entry) record_id_entry;
 	unsigned int	id;
@@ -166,9 +164,8 @@
 pwfile_read_file(struct pwm_ctx *ctx, FILE *fp)
 {
 	struct pws3_record *pws3_record;
+	size_t		record_list_len = 0;
 	struct pws3_record **pws3_record_list;
-	size_t		record_list_size = MIN_ARRAY_SIZE;
-	size_t		record_list_len = 0;
 	size_t		i;
 	struct pws3_field *uuid_field;
 	const unsigned char *uuid;
@@ -183,20 +180,20 @@
 	record_id_tree_clear(ctx->record_id_tree);
 
 	/* sort records by group and title */
+	for (pws3_record = pws3_file_first_record(ctx->file);
+	    pws3_record != NULL;
+	    pws3_record = pws3_file_next_record(ctx->file, pws3_record)) {
+		record_list_len++;
+	}
 	pws3_record_list = xmalloc(sizeof (struct pws3_record *) *
-	    record_list_size);
-	for (pws3_record = pws3_file_first_record(ctx->file);
-	    pws3_record != NULL; pws3_record = pws3_file_next_record(ctx->file,
-	    pws3_record)) {
-		if (record_list_len == record_list_size) {
-			record_list_size *= 2;
-			pws3_record_list = xrealloc(pws3_record_list,
-			    sizeof (struct pws3_record *) * record_list_size);
-		}
-		pws3_record_list[record_list_len++] = pws3_record;
+	    record_list_len);
+	for (pws3_record = pws3_file_first_record(ctx->file), i = 0;
+	    pws3_record != NULL;
+	    pws3_record = pws3_file_next_record(ctx->file, pws3_record)) {
+		pws3_record_list[i++] = pws3_record;
 	}
-	qsort(pws3_record_list, record_list_len, sizeof (struct pws3_record *),
-	    pws_record_cmp);
+	qsort(pws3_record_list, record_list_len,
+	    sizeof (struct pws3_record *), pws_record_cmp);
 
 	/* build the tree of record IDs */
 	for (i = 0; i < record_list_len; i++) {
@@ -409,31 +406,34 @@
 pwfile_create_list(struct pwm_ctx *ctx)
 {
 	union list_item	**list;
-	size_t		list_size = MIN_ARRAY_SIZE;
-	size_t		list_len = 0;
 	struct record_id_entry *entry;
-	union list_item	*item;
+	size_t		list_capacity = 0;
+	struct pws3_field *empty_group_field;
 	struct pws3_record *pws3_record;
 	struct pws3_field *group_field;
 	const char	*group;
 	struct pws3_field *title_field;
 	const char	*title;
+	union list_item	*item;
+	size_t		list_len = 0;
 	size_t		i;
-	size_t		records_len;
-	const char	*prev_group = "";
-	struct pws3_field *empty_group_field;
-
-	list = xmalloc(sizeof (union list_item *) * list_size);
-	list[0] = NULL;
+	size_t		j;
+	const char	*prev_group = NULL;
 
-	/* build list of records and sort it by group and title */
 	RB_FOREACH(entry, record_id_tree, ctx->record_id_tree) {
-		if (list_len == list_size - 1) {
-			list_size *= 2;
-			list = xrealloc(list, sizeof (union list_item *) *
-			    list_size);
-		}
+		list_capacity++;
+	}
+	list_capacity *= 2; /* maximum number of group items */
+	for (empty_group_field = pws3_file_first_empty_group(ctx->file);
+	    empty_group_field != NULL;
+	    empty_group_field = pws3_file_next_empty_group(ctx->file,
+	    empty_group_field)) {
+		list_capacity++;
+	}
+	list_capacity++; /* terminating NULL */
+	list = xmalloc(sizeof (union list_item *) * list_capacity);
 
+	RB_FOREACH(entry, record_id_tree, ctx->record_id_tree) {
 		pws3_record = pws3_file_get_record(ctx->file, entry->uuid);
 		group_field = pws3_record_get_field(pws3_record,
 		    PWS3_RECORD_FIELD_GROUP);
@@ -453,56 +453,43 @@
 		    sizeof (item->record.uuid));
 
 		list[list_len++] = item;
-		list[list_len] = NULL;
 	}
+	/* sort records by group and title in order to find unqiue groups */
 	qsort(list, list_len, sizeof (union list_item *), list_item_cmp);
 
-	/* build list of groups by comparing the groups of the sorted records */
-	for (i = 0, records_len = list_len; i < records_len; i++) {
-		if (list_len == list_size - 1) {
-			list_size *= 1.5;
-			list = xrealloc(list, sizeof (union list_item *) *
-			    list_size);
-		}
-
-		group = (list[i]->record.group != NULL) ?
-		    list[i]->record.group : "";
-		if (strcmp(prev_group, group) != 0) {
+	/* add groups based on the sorted records */
+	for (i = 0, j = list_len; i < list_len; i++) {
+		group = list[i]->record.group;
+		if ((group != NULL) && ((prev_group == NULL) ||
+		    (strcmp(prev_group, group) != 0))) {
 			item = xmalloc(sizeof (union list_item));
-			item->record.type = ITEM_TYPE_GROUP;
-			item->record.group = (group != NULL) ? xstrdup(group) :
+			item->group.type = ITEM_TYPE_GROUP;
+			item->group.group = (group != NULL) ? xstrdup(group) :
 			    NULL;
-
-			list[list_len++] = item;
-			list[list_len] = NULL;
-
+			list[j++] = item;
 			prev_group = group;
 		}
 	}
+	list_len = j;
 
 	/* add empty groups to the list */
 	for (empty_group_field = pws3_file_first_empty_group(ctx->file);
 	    empty_group_field != NULL;
 	    empty_group_field = pws3_file_next_empty_group(ctx->file,
 	    empty_group_field)) {
-		if (list_len == list_size - 1) {
-			list_size *= 1.5;
-			list = xrealloc(list, sizeof (union list_item *) *
-			    list_size);
-		}
-
 		group = pws3_field_get_text(empty_group_field);
 
 		item = xmalloc(sizeof (union list_item));
-		item->record.type = ITEM_TYPE_GROUP;
-		item->record.group = xstrdup(group);
+		item->group.type = ITEM_TYPE_GROUP;
+		item->group.group = xstrdup(group);
 
 		list[list_len++] = item;
-		list[list_len] = NULL;
 	}
 
-	list_size = list_len + 2;
-	list = xrealloc(list, sizeof (union list_item *) * list_size);
+	/* terminate the list */
+	list[list_len] = NULL;
+	list = xrealloc(list, sizeof (union list_item *) * (list_len + 1));
+
 	/* sort the final list by group and title */
 	qsort(list, list_len, sizeof (union list_item *), list_item_cmp);