Mercurial > repos > rhope
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 } |