2 Copyright © 1995-2004, The AROS Development Team. All rights reserved.
6 #include "iffparse_intern.h"
8 /*****************************************************************************
11 #include <proto/iffparse.h>
13 AROS_LH4(LONG
, PushChunk
,
16 AROS_LHA(struct IFFHandle
*, iff
, A0
),
17 AROS_LHA(LONG
, type
, D0
),
18 AROS_LHA(LONG
, id
, D1
),
19 AROS_LHA(LONG
, size
, D2
),
22 struct Library
*, IFFParseBase
, 14, IFFParse
)
25 Pushes a new context node onto the context stack. Usually used in write mode.
26 In write mode the contextnode will be pushed with the given parameters.
27 In Read mode the type, id and size will be read from the installed stream.
28 Note that IFFSIZE_UNKNOW can be given for size in write mode. In that case,
29 the size of will not be known until you do a PopChunk(). PopChunk()
30 will then seek back in the stream and write the correct size.
34 iff - pointer to IFFHandle struct.
35 type - chunk type specifier.
36 id - chunk identifier.
37 size - size of the new chunk. May be IFFSIZE_UNKNOWN.
40 error - 0 if successfull, IFFERR_#? otherwize.
52 We do different things for Read and Write streams (obviosly enough ;->)
54 Write: Write the supplied id, size and evt type into the stream.
56 Read: Get a chunk from disk
59 For Write mode there are som problems with unknown chunk size and
60 non-random-seekable streams:
63 SIZE KNOWN && RSEEK - Just write the whole header.
64 SIZE KNOWN && !RSEEK - Write whole header. No RSEEK does not matter, since
65 we don't have to seek back to write size in PopChunk
67 SIZE UNKNOWN && RSEEK - Write whole header. Write size too, just to seek pass it,
68 even if the size value might be meaningless. We will
69 seek back and insert the correct size later.
71 SIZE UNKNOWN && !RSEEK - Here is where the trouble starts. We can not seek back
72 and insert the correct size later, which means that we MUST
73 buffer the contents of the chunk, and don't write ANYTHING to
74 the stream until we know its size.
76 We preserve the old StreamHandler, and inserts a new one
77 that buffers all writes into memory.
79 *****************************************************************************/
82 AROS_LIBBASE_EXT_DECL(struct Library
*,IFFParseBase
)
90 DEBUG_PUSHCHUNK(dprintf("PushChunk: iff 0x%lx type 0x%08lx (%c%c%c%c) id 0x%08lx (%c%c%c%c) size %d\n",
91 iff
, type
, dmkid(type
), id
, dmkid(id
), size
));
93 if (iff
->iff_Flags
& IFFF_WRITE
)
95 struct ContextNode
*pcn
;
99 if((pcn
= (struct ContextNode
*)CurrentChunk(iff
)) != NULL
)
101 ptype
= pcn
->cn_Type
;
105 if(iff
->iff_Flags
& IFFF_NEWFILE
)
108 iff
->iff_Flags
&= ~IFFF_NEWFILE
;
116 /* do some syntax checks (cyfm: added 2003/03/01 to "fix"/handle some broken apps) */
120 DEBUG_PUSHCHUNK(dprintf("PushChunk: invalid id -> IFFERR_SYNTAX\n"
123 return(IFFERR_SYNTAX
);
126 else if(newfile
== TRUE
)
128 /* check if first chunk is either FORM, LIST or CAT */
130 if( id
!= ID_FORM
&& id
!= ID_LIST
&& id
!= ID_CAT
)
132 DEBUG_PUSHCHUNK(dprintf("PushChunk: invalid first chunk (neither FORM, nor LIST, nor CAT -> IFFERR_NOTIFF\n"
135 return(IFFERR_NOTIFF
);
138 else if(id
== ID_PROP
)
140 /* make sure PROP containing context is a LIST */
142 if(pcn
->cn_ID
!= ID_LIST
)
144 DEBUG_PUSHCHUNK(dprintf("PushChunk: invalid ID in PROP context -> IFFERR_SYNTAX\n"
147 return(IFFERR_SYNTAX
);
150 else if(id
== ID_FORM
|| id
== ID_LIST
|| id
== ID_CAT
|| id
== ID_PROP
)
152 /* check for valid subtype if we found a generic id */
156 DEBUG_PUSHCHUNK(dprintf("PushChunk: invalid type for generic id -> IFFERR_NOTIFF\n"
159 return(IFFERR_NOTIFF
);
164 /* if we found a non generic id, make sure the containing context is at
165 least PROP or FORM */
167 if((pcn
->cn_ID
!= ID_FORM
) && (pcn
->cn_ID
!= ID_PROP
))
169 DEBUG_PUSHCHUNK(dprintf("PushChunk: containing context id 0x%08lx (%c%c%c%c) for generic id is neither PROP nor FORM -> IFFERR_SYNTAX\n"
170 ,pcn
->cn_ID
,dmkid(pcn
->cn_ID
)));
172 return(IFFERR_SYNTAX
);
176 /* we passed the syntax test ! */
178 /* Do we have a problem - situation ? */
179 if ( (size
== IFFSIZE_UNKNOWN
)
180 && (!(iff
->iff_Flags
& IFFF_RSEEK
))
184 /* Initialize the buffering streamhandler */
185 err
= InitBufferedStream(iff
, IPB(IFFParseBase
));
186 if (err
) return (err
);
189 byteswritten
= WriteStreamLong
197 if (byteswritten
< 0) return (byteswritten
);
199 /* The chunk size will be written during PopChunk too, but we write
200 here to seek past it */
202 byteswritten
= WriteStreamLong
209 if (byteswritten
< 0) return (byteswritten
);
211 /* If a composite type, then write whole type */
213 ( id
== ID_FORM
|| id
== ID_LIST
|| id
== ID_CAT
|| id
== ID_PROP
)
215 byteswritten
= WriteStreamLong
222 if (byteswritten
< 0) return (byteswritten
);
224 scan
= sizeof(ULONG
);
226 } /* End of composite */
228 err
= PushContextNode
238 else /* Read or write mode */
240 /* Read mode. Read the chunk header from stream and put a new contextnode into the stack */
241 err
= GetChunkHeader(iff
, IPB(IFFParseBase
));
242 } /* End of Write or Read */