Mercurial > projects > pwm
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 } |