comparison 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
comparison
equal deleted inserted replaced
2:5cd0debdb7d8 3:1cc98a5677d9
36 #include <unistd.h> 36 #include <unistd.h>
37 37
38 #include "pwfile.h" 38 #include "pwfile.h"
39 #include "util.h" 39 #include "util.h"
40 40
41 #define MIN_ARRAY_SIZE 1024
42
43 struct record_id_entry { 41 struct record_id_entry {
44 RB_ENTRY(record_id_entry) record_id_entry; 42 RB_ENTRY(record_id_entry) record_id_entry;
45 unsigned int id; 43 unsigned int id;
46 unsigned char uuid[PWS3_UUID_SIZE]; 44 unsigned char uuid[PWS3_UUID_SIZE];
47 }; 45 };
164 162
165 int 163 int
166 pwfile_read_file(struct pwm_ctx *ctx, FILE *fp) 164 pwfile_read_file(struct pwm_ctx *ctx, FILE *fp)
167 { 165 {
168 struct pws3_record *pws3_record; 166 struct pws3_record *pws3_record;
167 size_t record_list_len = 0;
169 struct pws3_record **pws3_record_list; 168 struct pws3_record **pws3_record_list;
170 size_t record_list_size = MIN_ARRAY_SIZE;
171 size_t record_list_len = 0;
172 size_t i; 169 size_t i;
173 struct pws3_field *uuid_field; 170 struct pws3_field *uuid_field;
174 const unsigned char *uuid; 171 const unsigned char *uuid;
175 struct record_id_entry *entry; 172 struct record_id_entry *entry;
176 173
181 } 178 }
182 179
183 record_id_tree_clear(ctx->record_id_tree); 180 record_id_tree_clear(ctx->record_id_tree);
184 181
185 /* sort records by group and title */ 182 /* sort records by group and title */
183 for (pws3_record = pws3_file_first_record(ctx->file);
184 pws3_record != NULL;
185 pws3_record = pws3_file_next_record(ctx->file, pws3_record)) {
186 record_list_len++;
187 }
186 pws3_record_list = xmalloc(sizeof (struct pws3_record *) * 188 pws3_record_list = xmalloc(sizeof (struct pws3_record *) *
187 record_list_size); 189 record_list_len);
188 for (pws3_record = pws3_file_first_record(ctx->file); 190 for (pws3_record = pws3_file_first_record(ctx->file), i = 0;
189 pws3_record != NULL; pws3_record = pws3_file_next_record(ctx->file, 191 pws3_record != NULL;
190 pws3_record)) { 192 pws3_record = pws3_file_next_record(ctx->file, pws3_record)) {
191 if (record_list_len == record_list_size) { 193 pws3_record_list[i++] = pws3_record;
192 record_list_size *= 2; 194 }
193 pws3_record_list = xrealloc(pws3_record_list, 195 qsort(pws3_record_list, record_list_len,
194 sizeof (struct pws3_record *) * record_list_size); 196 sizeof (struct pws3_record *), pws_record_cmp);
195 }
196 pws3_record_list[record_list_len++] = pws3_record;
197 }
198 qsort(pws3_record_list, record_list_len, sizeof (struct pws3_record *),
199 pws_record_cmp);
200 197
201 /* build the tree of record IDs */ 198 /* build the tree of record IDs */
202 for (i = 0; i < record_list_len; i++) { 199 for (i = 0; i < record_list_len; i++) {
203 uuid_field = pws3_record_get_field(pws3_record_list[i], 200 uuid_field = pws3_record_get_field(pws3_record_list[i],
204 PWS3_RECORD_FIELD_UUID); 201 PWS3_RECORD_FIELD_UUID);
407 404
408 union list_item ** 405 union list_item **
409 pwfile_create_list(struct pwm_ctx *ctx) 406 pwfile_create_list(struct pwm_ctx *ctx)
410 { 407 {
411 union list_item **list; 408 union list_item **list;
412 size_t list_size = MIN_ARRAY_SIZE;
413 size_t list_len = 0;
414 struct record_id_entry *entry; 409 struct record_id_entry *entry;
415 union list_item *item; 410 size_t list_capacity = 0;
411 struct pws3_field *empty_group_field;
416 struct pws3_record *pws3_record; 412 struct pws3_record *pws3_record;
417 struct pws3_field *group_field; 413 struct pws3_field *group_field;
418 const char *group; 414 const char *group;
419 struct pws3_field *title_field; 415 struct pws3_field *title_field;
420 const char *title; 416 const char *title;
417 union list_item *item;
418 size_t list_len = 0;
421 size_t i; 419 size_t i;
422 size_t records_len; 420 size_t j;
423 const char *prev_group = ""; 421 const char *prev_group = NULL;
424 struct pws3_field *empty_group_field; 422
425
426 list = xmalloc(sizeof (union list_item *) * list_size);
427 list[0] = NULL;
428
429 /* build list of records and sort it by group and title */
430 RB_FOREACH(entry, record_id_tree, ctx->record_id_tree) { 423 RB_FOREACH(entry, record_id_tree, ctx->record_id_tree) {
431 if (list_len == list_size - 1) { 424 list_capacity++;
432 list_size *= 2; 425 }
433 list = xrealloc(list, sizeof (union list_item *) * 426 list_capacity *= 2; /* maximum number of group items */
434 list_size); 427 for (empty_group_field = pws3_file_first_empty_group(ctx->file);
435 } 428 empty_group_field != NULL;
436 429 empty_group_field = pws3_file_next_empty_group(ctx->file,
430 empty_group_field)) {
431 list_capacity++;
432 }
433 list_capacity++; /* terminating NULL */
434 list = xmalloc(sizeof (union list_item *) * list_capacity);
435
436 RB_FOREACH(entry, record_id_tree, ctx->record_id_tree) {
437 pws3_record = pws3_file_get_record(ctx->file, entry->uuid); 437 pws3_record = pws3_file_get_record(ctx->file, entry->uuid);
438 group_field = pws3_record_get_field(pws3_record, 438 group_field = pws3_record_get_field(pws3_record,
439 PWS3_RECORD_FIELD_GROUP); 439 PWS3_RECORD_FIELD_GROUP);
440 group = (group_field != NULL) ? 440 group = (group_field != NULL) ?
441 pws3_field_get_text(group_field) : NULL; 441 pws3_field_get_text(group_field) : NULL;
451 item->record.id = entry->id; 451 item->record.id = entry->id;
452 memcpy(item->record.uuid, entry->uuid, 452 memcpy(item->record.uuid, entry->uuid,
453 sizeof (item->record.uuid)); 453 sizeof (item->record.uuid));
454 454
455 list[list_len++] = item; 455 list[list_len++] = item;
456 list[list_len] = NULL; 456 }
457 } 457 /* sort records by group and title in order to find unqiue groups */
458 qsort(list, list_len, sizeof (union list_item *), list_item_cmp); 458 qsort(list, list_len, sizeof (union list_item *), list_item_cmp);
459 459
460 /* build list of groups by comparing the groups of the sorted records */ 460 /* add groups based on the sorted records */
461 for (i = 0, records_len = list_len; i < records_len; i++) { 461 for (i = 0, j = list_len; i < list_len; i++) {
462 if (list_len == list_size - 1) { 462 group = list[i]->record.group;
463 list_size *= 1.5; 463 if ((group != NULL) && ((prev_group == NULL) ||
464 list = xrealloc(list, sizeof (union list_item *) * 464 (strcmp(prev_group, group) != 0))) {
465 list_size);
466 }
467
468 group = (list[i]->record.group != NULL) ?
469 list[i]->record.group : "";
470 if (strcmp(prev_group, group) != 0) {
471 item = xmalloc(sizeof (union list_item)); 465 item = xmalloc(sizeof (union list_item));
472 item->record.type = ITEM_TYPE_GROUP; 466 item->group.type = ITEM_TYPE_GROUP;
473 item->record.group = (group != NULL) ? xstrdup(group) : 467 item->group.group = (group != NULL) ? xstrdup(group) :
474 NULL; 468 NULL;
475 469 list[j++] = item;
476 list[list_len++] = item;
477 list[list_len] = NULL;
478
479 prev_group = group; 470 prev_group = group;
480 } 471 }
481 } 472 }
473 list_len = j;
482 474
483 /* add empty groups to the list */ 475 /* add empty groups to the list */
484 for (empty_group_field = pws3_file_first_empty_group(ctx->file); 476 for (empty_group_field = pws3_file_first_empty_group(ctx->file);
485 empty_group_field != NULL; 477 empty_group_field != NULL;
486 empty_group_field = pws3_file_next_empty_group(ctx->file, 478 empty_group_field = pws3_file_next_empty_group(ctx->file,
487 empty_group_field)) { 479 empty_group_field)) {
488 if (list_len == list_size - 1) {
489 list_size *= 1.5;
490 list = xrealloc(list, sizeof (union list_item *) *
491 list_size);
492 }
493
494 group = pws3_field_get_text(empty_group_field); 480 group = pws3_field_get_text(empty_group_field);
495 481
496 item = xmalloc(sizeof (union list_item)); 482 item = xmalloc(sizeof (union list_item));
497 item->record.type = ITEM_TYPE_GROUP; 483 item->group.type = ITEM_TYPE_GROUP;
498 item->record.group = xstrdup(group); 484 item->group.group = xstrdup(group);
499 485
500 list[list_len++] = item; 486 list[list_len++] = item;
501 list[list_len] = NULL; 487 }
502 } 488
503 489 /* terminate the list */
504 list_size = list_len + 2; 490 list[list_len] = NULL;
505 list = xrealloc(list, sizeof (union list_item *) * list_size); 491 list = xrealloc(list, sizeof (union list_item *) * (list_len + 1));
492
506 /* sort the final list by group and title */ 493 /* sort the final list by group and title */
507 qsort(list, list_len, sizeof (union list_item *), list_item_cmp); 494 qsort(list, list_len, sizeof (union list_item *), list_item_cmp);
508 495
509 return (list); 496 return (list);
510 } 497 }