1/* 2 * Part of Very Secure FTPd 3 * Licence: GPL v2 4 * Author: Chris Evans 5 * strlist.c 6 */ 7 8/* Anti-lamer measures deployed, sir! */ 9#define PRIVATE_HANDS_OFF_alloc_len alloc_len 10#define PRIVATE_HANDS_OFF_list_len list_len 11#define PRIVATE_HANDS_OFF_p_nodes p_nodes 12#include "strlist.h" 13 14#include "str.h" 15#include "utility.h" 16#include "sysutil.h" 17 18struct mystr_list_node 19{ 20 struct mystr str; 21 struct mystr sort_key_str; 22}; 23 24/* File locals */ 25static struct mystr s_null_str; 26 27static int sort_compare_func(const void* p1, const void* p2); 28static int sort_compare_func_reverse(const void* p1, const void* p2); 29static int sort_compare_common(const void* p1, const void* p2, int reverse); 30 31void 32str_list_free(struct mystr_list* p_list) 33{ 34 unsigned int i; 35 for (i=0; i < p_list->list_len; ++i) 36 { 37 str_free(&p_list->p_nodes[i].str); 38 str_free(&p_list->p_nodes[i].sort_key_str); 39 } 40 p_list->list_len = 0; 41 p_list->alloc_len = 0; 42 if (p_list->p_nodes) 43 { 44 vsf_sysutil_free(p_list->p_nodes); 45 p_list->p_nodes = 0; 46 } 47} 48 49int 50str_list_get_length(const struct mystr_list* p_list) 51{ 52 return p_list->list_len; 53} 54 55int 56str_list_contains_str(const struct mystr_list* p_list, 57 const struct mystr* p_str) 58{ 59 unsigned int i; 60 for (i=0; i < p_list->list_len; ++i) 61 { 62 if (str_equal(p_str, &p_list->p_nodes[i].str)) 63 { 64 return 1; 65 } 66 } 67 return 0; 68} 69 70void 71str_list_add(struct mystr_list* p_list, const struct mystr* p_str, 72 const struct mystr* p_sort_key_str) 73{ 74 struct mystr_list_node* p_node; 75 /* Expand the node allocation if we have to */ 76 if (p_list->list_len == p_list->alloc_len) 77 { 78 if (p_list->alloc_len == 0) 79 { 80 p_list->alloc_len = 32; 81 p_list->p_nodes = vsf_sysutil_malloc(p_list->alloc_len * 82 sizeof(struct mystr_list_node)); 83 } 84 else 85 { 86 p_list->alloc_len *= 2; 87 p_list->p_nodes = vsf_sysutil_realloc(p_list->p_nodes, 88 p_list->alloc_len * 89 sizeof(struct mystr_list_node)); 90 } 91 } 92 p_node = &p_list->p_nodes[p_list->list_len]; 93 p_node->str = s_null_str; 94 p_node->sort_key_str = s_null_str; 95 str_copy(&p_node->str, p_str); 96 if (p_sort_key_str) 97 { 98 str_copy(&p_node->sort_key_str, p_sort_key_str); 99 } 100 p_list->list_len++; 101} 102 103void 104str_list_sort(struct mystr_list* p_list, int reverse) 105{ 106 if (!reverse) 107 { 108 vsf_sysutil_qsort(p_list->p_nodes, p_list->list_len, 109 sizeof(struct mystr_list_node), sort_compare_func); 110 } 111 else 112 { 113 vsf_sysutil_qsort(p_list->p_nodes, p_list->list_len, 114 sizeof(struct mystr_list_node), 115 sort_compare_func_reverse); 116 } 117} 118 119static int 120sort_compare_func(const void* p1, const void* p2) 121{ 122 return sort_compare_common(p1, p2, 0); 123} 124 125static int 126sort_compare_func_reverse(const void* p1, const void* p2) 127{ 128 return sort_compare_common(p1, p2, 1); 129} 130 131static int 132sort_compare_common(const void* p1, const void* p2, int reverse) 133{ 134 const struct mystr* p_cmp1; 135 const struct mystr* p_cmp2; 136 const struct mystr_list_node* p_node1 = (const struct mystr_list_node*) p1; 137 const struct mystr_list_node* p_node2 = (const struct mystr_list_node*) p2; 138 if (!str_isempty(&p_node1->sort_key_str)) 139 { 140 p_cmp1 = &p_node1->sort_key_str; 141 } 142 else 143 { 144 p_cmp1 = &p_node1->str; 145 } 146 if (!str_isempty(&p_node2->sort_key_str)) 147 { 148 p_cmp2 = &p_node2->sort_key_str; 149 } 150 else 151 { 152 p_cmp2 = &p_node2->str; 153 } 154 155 if (reverse) 156 { 157 return str_strcmp(p_cmp2, p_cmp1); 158 } 159 else 160 { 161 return str_strcmp(p_cmp1, p_cmp2); 162 } 163} 164 165const struct mystr* 166str_list_get_pstr(const struct mystr_list* p_list, unsigned int indexx) 167{ 168 if (indexx >= p_list->list_len) 169 { 170 bug("indexx out of range in str_list_get_str"); 171 } 172 return &p_list->p_nodes[indexx].str; 173} 174 175