comparison list.c @ 0:76568becd6d6

Rhope Alpha 2a source import
author Mike Pavone <pavone@retrodev.com>
date Tue, 28 Apr 2009 23:06:07 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:76568becd6d6
1 #include "structs.h"
2 #include "datum.h"
3 #include "interp.h"
4 #include <stdlib.h>
5 #include <string.h>
6
7 datum * create_list(program * prog)
8 {
9 short i;
10 datum * dat = new_datum(BUILTIN_TYPE_LIST, 1, sizeof(list_data) + sizeof(datum *)*7, prog);
11 dat->c.generic.len = 8;
12 ((list_data *)dat->c.generic.data)->num_entries = 0;
13 return dat;
14 }
15
16 int vis_list_new(datum ** inputlist, queue_entry * worker_entry)
17 {
18 inputlist[0] = create_list(worker_entry->instance->def->program);
19 return 0;
20 }
21
22 int vis_list_append(datum ** inputlist, queue_entry * worker_entry)
23 {
24 int ref_count, new_entry_count;
25 list_data * list, * new_list;
26 datum * output;
27 int i;
28
29 VIS_EnterCriticalSection(inputlist[0]->lock);
30 ref_count = inputlist[0]->ref_count;
31 VIS_LeaveCriticalSection(inputlist[0]->lock);
32 list = ((list_data *)inputlist[0]->c.generic.data);
33 DEBUGPRINTF("append: generic.len = %d, list->num_entries = %d, ref_count = %d\n", inputlist[0]->c.generic.len, list->num_entries, ref_count);
34 if(ref_count == 1)
35 {
36 if(inputlist[0]->c.generic.len > list->num_entries)
37 {
38 DEBUGPUTS("Fast append\n");
39 list->entries[list->num_entries] = inputlist[1]; //No need to add_ref because we're consuming the ref we wer passed
40 ++(list->num_entries);
41 }
42 else
43 {
44 DEBUGPUTS("malloc append\n");
45 new_entry_count = list->num_entries + (list->num_entries > 1);//grow by half current size
46 new_list = malloc((new_entry_count -1) * sizeof(datum *) + sizeof(list_data));
47 new_list->num_entries = list->num_entries+1;
48 inputlist[0]->c.generic.len = new_entry_count;
49 memcpy(new_list->entries, list->entries, list->num_entries * sizeof(datum *));
50 new_list->entries[list->num_entries] = inputlist[1];
51 inputlist[0]->c.generic.data = new_list;
52 VIS_FREE(list, "List object");
53 }
54 }
55 else
56 {
57 DEBUGPUTS("datum copy append\n");
58
59 if(inputlist[0]->c.generic.len > list->num_entries)
60 new_entry_count = inputlist[0]->c.generic.len;
61 else
62 new_entry_count = list->num_entries + (list->num_entries > 1);//grow by half current size
63 output = new_datum_comp(inputlist[0]->company, 1, (new_entry_count -1) * sizeof(datum *) + sizeof(list_data));
64 new_list = output->c.generic.data;
65 new_list->num_entries = list->num_entries+1;
66 output->c.generic.len = new_entry_count;
67 for(i = 0; i < list->num_entries; ++i)
68 new_list->entries[i] = add_ref(list->entries[i]);
69 new_list->entries[list->num_entries] = inputlist[1];
70 release_ref(inputlist[0]);
71 inputlist[0] = output;
72 }
73 DEBUGPRINTF("append: generic.len = %d, list->num_entries = %d\n", inputlist[0]->c.generic.len, ((list_data *)inputlist[0]->c.generic.data)->num_entries);
74 return 0;
75 }
76
77 int vis_list_swap(datum ** inputlist, queue_entry * worker_entry)
78 {
79 //TODO: Throw error if indices out of bounds
80 list_data * list;
81 datum * temp;
82 inputlist[0] = copy_datum(inputlist[0], 0);
83 list = ((list_data *)inputlist[0]->c.generic.data);
84
85 temp = list->entries[inputlist[1]->c.integers.num_a];
86 list->entries[inputlist[1]->c.integers.num_a] = list->entries[inputlist[2]->c.integers.num_a];
87 list->entries[inputlist[2]->c.integers.num_a] = temp;
88 release_ref(inputlist[1]);
89 release_ref(inputlist[2]);
90 return 0;
91 }
92
93 int vis_list_index(datum ** inputlist, queue_entry * worker_entry)
94 {
95 //TODO: Throw error if indices out of bounds
96 list_data * list = ((list_data *)inputlist[0]->c.generic.data);
97 datum * output;
98 DEBUGPRINTF("index: generic.len = %d, list->num_entries = %d, requested index: %d\n", inputlist[0]->c.generic.len, list->num_entries, inputlist[1]->c.integers.num_a);
99 DEBUGPRINTF("list->entries[%d] = %X\n", inputlist[1]->c.integers.num_a, list->entries[inputlist[1]->c.integers.num_a]);
100 if(inputlist[1]->c.integers.num_a < list->num_entries && list->entries[inputlist[1]->c.integers.num_a])
101 {
102 output = add_ref(list->entries[inputlist[1]->c.integers.num_a]);
103 release_ref(inputlist[1]);
104 inputlist[1] = NULL;
105 }
106 else
107 {
108 output = NULL;
109 inputlist[1] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program);
110 inputlist[1]->c.integers.num_a = 0;
111 }
112
113 release_ref(inputlist[0]);
114 inputlist[0] = output;
115 return 0;
116 }
117
118 int vis_list_insert(datum ** inputlist, queue_entry * worker_entry)
119 {
120 int ref_count, new_entry_count;
121 list_data * list, * new_list;
122 datum * output;
123 int i;
124 VIS_EnterCriticalSection(inputlist[0]->lock);
125 ref_count = inputlist[0]->ref_count;
126 VIS_LeaveCriticalSection(inputlist[0]->lock);
127 list = ((list_data *)inputlist[0]->c.generic.data);
128 if(ref_count == 1)
129 {
130 if(inputlist[0]->c.generic.len > list->num_entries)
131 {
132 memmove(list->entries + inputlist[1]->c.integers.num_a + 1, list->entries + inputlist[1]->c.integers.num_a, sizeof(datum *) * (list->num_entries-inputlist[1]->c.integers.num_a));
133 list->entries[inputlist[1]->c.integers.num_a] = inputlist[2]; //No need to add_ref because we're consuming the ref we wer passed
134 ++(list->num_entries);
135 }
136 else
137 {
138 new_entry_count = list->num_entries + (list->num_entries > 1);//grow by half current size
139 new_list = malloc((new_entry_count -1) * sizeof(datum *) + sizeof(list_data));
140 new_list->num_entries = list->num_entries+1;
141 inputlist[0]->c.generic.len = new_entry_count;
142 memcpy(new_list->entries, list->entries, list->num_entries * sizeof(datum *));
143 new_list->entries[list->num_entries] = inputlist[1];
144 inputlist[0]->c.generic.data = new_list;
145 VIS_FREE(list, "List object");
146 }
147 }
148 else
149 {
150 new_entry_count = list->num_entries + (list->num_entries > 1);//grow by half current size
151 output = new_datum_comp(inputlist[0]->company, 1, (new_entry_count -1) * sizeof(datum *) + sizeof(list_data));
152 new_list = output->c.generic.data;
153 new_list->num_entries = list->num_entries+1;
154 output->c.generic.len = new_entry_count;
155 for(i = 0; i < inputlist[1]->c.integers.num_a; ++i)
156 new_list->entries[i] = add_ref(list->entries[i]);
157 for(i = inputlist[1]->c.integers.num_a; i < list->num_entries; ++i)
158 new_list->entries[i+1] = add_ref(list->entries[i]);
159 release_ref(inputlist[0]);
160 new_list->entries[list->num_entries] = inputlist[2];
161 inputlist[0] = output;
162 }
163 release_ref(inputlist[1]);
164 return 0;
165 }
166
167 int vis_list_remove(datum ** inputlist, queue_entry * worker_entry)
168 {
169 int ref_count, new_entry_count;
170 list_data * list, * new_list;
171 int i;
172 datum * output;
173 VIS_EnterCriticalSection(inputlist[0]->lock);
174 ref_count = inputlist[0]->ref_count;
175 VIS_LeaveCriticalSection(inputlist[0]->lock);
176 list = ((list_data *)inputlist[0]->c.generic.data);
177 if(ref_count == 1)
178 {
179 release_ref(list->entries[inputlist[1]->c.integers.num_a]);
180 memmove(list->entries + inputlist[1]->c.integers.num_a, list->entries + inputlist[1]->c.integers.num_a + 1, sizeof(datum *) * (list->num_entries-(inputlist[1]->c.integers.num_a+1)));
181 --(list->num_entries);
182 }
183 else
184 {
185 new_entry_count = list->num_entries + (list->num_entries > 1);//grow by half current size
186 output = new_datum_comp(inputlist[0]->company, 1, (new_entry_count -1) * sizeof(datum *) + sizeof(list_data));
187 new_list = output->c.generic.data;
188 new_list->num_entries = list->num_entries+1;
189 output->c.generic.len = new_entry_count;
190 for(i = 0; i < inputlist[1]->c.integers.num_a; ++i)
191 new_list->entries[i] = add_ref(list->entries[i]);
192 for(i = inputlist[1]->c.integers.num_a+1; i < list->num_entries; ++i)
193 new_list->entries[i-1] = add_ref(list->entries[i]);
194 release_ref(inputlist[0]);
195 inputlist[0] = output;
196 }
197 release_ref(inputlist[1]);
198 return 0;
199 }
200
201 int vis_list_set(datum ** inputlist, queue_entry * worker_entry)
202 {
203 int new_num_entries, new_generic_len, i;
204 list_data * list;
205 DEBUGPUTS("vis_list_set\n");
206 if(((list_data *)inputlist[0]->c.generic.data)->num_entries <= inputlist[1]->c.integers.num_a)
207 {
208 new_num_entries = inputlist[1]->c.integers.num_a + 1;
209 new_generic_len = (new_num_entries + (new_num_entries>>1)-1)*sizeof(datum*) + sizeof(list_data);
210 }
211 else
212 {
213 new_num_entries = ((list_data *)inputlist[0]->c.generic.data)->num_entries;
214 new_generic_len = 0;
215 }
216 DEBUGPRINTF("new_generic_len: %d, new num_entries: %d\n", new_generic_len, new_num_entries);
217 inputlist[0] = copy_datum(inputlist[0], new_generic_len);
218 if(new_generic_len) {
219 inputlist[0]->c.generic.len = (new_num_entries + (new_num_entries>>1));
220 }
221 DEBUGPUTS("Datum copy done\n");
222 list = ((list_data *)inputlist[0]->c.generic.data);
223 DEBUGPUTS("before Null fill loop\n");
224 for(i = list->num_entries; i < new_num_entries; ++i)
225 list->entries[i] = NULL;
226 DEBUGPUTS("Before existing entry release_ref\n");
227 if(inputlist[1]->c.integers.num_a < list->num_entries)
228 release_ref(list->entries[inputlist[1]->c.integers.num_a]);
229 DEBUGPRINTF("Setting index %d to %X\n", inputlist[1]->c.integers.num_a, inputlist[2]);
230 list->entries[inputlist[1]->c.integers.num_a] = inputlist[2];
231 release_ref(inputlist[1]);
232 list->num_entries = new_num_entries;
233 DEBUGPUTS("vis_list_set done\n");
234 return 0;
235
236 }
237
238 int vis_list_length(datum ** inputlist, queue_entry * worker_entry)
239 {
240 datum * output;
241 list_data * list = ((list_data *)inputlist[0]->c.generic.data);
242 output = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
243 output->c.integers.num_a = list->num_entries;
244 release_ref(inputlist[0]);
245 inputlist[0] = output;
246 return 0;
247 }
248
249 int vis_list_first(datum ** inputlist, queue_entry * worker_entry)
250 {
251 int i;
252 list_data * list = inputlist[0]->c.generic.data;
253 if(!list->num_entries)
254 {
255 inputlist[1] = inputlist[0];
256 inputlist[0] = NULL;
257 }
258 else
259 {
260 i = 0;
261 while(!list->entries[i] && i < list->num_entries)
262 ++i;
263 release_ref(inputlist[0]);
264 inputlist[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
265 inputlist[0]->c.integers.num_a = i;
266 inputlist[1] = NULL;
267 }
268 return 0;
269 }
270
271 int vis_list_next(datum ** inputlist, queue_entry * worker_entry)
272 {
273 int i;
274 list_data * list = inputlist[0]->c.generic.data;
275 i = inputlist[1]->c.integers.num_a + 1;
276 while(i < list->num_entries && !list->entries[i])
277 ++i;
278 if(i < list->num_entries)
279 {
280 release_ref(inputlist[0]);
281 inputlist[0] = copy_datum(inputlist[1], 0);
282 inputlist[1] = NULL;
283 inputlist[0]->c.integers.num_a = i;
284 } else {
285 release_ref(inputlist[1]);
286 inputlist[1] = inputlist[0];
287 inputlist[0] = NULL;
288 }
289 return 0;
290 }