diff options
author | James Booth <boothj5@gmail.com> | 2012-04-30 02:36:45 +0100 |
---|---|---|
committer | James Booth <boothj5@gmail.com> | 2012-04-30 02:36:45 +0100 |
commit | f21cb52ab025cfe1bc90226d7bb433fc775d390e (patch) | |
tree | c98e3f6a58c1e3a3f121800643cd70429d4dd2f5 | |
parent | b6c5fef45eaadce4463ee60e60eb0a0252b61255 (diff) | |
download | profani-tty-f21cb52ab025cfe1bc90226d7bb433fc775d390e.tar.gz |
Create history session
-rw-r--r-- | prof_history.c | 108 | ||||
-rw-r--r-- | prof_history.h | 4 | ||||
-rw-r--r-- | test_prof_history.c | 64 |
3 files changed, 137 insertions, 39 deletions
diff --git a/prof_history.c b/prof_history.c index 3aca0150..24213140 100644 --- a/prof_history.c +++ b/prof_history.c @@ -8,16 +8,23 @@ struct p_history_t { GList *items; // the history + GList *items_curr; // pointer to the current line in the history GList *session; // a copy of the history for edits - GList *session_current; // pointer to the current item in the session + GList *sess_curr; // pointer to the current item in the session + GList *sess_new; // pointer to a possible new element in the session guint max_size; }; +static void _replace_history_with_session(PHistory history); + PHistory p_history_new(unsigned int size) { PHistory new_history = malloc(sizeof(struct p_history_t)); new_history->items = NULL; + new_history->items_curr = NULL; new_history->session = NULL; + new_history->sess_curr = NULL; + new_history->sess_new = NULL; new_history->max_size = size; return new_history; @@ -26,66 +33,111 @@ PHistory p_history_new(unsigned int size) void p_history_append(PHistory history, char *item) { char *copied = strdup(item); - // if already at max size - if (g_list_length(history->items) == history->max_size) { - // remove first element + // if not editing history (no session) + if (history->session == NULL) { + + // if already at max size + if (g_list_length(history->items) == history->max_size) { + + // remove first element + GList *first = g_list_first(history->items); + const char *first_item = (char *) first->data; + history->items = g_list_remove(history->items, first_item); + } + + // append the new item onto the history + history->items = g_list_append(history->items, copied); + + // if editing history (session exists with possible changes) + } else { + + // if adding a new element, copy the session over the history + if (history->sess_curr == history->sess_new) { + _replace_history_with_session(history); + + // otherwise, adding edited history item + } else { + // remove the new item, from the session + history->session = g_list_reverse(history->session); + GList *first = g_list_first(history->session); + const char *first_item = (char *) first->data; + history->session = g_list_remove(history->session, first_item); + history->session = g_list_reverse(history->session); + + // copy sess_curr to the end of the session + char *new_data = strdup(history->sess_curr->data); + history->session = g_list_append(history->session, new_data); + + // replace the edited version with the data from the history + history->sess_curr->data = strdup(history->items_curr->data); + + // rewrite history from the session + _replace_history_with_session(history); + } + } +} + +static void _replace_history_with_session(PHistory history) +{ + g_list_free(history->items); + history->items = g_list_copy(history->session); + + // remove first if overrun max size + if (g_list_length(history->items) > history->max_size) { GList *first = g_list_first(history->items); const char *first_item = (char *) first->data; history->items = g_list_remove(history->items, first_item); } - // append the new item onto the history - history->items = g_list_append(history->items, copied); - - // delete the current session - if (history->session != NULL) { - g_list_free(history->session); - history->session = NULL; - } + // reset the session + history->items_curr = NULL; + history->session = NULL; + history->sess_curr = NULL; + history->sess_new = NULL; } -char * p_history_previous(PHistory history) +char * p_history_previous(PHistory history, char *item) { if (history->items == NULL) { - return NULL; + return item; } if (history->session == NULL) { history->session = g_list_copy(history->items); - history->session_current = g_list_last(history->session); + history->sess_curr = g_list_last(history->session); } else { - history->session_current = g_list_previous(history->session_current); + history->sess_curr = g_list_previous(history->sess_curr); } // set to first if rolled over beginning - if (history->session_current == NULL) { - history->session_current = g_list_first(history->session); + if (history->sess_curr == NULL) { + history->sess_curr = g_list_first(history->session); } - char *item = (char *) history->session_current->data; - char *result = malloc((strlen(item) + 1) * sizeof(char)); - strcpy(result, item); + char *curr = history->sess_curr->data; + char *result = malloc((strlen(curr) + 1) * sizeof(char)); + strcpy(result, curr); return result; } -char * p_history_next(PHistory history) +char * p_history_next(PHistory history, char *item) { if (history->session == NULL) { return NULL; } else { - history->session_current = g_list_next(history->session_current); + history->sess_curr = g_list_next(history->sess_curr); } // set to last if rolled over end - if (history->session_current == NULL) { - history->session_current = g_list_last(history->session); + if (history->sess_curr == NULL) { + history->sess_curr = g_list_last(history->session); } - char *item = (char *) history->session_current->data; - char *result = malloc((strlen(item) + 1) * sizeof(char)); - strcpy(result, item); + char *curr = history->sess_curr->data; + char *result = malloc((strlen(curr) + 1) * sizeof(char)); + strcpy(result, curr); return result; } diff --git a/prof_history.h b/prof_history.h index 5c2acaaf..04c6fdaf 100644 --- a/prof_history.h +++ b/prof_history.h @@ -4,8 +4,8 @@ typedef struct p_history_t *PHistory; PHistory p_history_new(unsigned int size); -char * p_history_previous(PHistory history); -char * p_history_next(PHistory history); +char * p_history_previous(PHistory history, char *item); +char * p_history_next(PHistory history, char *item); void p_history_append(PHistory history, char *item); #endif diff --git a/test_prof_history.c b/test_prof_history.c index 5a9ae217..db4ef24b 100644 --- a/test_prof_history.c +++ b/test_prof_history.c @@ -2,18 +2,18 @@ #include <head-unit.h> #include "prof_history.h" -void previous_on_empty_returns_null(void) +void previous_on_empty_returns_current(void) { PHistory history = p_history_new(10); - char *item = p_history_previous(history); + char *item = p_history_previous(history, "inp"); - assert_is_null(item); + assert_string_equals("inp", item); } void next_on_empty_returns_null(void) { PHistory history = p_history_new(10); - char *item = p_history_next(history); + char *item = p_history_next(history, "inp"); assert_is_null(item); } @@ -23,7 +23,7 @@ void previous_once_returns_last(void) PHistory history = p_history_new(10); p_history_append(history, "Hello"); - char *item = p_history_previous(history); + char *item = p_history_previous(history, "inp"); assert_string_equals("Hello", item); } @@ -33,17 +33,63 @@ void previous_twice_when_one_returns_first(void) PHistory history = p_history_new(10); p_history_append(history, "Hello"); - p_history_previous(history); - char *item = p_history_previous(history); + char *item1 = p_history_previous(history, NULL); + char *item2 = p_history_previous(history, item1); - assert_string_equals("Hello", item); + assert_string_equals("Hello", item2); +} + +void previous_always_stops_at_first(void) +{ + PHistory history = p_history_new(10); + p_history_append(history, "Hello"); + + char *item1 = p_history_previous(history, NULL); + char *item2 = p_history_previous(history, item1); + char *item3 = p_history_previous(history, item2); + char *item4 = p_history_previous(history, item3); + char *item5 = p_history_previous(history, item4); + char *item6 = p_history_previous(history, item5); + + assert_string_equals("Hello", item6); +} + +void previous_goes_to_correct_element(void) +{ + PHistory history = p_history_new(10); + p_history_append(history, "Hello"); + p_history_append(history, "world"); + p_history_append(history, "whats"); + p_history_append(history, "going"); + p_history_append(history, "on"); + p_history_append(history, "here"); + + char *item1 = p_history_previous(history, NULL); + char *item2 = p_history_previous(history, item1); + char *item3 = p_history_previous(history, item2); + + assert_string_equals("going", item3); +} + +void prev_then_next_returns_null(void) +{ + PHistory history = p_history_new(10); + p_history_append(history, "Hello"); + + char *item1 = p_history_previous(history, NULL); + char *item2 = p_history_next(history, item1); + + assert_is_null(item2); } void register_prof_history_tests(void) { TEST_MODULE("prof_history tests"); - TEST(previous_on_empty_returns_null); + TEST(previous_on_empty_returns_current); TEST(next_on_empty_returns_null); TEST(previous_once_returns_last); TEST(previous_twice_when_one_returns_first); + TEST(previous_always_stops_at_first); + TEST(previous_goes_to_correct_element); + TEST(prev_then_next_returns_null); } |