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