2 Copyright © 1995-2004, The AROS Development Team. All rights reserved.
5 Basic help functions needed by iffparse.
9 #include <aros/debug.h>
10 #include "iffparse_intern.h"
14 struct IFFHandle
*iff
,
19 struct IFFParseBase_intern
*IFFParseBase
22 /* Allocates and puts a new context-node into the top of the context-stack
23 Also does GoodType and GoodID checking */
24 struct ContextNode
*cn
;
27 D(bug("PushContextNode(iff=%p, type=%c%c%c%c, id=%c%c%c%c, size=%d, scan=%d)\n",
35 /* Set the composite flag if we have a composite contextnnode */
36 if (id
== ID_FORM
|| id
== ID_LIST
|| id
== ID_CAT
|| id
== ID_PROP
)
39 /* We have a new type, check it */
44 /* No composite type found. Get old type from top contextnode */
49 /* Check if type and ids are valid */
50 if (!(GoodType(type
) && GoodID(id
)) )
51 ReturnInt ("PushContextNode",LONG
,IFFERR_MANGLED
);
53 /* Allocate a new context node */
54 if ( !(cn
= AllocMem ( sizeof (struct IntContextNode
), MEMF_ANY
) ) )
55 ReturnInt ("PushContextNode",LONG
,IFFERR_NOMEM
);
57 /* Put the context node at top of the stack */
58 AddHead ( (struct List
*)&( GetIntIH(iff
)->iff_CNStack
), (struct Node
*)cn
);
60 /* Set the contextnode attrs */
66 GetIntCN(cn
)->cn_Composite
= composite
;
67 /* Initialize the LCI-list */
68 NewList ((struct List
*)&( GetIntCN(cn
)->cn_LCIList
));
73 ReturnInt ("PushContextNode",LONG
,0L);
76 VOID
PopContextNode(struct IFFHandle
* iff
,
77 struct IFFParseBase_intern
*IFFParseBase
)
79 struct LocalContextItem
*node
,
82 struct IntContextNode
*cn
;
84 D(bug("PopContextNode(iff=%p)\n", iff
));
86 cn
= GetIntCN( TopChunk( iff
) );
90 D(bug("(%c%c%c%c, %c%c%c%c)\n",
91 dmkid(cn
->CN
.cn_Type
),
100 /* Free all localcontextitems */
101 node
= (struct LocalContextItem
*)cn
->cn_LCIList
.mlh_Head
;
103 while ((nextnode
= (struct LocalContextItem
*)node
->lci_Node
.mln_Succ
))
105 PurgeLCI((struct LocalContextItem
*)node
, IFFParseBase
);
110 /* Free the contextnode itself */
111 Remove((struct Node
*)cn
);
112 FreeMem(cn
,sizeof (struct IntContextNode
));
114 /*One less node on stack */
118 LONG
ReadStreamLong (struct IFFHandle
*iff
,
120 struct IFFParseBase_intern
*IFFParseBase
)
124 # define bytes valptr
129 D(bug("ReadStreamLong(iff=%p valptr=%p)\n", iff
, valptr
));
131 val
= ReadStream (iff
, bytes
, sizeof(LONG
), IFFParseBase
);
133 D(bug("ReadStreamLong: val %ld\n", val
));
137 else if (val
!= sizeof(LONG
))
141 *(LONG
*)valptr
= bytes
[0] << 24 | bytes
[1] << 16 | bytes
[2] << 8 | bytes
[3];
144 D(bug("ReadStreamLong: *valptr 0x%08lx '%c%c%c%c'\n", *(LONG
*) valptr
, dmkid(*(LONG
*) valptr
)));
147 } /* ReadStreamLong */
150 LONG
WriteStreamLong (struct IFFHandle
*iff
,
152 struct IFFParseBase_intern
*IFFParseBase
)
156 # define bytes valptr
159 val
= *(LONG
*)valptr
;
161 bytes
[0] = val
>> 24;
162 bytes
[1] = val
>> 16;
167 D(bug("WriteStreamLong(iff=%p valptr=%p)\n", iff
, valptr
));
169 val
= WriteStream (iff
, bytes
, sizeof(LONG
), IFFParseBase
);
171 D(bug("WriteStreamLong: val %ld\n", val
));
175 else if (val
!= sizeof(LONG
))
179 } /* WriteStreamLong */
181 /********************/
183 /********************/
185 LONG
GetChunkHeader(struct IFFHandle
*iff
,
186 struct IFFParseBase_intern
*IFFParseBase
)
194 D(bug("GetChunkHeader (iff=%p)\n", iff
));
196 /* Reads in the appropriate stuff from a chunk and makes a contextnode of it */
199 bytesread
= ReadStreamLong ( iff
, &id
, IFFParseBase
);
201 /* We may have an IFF Error */
203 ReturnInt ("GetChunkHeader",LONG
,bytesread
);
205 /* Read chunk size */
206 bytesread
= ReadStreamLong ( iff
, &size
, IFFParseBase
);
209 ReturnInt ("GetChunkHeader",LONG
,bytesread
);
211 /* We must see if we have a IFF header ("FORM", "CAT" or "LIST" */
212 if ( id
== ID_FORM
|| id
== ID_CAT
|| id
== ID_LIST
|| id
== ID_PROP
)
214 /* Read chunk size */
215 bytesread
= ReadStreamLong ( iff
, &type
, IFFParseBase
);
218 ReturnInt ("GetChunkHeader",LONG
,bytesread
);
220 DB2(bug(" Found Chunk %c%c%c%c size=%d type %c%c%c%c\n",
226 /* Type is inside chunk so we had to add its size to the scancount. */
227 scan
= sizeof (LONG
);
232 DB2(bug(" Found Chunk %c%c%c%c size=%d\n",
254 /********************/
256 /********************/
258 LONG
InvokeHandlers(struct IFFHandle
*iff
, LONG mode
, LONG ident
,
259 struct IFFParseBase_intern
*IFFParseBase
)
261 struct ContextNode
*cn
;
262 struct HandlerInfo
*hi
;
263 struct LocalContextItem
*lci
;
266 /* Either RETURN_2CLIENT or IFFERR_EOC */
267 LONG stepping_retval
;
270 D(bug("InvokeHandlers (Iff=%p, mode=%d, ident=0x%08lx\n",
274 if (ident
== IFFLCI_ENTRYHANDLER
)
275 stepping_retval
= IFF_RETURN2CLIENT
;
277 stepping_retval
= IFFERR_EOC
;
279 /* Check for IFFPARSE_RAWSTEP *before* calling evt entryhandlers */
280 if (mode
== IFFPARSE_RAWSTEP
)
281 ReturnInt ("InvokeHandlers(1)",LONG
,stepping_retval
);
283 /* Get top of contextstack */
286 /* Scan downwards to find a contextnode with a matching LCI */
287 lci
= FindLocalItem ( iff
, cn
->cn_Type
, cn
->cn_ID
, ident
);
291 /* Get the HandlerInfo userdata */
292 hi
= LocalItemData(lci
);
295 /* First check if a hook really is present */
297 ReturnInt ("InvokeHandlers",LONG
,IFFERR_NOHOOK
);
299 /* What kind off command shall the hook receive */
301 if (ident
== IFFLCI_ENTRYHANDLER
)
302 param
= IFFCMD_ENTRY
;
307 /* Call the handler */
308 if ( (err
= CallHookPkt ( hi
->hi_Hook
, hi
->hi_Object
, (APTR
)param
)) )
309 ReturnInt ("InvokeHandlers(2)",LONG
,err
);
312 /* Check for IFFPARSE_STEP. (stepping through file WITH handlers enabled */
313 if (mode
== IFFPARSE_STEP
)
314 ReturnInt ("InvokeHandlers(3)",LONG
,stepping_retval
);
316 ReturnInt ("InvokeHandlers",LONG
,0L);
323 VOID
PurgeLCI(struct LocalContextItem
*lci
,
324 struct IFFParseBase_intern
*IFFParseBase
)
326 /* Look in the RKM SetLocalItemPurge autodoc for explanation on that one below */
328 D(bug("PurgeLCI(lci=%p)\n", lci
));
330 Remove((struct Node
*)lci
);
331 /* Has the user specified a Purge hook ? */
333 if ( GetIntLCI(lci
)->lci_PurgeHook
)
336 GetIntLCI(lci
)->lci_PurgeHook
,
338 (APTR
)IFFCMD_PURGELCI
351 /* Reads from the current StreamHandler */
353 /* returns one of the standard IFF errors */
354 LONG
ReadStream(struct IFFHandle
*iff
, APTR buf
, LONG bytestoread
,
355 struct IFFParseBase_intern
*IFFParseBase
)
360 /* For use with custom streams */
361 struct IFFStreamCmd cmd
;
363 D(bug("ReadStream(iff=%p buf=%p bytestoread=%d)\n", iff
, buf
, bytestoread
));
365 retval
= bytestoread
;
368 /* Now we can do the actual reading of the stream */
369 cmd
.sc_Command
= IFFCMD_READ
;
371 cmd
.sc_NBytes
= bytestoread
;
375 GetIntIH(iff
)->iff_StreamHandler
,
381 retval
= IFFERR_READ
;
384 D(bug("ReadStream: return %d\n", retval
));
393 LONG
WriteStream(struct IFFHandle
*iff
, APTR buf
, LONG bytestowrite
,
394 struct IFFParseBase_intern
*IFFParseBase
)
399 struct IFFStreamCmd cmd
;
401 /* Call the custom hook with a write command */
403 D(bug("WriteStream(iff=%p buf=%p bytestowrite=%d)\n", iff
, buf
, bytestowrite
));
405 retval
= bytestowrite
;
409 cmd
.sc_Command
= IFFCMD_WRITE
;
411 cmd
.sc_NBytes
= bytestowrite
;
415 GetIntIH(iff
)->iff_StreamHandler
,
421 retval
= IFFERR_WRITE
;
424 D(bug("WriteStream: return %d\n", retval
));
431 LONG
SeekStream(struct IFFHandle
*iff
,LONG offset
,
432 struct IFFParseBase_intern
*IFFParseBase
)
435 /* Some different problem - situations:
437 1. Backwards seek in non back seekable stream. In this case the stream is buffered,
438 and we may seek in the buffer. This is done automagically, since PushChunk
439 then has inserted a Buffering streamhandle.
442 2. Forwards seek in a non - seekable stream. Simulate the seek with a bunch
447 struct IFFStreamCmd cmd
;
453 D(bug("SeekStream(iff=%p offset=%d)\n", iff
, offset
));
455 flags
= iff
->iff_Flags
;
472 /* We should use consecutive ReadStream()s to simulate a Seek */
474 /* Allocate a buffer to use with the read */
475 seekbuf
= AllocMem(SEEKBUFSIZE
, MEMF_ANY
);
478 retval
= IFFERR_NOMEM
;
482 for (; offset
> SEEKBUFSIZE
; offset
-= SEEKBUFSIZE
)
484 retval
= ReadStream(iff
, seekbuf
, SEEKBUFSIZE
, IFFParseBase
);
486 if (retval
!= SEEKBUFSIZE
)
487 retval
= IFFERR_SEEK
;
490 /* Seek what is left of offset */
491 retval
= ReadStream(iff
, seekbuf
, SEEKBUFSIZE
, IFFParseBase
);
492 if ( retval
!= SEEKBUFSIZE
)
493 retval
= IFFERR_SEEK
;
495 FreeMem(seekbuf
, SEEKBUFSIZE
);
499 else if (offset
== 0)
506 /* Everything is just fine... Seek in a normal manner */
508 cmd
.sc_Command
= IFFCMD_SEEK
;
509 cmd
.sc_NBytes
= offset
;
513 GetIntIH(iff
)->iff_StreamHandler
,
519 retval
= IFFERR_SEEK
;
522 D(bug("SeekStream: return %d\n", retval
));
527 /********************/
528 /* Buffering stuff */
529 /********************/