Tabs to spaces, more consistent formatting.
[AROS.git] / workbench / libs / muimaster / classes / dataspace.c
blob73c0b6c3d36d8b14b2a8cd407b4b11f243091c8e
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(&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)
88 DeletePool(data->pool_allocated);
89 else
90 CoerceMethod(cl, obj, MUIM_Dataspace_Clear);
91 return DoSuperMethodA(cl, obj, msg);
94 IPTR Dataspace__MUIM_Add(struct IClass *cl, Object *obj,
95 struct MUIP_Dataspace_Add *msg)
97 struct MUI_DataspaceData *data = INST_DATA(cl, obj);
98 struct Dataspace_Node *replace;
99 struct Dataspace_Node *node;
101 if (NULL == msg->data || msg->len < 1 || msg->id < 1)
102 return 0;
104 node = (struct Dataspace_Node *)AllocVecPooled(data->current_pool,
105 sizeof(struct Dataspace_Node) + msg->len);
106 if (NULL == node)
108 return 0;
111 replace = List_First(&data->list);
112 while (replace)
114 if (replace->id == msg->id)
116 Remove((struct Node *)replace);
117 FreeVecPooled(data->current_pool, replace);
118 break;
120 replace = Node_Next(replace);
123 AddTail((struct List *)&data->list, (struct Node *)node);
124 node->id = msg->id;
125 node->len = msg->len;
126 CopyMem(msg->data, node + 1, node->len);
127 return 1;
130 IPTR Dataspace__MUIM_Clear(struct IClass *cl, Object *obj,
131 struct MUIP_Dataspace_Clear *msg)
133 struct MUI_DataspaceData *data = INST_DATA(cl, obj);
134 struct Dataspace_Node *node;
136 node = List_First(&data->list);
137 while (node)
139 struct Dataspace_Node *tmp = node;
140 node = Node_Next(node);
142 FreeVecPooled(data->current_pool, tmp);
145 return 1;
148 IPTR Dataspace__MUIM_Find(struct IClass *cl, Object *obj,
149 struct MUIP_Dataspace_Find *msg)
151 struct MUI_DataspaceData *data = INST_DATA(cl, obj);
152 struct Dataspace_Node *find;
154 find = List_First(&data->list);
155 while (find)
157 if (find->id == msg->id)
159 return (IPTR) (find + 1);
161 find = Node_Next(find);
164 return (IPTR) NULL;
167 IPTR Dataspace__MUIM_Merge(struct IClass *cl, Object *obj,
168 struct MUIP_Dataspace_Merge *msg)
170 return 1;
173 IPTR Dataspace__MUIM_Remove(struct IClass *cl, Object *obj,
174 struct MUIP_Dataspace_Remove *msg)
176 struct MUI_DataspaceData *data = INST_DATA(cl, obj);
177 struct Dataspace_Node *node;
179 node = List_First(&data->list);
180 while (node)
182 if (node->id == msg->id)
184 Remove((struct Node *)node);
185 FreeVecPooled(data->current_pool, node);
186 return 1;
188 node = Node_Next(node);
191 return 0;
194 IPTR Dataspace__MUIM_ReadIFF(struct IClass *cl, Object *obj,
195 struct MUIP_Dataspace_ReadIFF *msg)
197 struct ContextNode *cn;
198 UBYTE *buffer, *p;
199 LONG read;
201 LONG len;
202 ULONG id;
204 cn = CurrentChunk(msg->handle);
205 if (!cn)
207 return IFFERR_EOF;
209 if (!(buffer = AllocVec(cn->cn_Size, 0)))
211 return IFFERR_NOMEM;
213 read = ReadChunkBytes(msg->handle, buffer, cn->cn_Size);
214 if (read < 0)
216 FreeVec(buffer);
217 return read;
220 p = buffer;
222 while (p < buffer + read)
224 /* Since data can be stored on uneven addresses we must read
225 ** them byte by byte as MC68000 doesn't like this
227 id = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
228 p += 4;
229 len = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
230 p += 4;
232 /* p might be uneven but MUIM_Dataspace_Add use CopyMem() */
234 /* Now add the data */
235 DoMethod(obj, MUIM_Dataspace_Add, (IPTR) p, len, id);
236 p += len;
238 FreeVec(buffer);
239 return 0;
242 IPTR Dataspace__MUIM_WriteIFF(struct IClass *cl, Object *obj,
243 struct MUIP_Dataspace_WriteIFF *msg)
245 struct MUI_DataspaceData *data = INST_DATA(cl, obj);
246 struct Dataspace_Node *iter;
247 LONG rc;
249 if ((rc = PushChunk(msg->handle, msg->type, msg->id, IFFSIZE_UNKNOWN)))
250 return rc;
252 iter = List_First(&data->list);
253 while (iter)
255 ULONG len = iter->len + 8;
256 /* Data is stored in big-endian whatever your machine.
257 * Be sure sure to convert data to big endian.
259 iter->id = AROS_LONG2BE(iter->id);
260 iter->len = AROS_LONG2BE(iter->len);
261 rc = WriteChunkBytes(msg->handle, &iter->id, len); /* ID - LEN - DATA */
262 iter->id = AROS_LONG2BE(iter->id);
263 iter->len = AROS_LONG2BE(iter->len);
264 if (rc < 0)
266 return rc;
268 iter = Node_Next(iter);
270 if ((rc = PopChunk(msg->handle)))
271 return rc;
272 return 0;
276 BOOPSI_DISPATCHER(IPTR, Dataspace_Dispatcher, cl, obj, msg)
278 IPTR res;
280 switch (msg->MethodID)
282 /* Whenever an object shall be created using NewObject(), it will be
283 ** sent a OM_NEW method.
285 case OM_NEW:
286 return Dataspace__OM_NEW(cl, obj, (struct opSet *)msg);
287 case OM_DISPOSE:
288 return Dataspace__OM_DISPOSE(cl, obj, msg);
289 case MUIM_Dataspace_Add:
290 DoMethod(obj, MUIM_Semaphore_Obtain);
291 res = Dataspace__MUIM_Add(cl, obj, (APTR) msg);
292 DoMethod(obj, MUIM_Semaphore_Release);
293 return res;
294 case MUIM_Dataspace_Clear:
295 DoMethod(obj, MUIM_Semaphore_Obtain);
296 res = Dataspace__MUIM_Clear(cl, obj, (APTR) msg);
297 DoMethod(obj, MUIM_Semaphore_Release);
298 return res;
299 case MUIM_Dataspace_Find:
300 DoMethod(obj, MUIM_Semaphore_ObtainShared);
301 res = Dataspace__MUIM_Find(cl, obj, (APTR) msg);
302 DoMethod(obj, MUIM_Semaphore_Release);
303 /* now that sem is released, imagine that the object gets freed ...
304 * it really needs that the caller locks the object,
305 * and release it when done with the result
307 return res;
308 case MUIM_Dataspace_Merge:
309 DoMethod(obj, MUIM_Semaphore_Obtain);
310 res = Dataspace__MUIM_Merge(cl, obj, (APTR) msg);
311 DoMethod(obj, MUIM_Semaphore_Release);
312 return res;
313 case MUIM_Dataspace_Remove:
314 DoMethod(obj, MUIM_Semaphore_Obtain);
315 res = Dataspace__MUIM_Remove(cl, obj, (APTR) msg);
316 DoMethod(obj, MUIM_Semaphore_Release);
317 return res;
318 case MUIM_Dataspace_ReadIFF:
319 DoMethod(obj, MUIM_Semaphore_Obtain);
320 res = (IPTR) Dataspace__MUIM_ReadIFF(cl, obj, (APTR) msg);
321 DoMethod(obj, MUIM_Semaphore_Release);
322 return res;
323 case MUIM_Dataspace_WriteIFF:
324 DoMethod(obj, MUIM_Semaphore_Obtain);
325 res = (IPTR) Dataspace__MUIM_WriteIFF(cl, obj, (APTR) msg);
326 DoMethod(obj, MUIM_Semaphore_Release);
327 return res;
330 return DoSuperMethodA(cl, obj, msg);
332 BOOPSI_DISPATCHER_END
335 * Class descriptor.
337 const struct __MUIBuiltinClass _MUI_Dataspace_desc =
339 MUIC_Dataspace, /* Class name */
340 MUIC_Semaphore, /* super class name */
341 sizeof(struct MUI_DataspaceData), /* size of class own datas */
342 (void *) Dataspace_Dispatcher /* class dispatcher */