1 /**
2  * Dynamic Array
3  *
4  * Copyright (C) 2006-2014 by
5  * Jeffrey Fulmer - <jeff@joedog.org>, et al.
6  * This file is distributed as part of Siege
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  *--
22  */
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <limits.h>
27 #include <array.h>
28 #include <memory.h>
29 #include <setup.h>
30 
31 typedef void *array;
32 
33 struct ARRAY_T
34 {
35   int     index;
36   int     length;
37   array * data;
38   method  free;
39 };
40 
41 size_t ARRAYSIZE = sizeof(struct ARRAY_T);
42 
43 ARRAY
new_array()44 new_array()
45 {
46   ARRAY this;
47 
48   this = xcalloc(sizeof(struct ARRAY_T), 1);
49   this->index  = -1;
50   this->length =  0;
51   this->free   = NULL;
52   return this;
53 }
54 
55 ARRAY
array_destroy(ARRAY this)56 array_destroy(ARRAY this)
57 {
58   int i;
59 
60   if (this == NULL) return NULL;
61 
62   if (this->free == NULL) {
63     this->free = free;
64   }
65 
66   for (i = 0; i < this->length; i++) {
67     this->free(this->data[i]);
68   }
69   xfree(this->data);
70   xfree(this);
71   this = NULL;
72   return this;
73 }
74 
75 ARRAY
array_destroyer(ARRAY this,method m)76 array_destroyer(ARRAY this, method m)
77 {
78   this->free = m;
79   return array_destroy(this);
80 }
81 
82 void
array_set_destroyer(ARRAY this,method m)83 array_set_destroyer(ARRAY this, method m)
84 {
85   this->free = m;
86 }
87 
88 
89 void
array_push(ARRAY this,void * thing)90 array_push(ARRAY this, void *thing)
91 {
92   int len = 0;
93 
94   if (thing==NULL) return;
95 
96   len = strlen(thing)+1;
97   array_npush(this, (void*)thing, len);
98   return;
99 }
100 
101 void
array_npush(ARRAY this,void * thing,size_t len)102 array_npush(ARRAY this, void *thing, size_t len)
103 {
104   array arr;
105   if (thing==NULL) return;
106   if (this->data == NULL && this->length == 0) {
107     this->data = xmalloc(sizeof(array));
108   } else {
109     this->data = realloc(this->data,(this->length+1)*sizeof(array));
110   }
111   arr = xmalloc(len+1);
112   memset(arr, '\0', len+1);
113   memcpy(arr, thing, len);
114   this->data[this->length] = arr;
115   this->length += 1;
116   return;
117 }
118 
119 void *
array_get(ARRAY this,int index)120 array_get(ARRAY this, int index)
121 {
122   if (index > this->length) return NULL;
123 
124   return this->data[index];
125 }
126 
127 void *
array_remove(ARRAY this,int index)128 array_remove (ARRAY this, int index) {
129   int   length = 0;
130   array arr;
131 
132   if (index > this->length) return NULL;
133 
134   arr    = this->data[index];
135   length = --this->length;
136 
137   for (; index < length; index++) {
138     this->data[index] = this->data[index+1];
139   }
140 
141   return arr;
142 }
143 
144 void *
array_pop(ARRAY this)145 array_pop(ARRAY this)
146 {
147   if (this == NULL) return NULL;
148   return this->length ? this->data[--this->length] : NULL;
149 }
150 
151 void *
array_next(ARRAY this)152 array_next(ARRAY this)
153 {
154   this->index++;
155   return this->data[(this->index) % this->length];
156 }
157 
158 void *
array_prev(ARRAY this)159 array_prev(ARRAY this)
160 {
161   this->index--;
162   return this->data[((this->index) + (this->length - 1)) % this->length] ;
163 }
164 
165 size_t
array_length(ARRAY this)166 array_length(ARRAY this)
167 {
168   return this->length;
169 }
170 
171 char *
array_to_string(ARRAY this)172 array_to_string(ARRAY this)
173 {
174   size_t i;
175   int    len = 0;
176   char  *str;
177 
178   if (this->length == 0) return "NULL";
179 
180   for (i = 0; i < array_length(this); i++) {
181     len += strlen(array_get(this, i))+3;
182   }
183   str = (char*)malloc(len+1);
184   memset(str, '\0', len+1);
185 
186   for (i = 0; i < array_length(this); i++) {
187     strcat(str, "[");
188     strcat(str, array_get(this, i));
189     if (i == array_length(this) - 1) {
190       strcat(str, "]");
191     } else {
192       strcat(str, "],");
193     }
194   }
195   return str;
196 }
197 
198 void
array_print(ARRAY this)199 array_print(ARRAY this)
200 {
201   printf("%s\n", array_to_string(this));
202 }
203 
204 
205 #if 0
206 #include <unistd.h>
207 int
208 main (int argc, char *argv[])
209 {
210   int   x;
211   int   i;
212   int   len;
213   ARRAY A = new_array();
214   void *v;
215 for (i = 0; i < 1000000; i++) {
216   array_push(A, "Zero");
217   array_push(A, "One");
218   array_push(A, "Two");
219   array_push(A, "Three");
220   array_push(A, "Four");
221   array_push(A, "Five");
222   array_push(A, "Six-six-six");
223 
224   while ((v = array_pop(A)) != NULL) {
225     printf("popped: %s\n", (char*)v);
226     xfree(v);
227   }
228 
229 }
230   A = array_destroy(A);
231   return 0;
232 }
233 #endif
234 
235 
236