Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / libs / muimaster / classes / dataspace.c
blobba713a3c37cc4a7798996ef8e8eec4cbdc2a0cb6
1 /*
2 Copyright © 2002-2006, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <stdlib.h>
7 #include <string.h>
9 #include <exec/types.h>
10 #include <clib/alib_protos.h>
11 #include <proto/exec.h>
12 #include <proto/intuition.h>
13 #include <proto/utility.h>
14 #include <proto/iffparse.h>
15 #include <proto/muimaster.h>
17 #include "muimaster_intern.h"
18 #include "mui.h"
19 #include "support.h"
21 extern struct Library *MUIMasterBase;
23 struct Dataspace_Node
25 struct MinNode node;
26 ULONG id;
27 ULONG len;
28 /* len bytes data follows */
31 struct MUI_DataspaceData
33 /* We store this as a linear list, but it has O(n) when looking
34 ** for an entry which is bad, because the is the most fequently used
35 ** operation.
37 struct MinList list;
38 APTR pool;
39 APTR pool_allocated;
40 APTR current_pool;
43 IPTR Dataspace__OM_NEW (struct IClass *cl, Object *obj, struct opSet *msg)
45 struct MUI_DataspaceData *data;
46 struct TagItem *tags,*tag;
48 obj = (Object *)DoSuperMethodA(cl, obj, (Msg)msg);
49 if (!obj)
50 return FALSE;
52 data = INST_DATA(cl, obj);
54 for (tags = msg->ops_AttrList; (tag = NextTagItem((const struct TagItem**)&tags)); )
56 switch (tag->ti_Tag)
58 case MUIA_Dataspace_Pool:
59 data->pool = (APTR)tag->ti_Data;
60 break;
64 NewList((struct List*)&data->list);
66 if (!data->pool)
68 if (!(data->pool_allocated = CreatePool(0,4096,4096)))
70 CoerceMethod(cl,obj,OM_DISPOSE);
71 return (IPTR)NULL;
73 data->current_pool = data->pool_allocated;
75 else
77 data->current_pool = data->pool;
80 return (IPTR)obj;
84 IPTR Dataspace__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
86 struct MUI_DataspaceData *data = INST_DATA(cl, obj);
87 if (data->pool_allocated) DeletePool(data->pool_allocated);
88 else CoerceMethod(cl,obj,MUIM_Dataspace_Clear);
89 return DoSuperMethodA(cl, obj, msg);
92 IPTR Dataspace__MUIM_Add(struct IClass *cl, Object *obj, struct MUIP_Dataspace_Add *msg)
94 struct MUI_DataspaceData *data = INST_DATA(cl, obj);
95 struct Dataspace_Node *replace;
96 struct Dataspace_Node *node;
98 if (NULL == msg->data || msg->len < 1 || msg->id < 1)
99 return 0;
101 node = (struct Dataspace_Node*)AllocVecPooled(data->current_pool,
102 sizeof(struct Dataspace_Node)+msg->len);
103 if (NULL == node)
105 return 0;
108 replace = List_First(&data->list);
109 while (replace)
111 if (replace->id == msg->id)
113 Remove((struct Node*)replace);
114 FreeVecPooled(data->current_pool, replace);
115 break;
117 replace = Node_Next(replace);
120 AddTail((struct List*)&data->list,(struct Node*)node);
121 node->id = msg->id;
122 node->len = msg->len;
123 CopyMem(msg->data, node + 1, node->len);
124 return 1;
127 IPTR Dataspace__MUIM_Clear(struct IClass *cl, Object *obj, struct MUIP_Dataspace_Clear *msg)
129 struct MUI_DataspaceData *data = INST_DATA(cl, obj);
130 struct Dataspace_Node *node;
132 node = List_First(&data->list);
133 while (node)
135 struct Dataspace_Node *tmp = node;
136 node = Node_Next(node);
138 FreeVecPooled(data->current_pool, tmp);
141 return 1;
144 IPTR Dataspace__MUIM_Find(struct IClass *cl, Object *obj, struct MUIP_Dataspace_Find *msg)
146 struct MUI_DataspaceData *data = INST_DATA(cl, obj);
147 struct Dataspace_Node *find;
149 find = List_First(&data->list);
150 while (find)
152 if (find->id == msg->id)
154 return (IPTR)(find + 1);
156 find = Node_Next(find);
159 return (IPTR)NULL;
162 IPTR Dataspace__MUIM_Merge(struct IClass *cl, Object *obj, struct MUIP_Dataspace_Merge *msg)
164 return 1;
167 IPTR Dataspace__MUIM_Remove(struct IClass *cl, Object *obj, struct MUIP_Dataspace_Remove *msg)
169 struct MUI_DataspaceData *data = INST_DATA(cl, obj);
170 struct Dataspace_Node *node;
172 node = List_First(&data->list);
173 while (node)
175 if (node->id == msg->id)
177 Remove((struct Node*)node);
178 FreeVecPooled(data->current_pool, node);
179 return 1;
181 node = Node_Next(node);
184 return 0;
187 IPTR Dataspace__MUIM_ReadIFF(struct IClass *cl, Object *obj, struct MUIP_Dataspace_ReadIFF *msg)
189 struct ContextNode *cn;
190 UBYTE *buffer, *p;
191 LONG read;
193 LONG len;
194 ULONG id;
196 cn = CurrentChunk(msg->handle);
197 if (!cn)
199 return IFFERR_EOF;
201 if (!(buffer = AllocVec(cn->cn_Size,0)))
203 return IFFERR_NOMEM;
205 read = ReadChunkBytes(msg->handle,buffer,cn->cn_Size);
206 if (read < 0)
208 FreeVec(buffer);
209 return read;
212 p = buffer;
214 while (p < buffer + read)
216 /* Since data can be stored on uneven addresses we must read
217 ** them byte by byte as MC68000 doesn't like this
219 id = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
220 p+=4;
221 len = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
222 p+=4;
224 /* p might be uneven but MUIM_Dataspace_Add use CopyMem() */
226 /* Now add the data */
227 DoMethod(obj, MUIM_Dataspace_Add, (IPTR)p, len, id);
228 p += len;
230 FreeVec(buffer);
231 return 0;
234 IPTR Dataspace__MUIM_WriteIFF(struct IClass *cl, Object *obj, struct MUIP_Dataspace_WriteIFF *msg)
236 struct MUI_DataspaceData *data = INST_DATA(cl, obj);
237 struct Dataspace_Node *iter;
238 LONG rc;
240 if ((rc = PushChunk(msg->handle,msg->type,msg->id,IFFSIZE_UNKNOWN))) return rc;
242 iter = List_First(&data->list);
243 while (iter)
245 ULONG len = iter->len+8;
246 /* Data is stored in big-endian whatever your machine.
247 * Be sure sure to convert data to big endian.
249 iter->id = AROS_LONG2BE(iter->id);
250 iter->len = AROS_LONG2BE(iter->len);
251 rc = WriteChunkBytes(msg->handle, &iter->id, len); /* ID - LEN - DATA */
252 iter->id = AROS_LONG2BE(iter->id);
253 iter->len = AROS_LONG2BE(iter->len);
254 if (rc < 0)
256 return rc;
258 iter = Node_Next(iter);
260 if ((rc = PopChunk(msg->handle))) return rc;
261 return 0;
265 BOOPSI_DISPATCHER(IPTR, Dataspace_Dispatcher, cl, obj, msg)
267 IPTR res;
269 switch (msg->MethodID)
271 /* Whenever an object shall be created using NewObject(), it will be
272 ** sent a OM_NEW method.
274 case OM_NEW: return Dataspace__OM_NEW(cl, obj, (struct opSet *) msg);
275 case OM_DISPOSE: return Dataspace__OM_DISPOSE(cl, obj, msg);
276 case MUIM_Dataspace_Add:
277 DoMethod(obj, MUIM_Semaphore_Obtain);
278 res = Dataspace__MUIM_Add(cl, obj, (APTR)msg);
279 DoMethod(obj, MUIM_Semaphore_Release);
280 return res;
281 case MUIM_Dataspace_Clear:
282 DoMethod(obj, MUIM_Semaphore_Obtain);
283 res = Dataspace__MUIM_Clear(cl, obj, (APTR)msg);
284 DoMethod(obj, MUIM_Semaphore_Release);
285 return res;
286 case MUIM_Dataspace_Find:
287 DoMethod(obj, MUIM_Semaphore_ObtainShared);
288 res = Dataspace__MUIM_Find(cl, obj, (APTR)msg);
289 DoMethod(obj, MUIM_Semaphore_Release);
290 /* now that sem is released, imagine that the object gets freed ...
291 * it really needs that the caller locks the object,
292 * and release it when done with the result
294 return res;
295 case MUIM_Dataspace_Merge:
296 DoMethod(obj, MUIM_Semaphore_Obtain);
297 res = Dataspace__MUIM_Merge(cl, obj, (APTR)msg);
298 DoMethod(obj, MUIM_Semaphore_Release);
299 return res;
300 case MUIM_Dataspace_Remove:
301 DoMethod(obj, MUIM_Semaphore_Obtain);
302 res = Dataspace__MUIM_Remove(cl, obj, (APTR)msg);
303 DoMethod(obj, MUIM_Semaphore_Release);
304 return res;
305 case MUIM_Dataspace_ReadIFF:
306 DoMethod(obj, MUIM_Semaphore_Obtain);
307 res = (IPTR)Dataspace__MUIM_ReadIFF(cl, obj, (APTR)msg);
308 DoMethod(obj, MUIM_Semaphore_Release);
309 return res;
310 case MUIM_Dataspace_WriteIFF:
311 DoMethod(obj, MUIM_Semaphore_Obtain);
312 res = (IPTR)Dataspace__MUIM_WriteIFF(cl, obj, (APTR)msg);
313 DoMethod(obj, MUIM_Semaphore_Release);
314 return res;
317 return DoSuperMethodA(cl, obj, msg);
319 BOOPSI_DISPATCHER_END
322 * Class descriptor.
324 const struct __MUIBuiltinClass _MUI_Dataspace_desc = {
325 MUIC_Dataspace, /* Class name */
326 MUIC_Semaphore, /* super class name */
327 sizeof(struct MUI_DataspaceData), /* size of class own datas */
328 (void*)Dataspace_Dispatcher /* class dispatcher */