home *** CD-ROM | disk | FTP | other *** search
- /*
- (C) 1995-96 AROS - The Amiga Replacement OS
- $Id: basicfuncs.c,v 1.3 1997/02/04 14:10:03 digulla Exp $
-
- Desc: Basic help functions needed by iffparse.
- Lang: English.
- */
- #include "iffparse_intern.h"
-
- LONG PushContextNode
- (
- struct IFFHandle *iff,
- LONG type,
- LONG id,
- LONG size,
- LONG scan,
- struct IFFParseBase_intern *IFFParseBase
- )
- {
- /* Allocates and puts a new context-node into the top of the context-stack
- Also does GoodType and GoodID checking */
-
- struct ContextNode *cn;
-
- BOOL composite;
-
-
- /* Set the composite flag if we have a composite contextnnode */
- if (id == ID_FORM || id == ID_LIST || id == ID_CAT || id == ID_PROP)
- {
- composite = TRUE;
- /* We have a new type, check it */
- }
- else
- {
- composite = FALSE;
- /* No composite type found. Get old type from top contextnode */
- cn = TopChunk(iff);
- type = cn->cn_Type;
- }
-
- /* Check if type and ids are valid */
- if (!(GoodType(type) && GoodID(id)) )
- return (IFFERR_MANGLED);
-
- /* Allocate a new context node */
- if
- (
- !(cn = AllocMem
- (
- sizeof (struct IntContextNode),
- MEMF_ANY
- )
- )
- )
- return (IFFERR_NOMEM);
-
- /* Put the context node at top of the stack */
- AddHead
- (
- (struct List*)&( GetIntIH(iff)->iff_CNStack ),
- (struct Node*)cn
- );
-
-
- /* Set the contextnode attrs */
- cn->cn_Type = type;
- cn->cn_ID = id;
- cn->cn_Size = size;
- cn->cn_Scan = scan;
-
- GetIntCN(cn)->cn_Composite = composite;
- /* Initialize the LCI-list */
- NewList ((struct List*)&( GetIntCN(cn)->cn_LCIList ));
-
- /* Deeper stack */
- iff->iff_Depth ++;
-
- return (NULL);
- }
-
- VOID PopContextNode(struct IFFHandle* iff,
- struct IFFParseBase_intern *IFFParseBase)
- {
- struct LocalContextItem *node,
- *nextnode;
-
- struct IntContextNode *cn;
-
- cn = GetIntCN( TopChunk( iff ) );
-
- /* Free all localcontextitems */
- node = (struct LocalContextItem*)cn->cn_LCIList.mlh_Head;
-
- while ((nextnode = (struct LocalContextItem*)node->lci_Node.mln_Succ))
- {
- PurgeLCI((struct LocalContextItem*)node, IFFParseBase);
-
- node = nextnode;
- }
-
- /* Free the contextnode itself */
- Remove((struct Node*)cn);
- FreeMem(cn,sizeof (struct IntContextNode));
-
- /*One less node on stack */
- iff->iff_Depth --;
- return;
- }
-
- LONG ReadStreamLong (struct IFFHandle *iff,
- APTR valptr,
- struct IFFParseBase_intern *IFFParseBase)
- {
- LONG val;
- UBYTE bytes[4];
-
- val = ReadStream (iff, bytes, sizeof(LONG), IFFParseBase);
-
- if (val < 0)
- return val;
- else if (val != sizeof(LONG))
- return IFFERR_EOF;
-
- *(LONG *)valptr = bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3];
-
- return sizeof(LONG);
- } /* ReadStreamLong */
-
- LONG WriteStreamLong (struct IFFHandle *iff,
- APTR valptr,
- struct IFFParseBase_intern *IFFParseBase)
- {
- LONG val = *(LONG *)valptr;
- UBYTE bytes[4];
-
- bytes[0] = val >> 24;
- bytes[1] = val >> 16;
- bytes[2] = val >> 8;
- bytes[3] = val;
-
- val = WriteStream (iff, bytes, sizeof(LONG), IFFParseBase);
-
- if (val < 0)
- return val;
- else if (val != sizeof(LONG))
- return IFFERR_EOF;
-
- return sizeof(LONG);
- } /* WriteStreamLong */
-
- /********************/
- /* GetChunkHeader */
- /********************/
-
- LONG GetChunkHeader(struct IFFHandle *iff,
- struct IFFParseBase_intern *IFFParseBase)
- {
- LONG type,
- id,
- size;
-
- LONG scan = 0;
-
- LONG bytesread;
-
- /* Reads in the appropriate stuff from a chunk and makes a contextnode of it */
-
- /* Read chunk ID */
- bytesread = ReadStreamLong
- (
- iff,
- &id,
- IFFParseBase
- );
-
- /* We may have an IFF Error */
- if ( bytesread < 0) return (bytesread);
-
- /* Read chunk size */
- bytesread = ReadStreamLong
- (
- iff,
- &size,
- IFFParseBase
- );
-
- if ( bytesread < 0) return (bytesread);
-
- /* We must see if we have a IFF header ("FORM", "CAT" or "LIST" */
- if
- (
- id == ID_FORM
- ||
- id == ID_CAT
- ||
- id == ID_LIST
- ||
- id == ID_PROP
- )
- {
- /* Read chunk size */
- bytesread = ReadStreamLong
- (
- iff,
- &type,
- IFFParseBase
- );
-
- if ( bytesread < 0) return (bytesread);
-
- /* Type is inside chunk so we had to add its size to the scancount. */
- scan = sizeof (LONG);
-
- }
-
-
- return
- (
- PushContextNode
- (
- iff,
- type,
- id,
- size,
- scan,
- IFFParseBase
- )
- );
- }
-
- /********************/
- /* InvokeHandlers */
- /********************/
-
- LONG InvokeHandlers(struct IFFHandle *iff, LONG mode, LONG ident,
- struct IFFParseBase_intern *IFFParseBase)
- {
- struct ContextNode *cn;
- struct HandlerInfo *hi;
- struct LocalContextItem *lci;
-
- LONG err;
-
- /* Either RETURN_2CLIENT or IFFERR_EOC */
- LONG stepping_retval;
-
- ULONG param;
-
- if (ident == IFFLCI_ENTRYHANDLER)
- stepping_retval = IFF_RETURN2CLIENT;
- else
- stepping_retval = IFFERR_EOC;
-
- /* Check for IFFPARSE_RAWSTEP *before* calling evt entryhandlers */
- if (mode == IFFPARSE_RAWSTEP)
- return (stepping_retval);
-
-
- /* Get top of contextstack */
- cn = TopChunk(iff);
-
- /* Scan downwards to find a contextnode with a matching LCI */
-
- lci = FindLocalItem
- (
- iff,
- cn->cn_Type,
- cn->cn_ID,
- ident
- );
-
- if (lci)
- {
- /* Get the HandlerInfo userdata */
- hi = LocalItemData(lci);
-
-
- /* First check if a hook really is present */
- if (! hi->hi_Hook)
- return (IFFERR_NOHOOK);
-
- /* What kind off command shall the hook receive */
-
- if (ident == IFFLCI_ENTRYHANDLER)
- param = IFFCMD_ENTRY;
- else
- param = IFFCMD_EXIT;
-
-
- /* Call the handler */
- if ( (err = CallHookPkt ( hi->hi_Hook, hi->hi_Object, (APTR)param)) )
- return (err);
- }
-
- /* Check for IFFPARSE_STEP. (stepping through file WITH handlers enabled */
- if (mode == IFFPARSE_STEP)
- return (stepping_retval);
-
- return (NULL);
- }
-
- /******************/
- /* PurgeLCI */
- /******************/
-
- VOID PurgeLCI(struct LocalContextItem *lci,
- struct IFFParseBase_intern *IFFParseBase)
- {
- /* Look in the RKM SetLocalItemPurge autodoc for explanation on that one below */
-
- Remove((struct Node*)lci);
- /* Has the user specified a Purge hook ? */
-
- if ( GetIntLCI(lci)->lci_PurgeHook)
- CallHookPkt
- (
- GetIntLCI(lci)->lci_PurgeHook,
- lci,
- (APTR)IFFCMD_PURGELCI
- );
-
- else
- FreeLocalItem(lci);
-
- return;
- }
-
-
-
- /******************/
- /* Readstream */
- /******************/
-
- /* Reads from the current StreamHandler */
-
- /* returns one of the standar IFF errors */
- LONG ReadStream(struct IFFHandle *iff, APTR buf, LONG bytestoread,
- struct IFFParseBase_intern *IFFParseBase)
- {
- LONG retval,
- err;
-
- /* For use with custom streams */
- struct IFFStreamCmd cmd;
-
- /* Now we can do the actual reading of the stream */
- cmd.sc_Command = IFFCMD_READ;
- cmd.sc_Buf = buf;
- cmd.sc_NBytes = bytestoread;
-
- err = CallHookPkt
- (
- GetIntIH(iff)->iff_StreamHandler,
- iff,
- &cmd
- );
- if (err)
- retval = IFFERR_READ;
- else
- retval = bytestoread;
-
- return (retval);
- }
-
-
- /****************/
- /* WriteStream */
- /****************/
-
- LONG WriteStream(struct IFFHandle *iff, APTR buf, LONG bytestowrite,
- struct IFFParseBase_intern *IFFParseBase)
- {
- LONG retval,
- err;
-
- struct IFFStreamCmd cmd;
-
- /* Call the custom hook with a write command */
-
- cmd.sc_Command = IFFCMD_WRITE;
- cmd.sc_Buf = buf;
- cmd.sc_NBytes = bytestowrite;
-
- err = CallHookPkt
- (
- GetIntIH(iff)->iff_StreamHandler,
- iff,
- &cmd
- );
-
- if (err)
- retval = IFFERR_WRITE;
- else
- retval = bytestowrite;
-
- return (retval);
- }
- /***************/
- /* SeekStream */
- /***************/
-
- LONG SeekStream(struct IFFHandle *iff,LONG offset,
- struct IFFParseBase_intern *IFFParseBase)
- {
-
- /* Some different problem - situations:
-
- 1. Backwards seek in non back seekable stream. In this case the stream is buffered,
- and we may seek in the buffer. This is done automagically, since PushChunk
- then has inserted a Buffering streamhandle.
-
-
- 2. Forwards seek in a non - seekable stream. Simulate the seek with a bunch
- of ReadStream's
-
- */
-
- struct IFFStreamCmd cmd;
-
-
- ULONG flags;
-
- LONG retval = NULL;
-
- LONG err;
-
- UBYTE *seekbuf;
-
- flags = iff->iff_Flags;
-
-
- /* Problem 2. */
- if
- (
- (offset > 0)
- &&
- (
- !(
- (flags & IFFF_RSEEK)
- ||
- (flags & IFFF_FSEEK)
- )
- )
- )
- {
- /* We should use consecutive ReadStream()s to simulate a Seek */
-
- /* Allocote a buffer to use with the read */
- seekbuf = AllocMem(SEEKBUFSIZE, MEMF_ANY);
-
- if (!seekbuf)
- retval = IFFERR_NOMEM;
- else
- {
-
- for (; offset > SEEKBUFSIZE; offset -= SEEKBUFSIZE)
- {
- retval = ReadStream(iff, seekbuf, SEEKBUFSIZE, IFFParseBase);
-
- if (retval != SEEKBUFSIZE)
- retval = IFFERR_SEEK;
- }
-
- /* Seek what is left of offset */
- retval = ReadStream(iff, seekbuf, SEEKBUFSIZE, IFFParseBase);
- if ( retval != SEEKBUFSIZE)
- retval = IFFERR_SEEK;
-
- FreeMem(seekbuf, SEEKBUFSIZE);
- }
-
- }
- else if (offset == 0)
- {
- ; /* Do nothing */
- }
- else
- {
-
- /* Everything is just fine... Seek in a normal manner */
-
- cmd.sc_Command = IFFCMD_SEEK;
- cmd.sc_NBytes = offset;
-
- err = CallHookPkt
- (
- GetIntIH(iff)->iff_StreamHandler,
- iff,
- &cmd
- );
-
- if (err)
- retval = IFFERR_SEEK;
- }
-
- return (retval);
- }
-
-
- /********************/
- /* Buffering stuff */
- /********************/
-
-
-
-
- /************************/
- /* Endian conversions */
- /************************/
-
- /* If the CPU is little endian, the id will be switched to the opposite
- endianess of what it is now.
-
- Have tried to put this into a macro, but only got heaps of errors.
-
- */
-
- LONG SwitchIfLittleEndian(LONG id)
- {
-
- #if (AROS_BIG_ENDIAN == 0)
- id = ((id & 0xFF000000) >> 24)
- | ((id & 0x00FF0000) >> 8)
- | ((id & 0x0000FF00) << 8)
- | ((id & 0x000000FF) << 24);
- #endif
-
- return (id);
- }
-