home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / workbench / libs / iffparse / pushchunk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-03  |  4.2 KB  |  176 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: pushchunk.c,v 1.2 1997/02/03 18:38:02 digulla Exp $
  4.  
  5.     Desc:
  6.     Lang: english
  7. */
  8. #include "iffparse_intern.h"
  9.  
  10. /*****************************************************************************
  11.  
  12.     NAME */
  13. #include <proto/iffparse.h>
  14.  
  15.     AROS_LH4(LONG, PushChunk,
  16.  
  17. /*  SYNOPSIS */
  18.     AROS_LHA(struct IFFHandle *, iff, A0),
  19.     AROS_LHA(LONG              , type, D0),
  20.     AROS_LHA(LONG              , id, D1),
  21.     AROS_LHA(LONG              , size, D2),
  22.  
  23. /*  LOCATION */
  24.     struct Library *, IFFParseBase, 14, IFFParse)
  25.  
  26. /*  FUNCTION
  27.     Pushes a new context node onto the context stack. Usually used in write mode.
  28.     In write mode the contextnode will be pushed with the given parameters.
  29.     In Read mode the type, id and size will be read from the installed stream.
  30.     Note that IFFSIZE_UNKNOW can be given for size in write mode. In that case,
  31.     the size of will not be known until you do a PopChunk(). PopChunk()
  32.     will then seek back in the stream and write the correct size.
  33.  
  34.  
  35.     INPUTS
  36.     iff    - pointer to IFFHandle struct.
  37.     type  -  chunk type specifier.
  38.     id    -  chunk identifier.
  39.     size  -  size of the new chunk. May be IFFSIZE_UNKNOWN.
  40.  
  41.     RESULT
  42.     error  -  0 if successfull, IFFERR_#? otherwize.
  43.  
  44.     NOTES
  45.  
  46.     EXAMPLE
  47.  
  48.     BUGS
  49.  
  50.     SEE ALSO
  51.     PopChunk()
  52.  
  53.     INTERNALS
  54.     We do different things for Read and Write streams (obviosly enough ;->)
  55.  
  56.     Write: Write the supplied id, size and evt type into the stream.
  57.  
  58.     Read: Get a chunk from disk
  59.  
  60.  
  61.     For Write mode there are som problems with unknown chunk size and
  62.     non-random-seekable streams:
  63.     4. situations:
  64.  
  65.     SIZE KNOWN && RSEEK    - Just write the whole header.
  66.     SIZE KNOWN && !RSEEK     - Write whole header. No RSEEK does not matter, since
  67.                   we don't have to seek back to write size in PopChunk
  68.  
  69.     SIZE UNKNOWN && RSEEK    - Write whole header. Write size too, just to seek pass it,
  70.                   even if the size value might be meaningless. We will
  71.                   seek back and insert the correct size later.
  72.  
  73.     SIZE UNKNOWN && !RSEEK    - Here is where the trouble starts. We can not seek back
  74.                   and insert the correct size later, which means that we MUST
  75.                   buffer the contents of the chunk, and don't write ANYTHING to
  76.                   the stream until we know its size.
  77.  
  78.                   We preserve the old StreamHandler, and inserts a new one
  79.                   that buffers all writes into memory.
  80.  
  81.  
  82.  
  83.     HISTORY
  84.   27-11-96    digulla automatically created from
  85.       iffparse_lib.fd and clib/iffparse_protos.h
  86.  
  87. *****************************************************************************/
  88. {
  89.     AROS_LIBFUNC_INIT
  90.     AROS_LIBBASE_EXT_DECL(struct Library *,IFFParseBase)
  91.  
  92.     LONG err;
  93.  
  94.     LONG byteswritten;
  95.  
  96.     LONG scan = 0;
  97.  
  98.     if (iff->iff_Flags & IFFF_WRITE)
  99.     {
  100.       /* Do we have a problem - situation ? */
  101.     if ( (size == IFFSIZE_UNKNOWN)
  102.         && (!(iff->iff_Flags & IFFF_RSEEK))
  103.     )
  104.     {
  105.  
  106.         /* Initialize the buffering streamhandler */
  107.         err = InitBufferedStream(iff, IPB(IFFParseBase));
  108.         if (err) return (err);
  109.     }
  110.  
  111.     /* The ID must be big endian when written */
  112.     id = SwitchIfLittleEndian(id);
  113.  
  114.     byteswritten = WriteStreamLong
  115.     (
  116.         iff,
  117.         &id,
  118.         IPB(IFFParseBase)
  119.     );
  120.  
  121.     /* IFFFERR_ ..    ? */
  122.         if (byteswritten < 0) return (byteswritten);
  123.  
  124.     /* The chunk size will be written during PopChunk too, but we write
  125.      here to seek past it */
  126.  
  127.     byteswritten = WriteStreamLong
  128.     (
  129.         iff,
  130.         &size,
  131.         IPB(IFFParseBase)
  132.     );
  133.     /* IFFERR_... ? */
  134.     if (byteswritten < 0) return (byteswritten);
  135.  
  136.     /* If a composite type, then write whole type */
  137.     if
  138.     ( id == ID_FORM || id == ID_LIST || id == ID_CAT || id == ID_PROP )
  139.     {
  140.         /* The type MUST be big endian when written */
  141.         type = SwitchIfLittleEndian(type);
  142.  
  143.         byteswritten = WriteStreamLong
  144.         (
  145.         iff,
  146.         &type,
  147.         IPB(IFFParseBase)
  148.         );
  149.  
  150.         if (byteswritten < 0) return (byteswritten);
  151.  
  152.         scan = sizeof(ULONG);
  153.  
  154.     } /* End of composite */
  155.  
  156.     err = PushContextNode
  157.     (
  158.         iff,
  159.         type,
  160.         id,
  161.         size,
  162.         scan,
  163.         IPB(IFFParseBase)
  164.     );
  165.     }
  166.     else  /* Read or write mode */
  167.     {
  168.     /* Read mode. Read the chunk header from stream and put a new contextnode into the stack */
  169.     err = GetChunkHeader(iff, IPB(IFFParseBase));
  170.     }  /* End of Write or Read */
  171.  
  172.     return (err);
  173.  
  174.     AROS_LIBFUNC_EXIT
  175. } /* PushChunk */
  176.