1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-09-22 19:45:54 -04:00

Rewrote copying of contact list for /who

This commit is contained in:
James Booth 2012-03-20 00:05:33 +00:00
parent 9a3a0840e3
commit dab37236a2
7 changed files with 231 additions and 151 deletions

View File

@ -156,7 +156,7 @@ static int _cmd_who(void)
if (conn_status != JABBER_CONNECTED) {
cons_not_connected();
} else {
contact_list_t *list = get_contact_list();
struct contact_node_t *list = get_contact_list();
cons_show_online_contacts(list);
}

View File

@ -26,33 +26,29 @@
#include "contact_list.h"
// contact list node
struct _contact_node_t {
contact_t *contact;
struct _contact_node_t *next;
};
// internal contact list
static struct contact_node_t * _contact_list = NULL;
// contact list
static struct _contact_node_t * _contact_list = NULL;
// state of current tab completion, currrent node and current search pattern
static struct _contact_node_t * _last_found = NULL;
// state of current tab completion, currrent node
static struct contact_node_t * _last_found = NULL;
// and current search pattern
static char * _search_str = NULL;
static char * _search_contact_list_from(struct _contact_node_t * curr);
static struct _contact_node_t * _make_contact_node(const char * const name,
static char * _search_contact_list_from(struct contact_node_t * curr);
static struct contact_node_t * _make_contact_node(const char * const name,
const char * const show, const char * const status);
static contact_t * _new_contact(const char * const name, const char * const show,
static struct contact_t * _new_contact(const char * const name, const char * const show,
const char * const status);
static void _destroy_contact(contact_t *contact);
static void _destroy_contact(struct contact_t *contact);
static struct contact_node_t * _copy_contact_list(struct contact_node_t *node);
void contact_list_clear(void)
{
struct _contact_node_t *curr = _contact_list;
struct contact_node_t *curr = _contact_list;
if (curr) {
while(curr) {
contact_t *contact = curr->contact;
struct contact_t *contact = curr->contact;
_destroy_contact(contact);
curr = curr->next;
}
@ -64,6 +60,18 @@ void contact_list_clear(void)
}
}
void destroy_list(struct contact_node_t *list)
{
while(list) {
struct contact_t *contact = list->contact;
_destroy_contact(contact);
list = list->next;
}
free(list);
list = NULL;
}
void reset_search_attempts(void)
{
_last_found = NULL;
@ -78,11 +86,11 @@ int contact_list_remove(const char * const name)
if (!_contact_list) {
return 0;
} else {
struct _contact_node_t *curr = _contact_list;
struct _contact_node_t *prev = NULL;
struct contact_node_t *curr = _contact_list;
struct contact_node_t *prev = NULL;
while(curr) {
contact_t *contact = curr->contact;
struct contact_t *contact = curr->contact;
if (strcmp(contact->name, name) == 0) {
if (prev)
prev->next = curr->next;
@ -117,20 +125,20 @@ int contact_list_add(const char * const name, const char * const show,
return 1;
} else {
struct _contact_node_t *curr = _contact_list;
struct _contact_node_t *prev = NULL;
struct contact_node_t *curr = _contact_list;
struct contact_node_t *prev = NULL;
while(curr) {
contact_t *curr_contact = curr->contact;
struct contact_t *curr_contact = curr->contact;
// insert
if (strcmp(curr_contact->name, name) > 0) {
if (prev) {
struct _contact_node_t *new = _make_contact_node(name, show, status);
struct contact_node_t *new = _make_contact_node(name, show, status);
new->next = curr;
prev->next = new;
} else {
struct _contact_node_t *new = _make_contact_node(name, show, status);
struct contact_node_t *new = _make_contact_node(name, show, status);
new->next = _contact_list;
_contact_list = new;
}
@ -156,36 +164,32 @@ int contact_list_add(const char * const name, const char * const show,
}
}
contact_list_t * get_contact_list(void)
struct contact_node_t * get_contact_list(void)
{
int count = 0;
struct contact_node_t *copy = NULL;
struct contact_node_t *curr = _contact_list;
contact_list_t *list =
(contact_list_t *) malloc(sizeof(contact_list_t));
copy = _copy_contact_list(curr);
struct _contact_node_t *curr = _contact_list;
if (!curr) {
list->contacts = NULL;
} else {
list->contacts = (contact_t **) malloc(sizeof(contact_t *));
while(curr) {
contact_t *curr_contact = curr->contact;
list->contacts[count] =
_new_contact(curr_contact->name, curr_contact->show,
curr_contact->status);
count++;
curr = curr->next;
}
}
list->size = count;
return list;
return copy;
}
char * find_contact(const char * const search_str)
struct contact_node_t * _copy_contact_list(struct contact_node_t *node)
{
if (node == NULL) {
return NULL;
} else {
struct contact_t *curr_contact = node->contact;
struct contact_node_t *copy =
_make_contact_node(curr_contact->name, curr_contact->show, curr_contact->status);
copy->next = _copy_contact_list(node->next);
return copy;
}
}
char * find_contact(char *search_str)
{
char *found = NULL;
@ -219,10 +223,22 @@ char * find_contact(const char * const search_str)
}
}
static char * _search_contact_list_from(struct _contact_node_t * curr)
int get_size(struct contact_node_t *list)
{
int size = 0;
while(list) {
size++;
list = list->next;
}
return size;
}
static char * _search_contact_list_from(struct contact_node_t * curr)
{
while(curr) {
contact_t *curr_contact = curr->contact;
struct contact_t *curr_contact = curr->contact;
// match found
if (strncmp(curr_contact->name, _search_str, strlen(_search_str)) == 0) {
@ -243,21 +259,21 @@ static char * _search_contact_list_from(struct _contact_node_t * curr)
return NULL;
}
static struct _contact_node_t * _make_contact_node(const char * const name,
static struct contact_node_t * _make_contact_node(const char * const name,
const char * const show, const char * const status)
{
struct _contact_node_t *new =
(struct _contact_node_t *) malloc(sizeof(struct _contact_node_t));
struct contact_node_t *new =
(struct contact_node_t *) malloc(sizeof(struct contact_node_t));
new->contact = _new_contact(name, show, status);
new->next = NULL;
return new;
}
static contact_t * _new_contact(const char * const name, const char * const show,
static struct contact_t * _new_contact(const char * const name, const char * const show,
const char * const status)
{
contact_t *new = (contact_t *) malloc(sizeof(contact_t));
struct contact_t *new = (struct contact_t *) malloc(sizeof(struct contact_t));
new->name = (char *) malloc((strlen(name) + 1) * sizeof(char));
strcpy(new->name, name);
@ -279,15 +295,20 @@ static contact_t * _new_contact(const char * const name, const char * const show
return new;
}
static void _destroy_contact(contact_t *contact)
static void _destroy_contact(struct contact_t *contact)
{
free(contact->name);
if (contact->show != NULL)
if (contact->show != NULL) {
free(contact->show);
if (contact->status != NULL)
contact->show = NULL;
}
if (contact->status != NULL) {
free(contact->status);
contact->status = NULL;
}
free(contact);
contact = NULL;
}

View File

@ -23,23 +23,25 @@
#ifndef CONTACT_LIST_H
#define CONTACT_LIST_H
typedef struct _contact {
struct contact_t {
char *name;
char *show;
char *status;
} contact_t;
};
typedef struct _contact_list_t {
contact_t **contacts;
int size;
} contact_list_t;
struct contact_node_t {
struct contact_t *contact;
struct contact_node_t *next;
};
void contact_list_clear(void);
void reset_search_attempts(void);
int contact_list_add(const char * const name, const char * const show,
const char * const status);
int contact_list_remove(const char * const name);
contact_list_t * get_contact_list(void);
char * find_contact(const char * const search_str);
struct contact_node_t * get_contact_list(void);
char * find_contact(char *search_str);
int get_size(struct contact_node_t *list);
void destroy_list(struct contact_node_t *list);
#endif

View File

@ -43,7 +43,7 @@ void history_init(void)
void history_append(const char * const inp)
{
if (_size < MAX_HISTORY) {
_history[_size] = (char*) malloc(strlen(inp) * sizeof(char));
_history[_size] = (char*) malloc((strlen(inp) + 1) * sizeof(char));
strcpy(_history[_size], inp);
_pos = _size;
_size++;

View File

@ -1,4 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <head-unit.h>
#include "contact_list.h"
@ -7,47 +9,58 @@ static void beforetest(void)
contact_list_clear();
}
static void aftertest(void)
{
contact_list_clear();
}
static void empty_list_when_none_added(void)
{
contact_list_t *list = get_contact_list();
assert_int_equals(0, list->size);
struct contact_node_t *list = get_contact_list();
assert_is_null(list);
destroy_list(list);
}
static void contains_one_element(void)
{
contact_list_add("James", NULL, NULL);
contact_list_t *list = get_contact_list();
assert_int_equals(1, list->size);
struct contact_node_t *list = get_contact_list();
assert_int_equals(1, get_size(list));
destroy_list(list);
}
static void first_element_correct(void)
{
contact_list_add("James", NULL, NULL);
contact_list_t *list = get_contact_list();
contact_t *james = list->contacts[0];
struct contact_node_t *list = get_contact_list();
struct contact_t *james = list->contact;
assert_string_equals("James", james->name);
destroy_list(list);
}
static void contains_two_elements(void)
{
contact_list_add("James", NULL, NULL);
contact_list_add("Dave", NULL, NULL);
contact_list_t *list = get_contact_list();
struct contact_node_t *list = get_contact_list();
assert_int_equals(2, list->size);
assert_int_equals(2, get_size(list));
destroy_list(list);
}
static void first_and_second_elements_correct(void)
{
contact_list_add("James", NULL, NULL);
contact_list_add("Dave", NULL, NULL);
contact_list_t *list = get_contact_list();
contact_t *dave = list->contacts[0];
contact_t *james = list->contacts[1];
struct contact_node_t *list = get_contact_list();
struct contact_t *dave = list->contact;
struct contact_t *james = (list->next)->contact;
assert_string_equals("James", james->name);
assert_string_equals("Dave", dave->name);
destroy_list(list);
}
static void contains_three_elements(void)
@ -55,9 +68,10 @@ static void contains_three_elements(void)
contact_list_add("James", NULL, NULL);
contact_list_add("Bob", NULL, NULL);
contact_list_add("Dave", NULL, NULL);
contact_list_t *list = get_contact_list();
struct contact_node_t *list = get_contact_list();
assert_int_equals(3, list->size);
assert_int_equals(3, get_size(list));
destroy_list(list);
}
static void first_three_elements_correct(void)
@ -65,14 +79,15 @@ static void first_three_elements_correct(void)
contact_list_add("Bob", NULL, NULL);
contact_list_add("Dave", NULL, NULL);
contact_list_add("James", NULL, NULL);
contact_list_t *list = get_contact_list();
contact_t *bob = list->contacts[0];
contact_t *dave = list->contacts[1];
contact_t *james = list->contacts[2];
struct contact_node_t *list = get_contact_list();
struct contact_t *bob = list->contact;
struct contact_t *dave = (list->next)->contact;
struct contact_t *james = ((list->next)->next)->contact;
assert_string_equals("James", james->name);
assert_string_equals("Dave", dave->name);
assert_string_equals("Bob", bob->name);
destroy_list(list);
}
static void add_twice_at_beginning_adds_once(void)
@ -81,15 +96,16 @@ static void add_twice_at_beginning_adds_once(void)
contact_list_add("James", NULL, NULL);
contact_list_add("Dave", NULL, NULL);
contact_list_add("Bob", NULL, NULL);
contact_list_t *list = get_contact_list();
contact_t *bob = list->contacts[0];
contact_t *dave = list->contacts[1];
contact_t *james = list->contacts[2];
struct contact_node_t *list = get_contact_list();
struct contact_t *bob = list->contact;
struct contact_t *dave = (list->next)->contact;
struct contact_t *james = ((list->next)->next)->contact;
assert_int_equals(3, list->size);
assert_int_equals(3, get_size(list));
assert_string_equals("James", james->name);
assert_string_equals("Dave", dave->name);
assert_string_equals("Bob", bob->name);
destroy_list(list);
}
static void add_twice_in_middle_adds_once(void)
@ -98,15 +114,16 @@ static void add_twice_in_middle_adds_once(void)
contact_list_add("Dave", NULL, NULL);
contact_list_add("James", NULL, NULL);
contact_list_add("Bob", NULL, NULL);
contact_list_t *list = get_contact_list();
contact_t *bob = list->contacts[0];
contact_t *dave = list->contacts[1];
contact_t *james = list->contacts[2];
struct contact_node_t *list = get_contact_list();
struct contact_t *bob = list->contact;
struct contact_t *dave = (list->next)->contact;
struct contact_t *james = ((list->next)->next)->contact;
assert_int_equals(3, list->size);
assert_int_equals(3, get_size(list));
assert_string_equals("James", james->name);
assert_string_equals("Dave", dave->name);
assert_string_equals("Bob", bob->name);
destroy_list(list);
}
static void add_twice_at_end_adds_once(void)
@ -115,32 +132,35 @@ static void add_twice_at_end_adds_once(void)
contact_list_add("Dave", NULL, NULL);
contact_list_add("Bob", NULL, NULL);
contact_list_add("James", NULL, NULL);
contact_list_t *list = get_contact_list();
contact_t *bob = list->contacts[0];
contact_t *dave = list->contacts[1];
contact_t *james = list->contacts[2];
struct contact_node_t *list = get_contact_list();
struct contact_t *bob = list->contact;
struct contact_t *dave = (list->next)->contact;
struct contact_t *james = ((list->next)->next)->contact;
assert_int_equals(3, list->size);
assert_int_equals(3, get_size(list));
assert_string_equals("James", james->name);
assert_string_equals("Dave", dave->name);
assert_string_equals("Bob", bob->name);
destroy_list(list);
}
static void remove_when_none_does_nothing(void)
{
contact_list_remove("James");
contact_list_t *list = get_contact_list();
struct contact_node_t *list = get_contact_list();
assert_int_equals(0, list->size);
assert_int_equals(0, get_size(list));
destroy_list(list);
}
static void remove_when_one_removes(void)
{
contact_list_add("James", NULL, NULL);
contact_list_remove("James");
contact_list_t *list = get_contact_list();
struct contact_node_t *list = get_contact_list();
assert_int_equals(0, list->size);
assert_int_equals(0, get_size(list));
destroy_list(list);
}
static void remove_first_when_two(void)
@ -149,11 +169,12 @@ static void remove_first_when_two(void)
contact_list_add("Dave", NULL, NULL);
contact_list_remove("James");
contact_list_t *list = get_contact_list();
struct contact_node_t *list = get_contact_list();
assert_int_equals(1, list->size);
contact_t *dave = list->contacts[0];
assert_int_equals(1, get_size(list));
struct contact_t *dave = list->contact;
assert_string_equals("Dave", dave->name);
destroy_list(list);
}
static void remove_second_when_two(void)
@ -162,11 +183,12 @@ static void remove_second_when_two(void)
contact_list_add("Dave", NULL, NULL);
contact_list_remove("Dave");
contact_list_t *list = get_contact_list();
struct contact_node_t *list = get_contact_list();
assert_int_equals(1, list->size);
contact_t *james = list->contacts[0];
assert_int_equals(1, get_size(list));
struct contact_t *james = list->contact;
assert_string_equals("James", james->name);
destroy_list(list);
}
static void remove_first_when_three(void)
@ -176,14 +198,15 @@ static void remove_first_when_three(void)
contact_list_add("Bob", NULL, NULL);
contact_list_remove("James");
contact_list_t *list = get_contact_list();
struct contact_node_t *list = get_contact_list();
assert_int_equals(2, list->size);
contact_t *bob = list->contacts[0];
contact_t *dave = list->contacts[1];
assert_int_equals(2, get_size(list));
struct contact_t *bob = list->contact;
struct contact_t *dave = (list->next)->contact;
assert_string_equals("Dave", dave->name);
assert_string_equals("Bob", bob->name);
destroy_list(list);
}
static void remove_second_when_three(void)
@ -193,14 +216,15 @@ static void remove_second_when_three(void)
contact_list_add("Bob", NULL, NULL);
contact_list_remove("Dave");
contact_list_t *list = get_contact_list();
struct contact_node_t *list = get_contact_list();
assert_int_equals(2, list->size);
contact_t *bob = list->contacts[0];
contact_t *james = list->contacts[1];
assert_int_equals(2, get_size(list));
struct contact_t *bob = list->contact;
struct contact_t *james = (list->next)->contact;
assert_string_equals("James", james->name);
assert_string_equals("Bob", bob->name);
destroy_list(list);
}
static void remove_third_when_three(void)
@ -210,107 +234,117 @@ static void remove_third_when_three(void)
contact_list_add("Bob", NULL, NULL);
contact_list_remove("Bob");
contact_list_t *list = get_contact_list();
struct contact_node_t *list = get_contact_list();
assert_int_equals(2, list->size);
contact_t *dave = list->contacts[0];
contact_t *james = list->contacts[1];
assert_int_equals(2, get_size(list));
struct contact_t *dave = list->contact;
struct contact_t *james = (list->next)->contact;
assert_string_equals("James", james->name);
assert_string_equals("Dave", dave->name);
destroy_list(list);
}
static void test_show_when_value(void)
{
contact_list_add("James", "away", NULL);
contact_list_t *list = get_contact_list();
contact_t *james = list->contacts[0];
struct contact_node_t *list = get_contact_list();
struct contact_t *james = list->contact;
assert_string_equals("away", james->show);
destroy_list(list);
}
static void test_show_online_when_no_value(void)
{
contact_list_add("James", NULL, NULL);
contact_list_t *list = get_contact_list();
contact_t *james = list->contacts[0];
struct contact_node_t *list = get_contact_list();
struct contact_t *james = list->contact;
assert_string_equals("online", james->show);
destroy_list(list);
}
static void test_show_online_when_empty_string(void)
{
contact_list_add("James", "", NULL);
contact_list_t *list = get_contact_list();
contact_t *james = list->contacts[0];
struct contact_node_t *list = get_contact_list();
struct contact_t *james = list->contact;
assert_string_equals("online", james->show);
destroy_list(list);
}
static void test_status_when_value(void)
{
contact_list_add("James", NULL, "I'm not here right now");
contact_list_t *list = get_contact_list();
contact_t *james = list->contacts[0];
struct contact_node_t *list = get_contact_list();
struct contact_t *james = list->contact;
assert_string_equals("I'm not here right now", james->status);
destroy_list(list);
}
static void test_status_when_no_value(void)
{
contact_list_add("James", NULL, NULL);
contact_list_t *list = get_contact_list();
contact_t *james = list->contacts[0];
struct contact_node_t *list = get_contact_list();
struct contact_t *james = list->contact;
assert_is_null(james->status);
destroy_list(list);
}
static void update_show(void)
{
contact_list_add("James", "away", NULL);
contact_list_add("James", "dnd", NULL);
contact_list_t *list = get_contact_list();
struct contact_node_t *list = get_contact_list();
assert_int_equals(1, list->size);
contact_t *james = list->contacts[0];
assert_int_equals(1, get_size(list));
struct contact_t *james = list->contact;
assert_string_equals("James", james->name);
assert_string_equals("dnd", james->show);
destroy_list(list);
}
static void set_show_to_null(void)
{
contact_list_add("James", "away", NULL);
contact_list_add("James", NULL, NULL);
contact_list_t *list = get_contact_list();
struct contact_node_t *list = get_contact_list();
assert_int_equals(1, list->size);
contact_t *james = list->contacts[0];
assert_int_equals(1, get_size(list));
struct contact_t *james = list->contact;
assert_string_equals("James", james->name);
assert_string_equals("online", james->show);
destroy_list(list);
}
static void update_status(void)
{
contact_list_add("James", NULL, "I'm not here right now");
contact_list_add("James", NULL, "Gone to lunch");
contact_list_t *list = get_contact_list();
struct contact_node_t *list = get_contact_list();
assert_int_equals(1, list->size);
contact_t *james = list->contacts[0];
assert_int_equals(1, get_size(list));
struct contact_t *james = list->contact;
assert_string_equals("James", james->name);
assert_string_equals("Gone to lunch", james->status);
destroy_list(list);
}
static void set_status_to_null(void)
{
contact_list_add("James", NULL, "Gone to lunch");
contact_list_add("James", NULL, NULL);
contact_list_t *list = get_contact_list();
struct contact_node_t *list = get_contact_list();
assert_int_equals(1, list->size);
contact_t *james = list->contacts[0];
assert_int_equals(1, get_size(list));
struct contact_t *james = list->contact;
assert_string_equals("James", james->name);
assert_is_null(james->status);
destroy_list(list);
}
static void find_first_exists(void)
@ -319,8 +353,13 @@ static void find_first_exists(void)
contact_list_add("Dave", NULL, NULL);
contact_list_add("Bob", NULL, NULL);
char *result = find_contact("B");
char *search = (char *) malloc(2 * sizeof(char));
strcpy(search, "B");
char *result = find_contact(search);
assert_string_equals("Bob", result);
free(result);
free(search);
}
static void find_second_exists(void)
@ -331,6 +370,7 @@ static void find_second_exists(void)
char *result = find_contact("Dav");
assert_string_equals("Dave", result);
free(result);
}
static void find_third_exists(void)
@ -341,6 +381,7 @@ static void find_third_exists(void)
char *result = find_contact("Ja");
assert_string_equals("James", result);
free(result);
}
static void find_returns_null(void)
@ -368,6 +409,8 @@ static void find_twice_returns_second_when_two_match(void)
char *result1 = find_contact("Jam");
char *result2 = find_contact(result1);
assert_string_equals("Jamie", result2);
free(result1);
free(result2);
}
static void find_five_times_finds_fifth(void)
@ -389,6 +432,11 @@ static void find_five_times_finds_fifth(void)
char *result4 = find_contact(result3);
char *result5 = find_contact(result4);
assert_string_equals("Jamo", result5);
free(result1);
free(result2);
free(result3);
free(result4);
free(result5);
}
static void find_twice_returns_first_when_two_match_and_reset(void)
@ -401,6 +449,8 @@ static void find_twice_returns_first_when_two_match_and_reset(void)
reset_search_attempts();
char *result2 = find_contact(result1);
assert_string_equals("James", result2);
free(result1);
free(result2);
}
static void removed_contact_not_in_search(void)
@ -416,12 +466,16 @@ static void removed_contact_not_in_search(void)
contact_list_remove("James");
char *result3 = find_contact(result2);
assert_string_equals("Jamie", result3);
free(result1);
free(result2);
free(result3);
}
void register_contact_list_tests(void)
{
TEST_MODULE("contact_list tests");
BEFORETEST(beforetest);
AFTERTEST(aftertest);
TEST(empty_list_when_none_added);
TEST(contains_one_element);
TEST(first_element_correct);

View File

@ -239,14 +239,15 @@ void cons_help(void)
dirty = TRUE;
}
void cons_show_online_contacts(const contact_list_t * const list)
void cons_show_online_contacts(struct contact_node_t *list)
{
_win_show_time(_cons_win);
wprintw(_cons_win, "Online contacts:\n");
int i;
for (i = 0; i < list->size; i++) {
contact_t *contact = list->contacts[i];
struct contact_node_t *curr = list;
while(curr) {
struct contact_t *contact = curr->contact;
_win_show_time(_cons_win);
wattron(_cons_win, COLOR_PAIR(2));
wprintw(_cons_win, "%s", contact->name);
@ -256,6 +257,8 @@ void cons_show_online_contacts(const contact_list_t * const list)
wprintw(_cons_win, ", \"%s\"", contact->status);
wprintw(_cons_win, "\n");
wattroff(_cons_win, COLOR_PAIR(2));
curr = curr->next;
}
}

View File

@ -74,7 +74,7 @@ void cons_bad_message(void);
void cons_show(const char * const cmd);
void cons_bad_show(const char * const cmd);
void cons_highlight_show(const char * const cmd);
void cons_show_online_contacts(const contact_list_t * const list);
void cons_show_online_contacts(struct contact_node_t * list);
// status bar actions
void status_bar_refresh(void);