]> git.cworth.org Git - mnemon/blobdiff - mnemon.c
Wait until category is complete before adding items to bins
[mnemon] / mnemon.c
index a1872bcf9632b9b0b00debd2d6cd0c1a5ba490b9..039f0ca0115325a6163018d47f1f1b68e53529a2 100644 (file)
--- a/mnemon.c
+++ b/mnemon.c
@@ -345,33 +345,22 @@ mnemon_get_bin (mnemon_t  *mnemon,
     for (i = 0; i < mnemon->num_bins; i++)
        if (mnemon->bins[i].count == count)
            return &mnemon->bins[i];
+       else if (mnemon->bins[i].count > count)
+           break;
 
     mnemon_bins_grow (mnemon);
 
-    bin = &mnemon->bins[mnemon->num_bins++];
+    bin = &mnemon->bins[i];
+
+    /* Make room to insert new bin at its sorted location. */
+    memmove (bin + 1, bin, (mnemon->num_bins - i) * sizeof (bin_t));
+    mnemon->num_bins++;
 
     bin_init (bin, count);
 
     return bin;
 }
 
-static void
-mnemon_add_item (mnemon_t      *mnemon,
-                category_t     *category,
-                int             count,
-                const char     *challenge,
-                const char     *response)
-{
-    item_t *item;
-    bin_t *bin;
-
-    item = category_add_item (category, count, challenge, response);
-
-    bin = mnemon_get_bin (mnemon, count);
-
-    bin_add_item (bin, item);
-}
-
 static void
 chomp (char *s)
 {
@@ -393,6 +382,7 @@ mnemon_load_category (mnemon_t              *mnemon,
     int line_count = 0;
     char *path;
     category_t *category;
+    int i;
 
     path = xmalloc (strlen (mnemon->dir_name) + 1 + strlen (name) + 1);
     sprintf (path, "%s/%s", mnemon->dir_name, name);
@@ -442,7 +432,7 @@ mnemon_load_category (mnemon_t              *mnemon,
        chomp (line);
        response = line;
 
-       mnemon_add_item (mnemon, category, count, challenge, response);
+       category_add_item (category, count, challenge, response);
 
        free (challenge);
     }
@@ -451,6 +441,20 @@ mnemon_load_category (mnemon_t             *mnemon,
     free (line);
     fclose (file);
     free (path);
+
+    /* Resize category items to fit exactly. */
+    category->items_size = category->num_items;
+    category->items = xrealloc (category->items, category->items_size * sizeof (item_t));
+
+    /* Now that the category is completely loaded, with stable
+     * pointers to every item, we can add each item to its appropriate
+     * bin. */
+    for (i = 0; i < category->num_items; i++) {
+       item_t *item = &category->items[i];
+       bin_t *bin = mnemon_get_bin (mnemon, item->count);
+
+       bin_add_item (bin, item);
+    }
 }
 
 static void
@@ -497,6 +501,7 @@ mnemon_save (mnemon_t *mnemon)
                   mnemon->dir_name, category->name);
        xasprintf (&lock_filename, "%s/.#%s",
                   mnemon->dir_name, category->name);
+
        file = fopen (lock_filename, "w");
        if (file == NULL) {
            fprintf (stderr, "Error: Failed to open %s for writing: %s\n",
@@ -506,12 +511,17 @@ mnemon_save (mnemon_t *mnemon)
 
        category_print (category, file);
 
+       fclose (file);
+
        err = rename (lock_filename, filename);
        if (err < 0) {
            fprintf (stderr, "Error: Failes to rename %s to %s: %s\n",
                     lock_filename, filename, strerror (errno));
            continue;
        }
+
+       free (filename);
+       free (lock_filename);
     }
 }