Exemplo n.º 1
0
        /// <summary>
        /// Writes the chunk.
        /// </summary>
        /// <returns>The chunk.</returns>
        /// <param name="buffer">Buffer.</param>
        /// <param name="offset">Offset.</param>
        /// <param name="count">Count.</param>
        public int WriteChunk(byte[] buffer, int offset, int count)
        {
            var top = GetCurrentContext();

            if (top == null)
            {
                return((int)ParserStatus.EndOfFile);
            }
            if (IdUtility.IsGenericId(top.Id))
            {
                return((int)ParserStatus.NotIFF);
            }
            return(WriteChunkInternal(top, buffer, offset, count));
        }
Exemplo n.º 2
0
        /// <summary>
        ///Test current state and advance to the next state. State is one of:
        /// -   Start of file if iff_NewIO is TRUE.
        ///		Push initial chunk, get its info and return.
        ///
        ///	-   Poised at end of chunk if iff_Paused is TRUE.
        ///		PopChunk() the current context. The top context will then be a generic
        ///		or end of file.  Return EOF if the latter. If this chunk is exhausted,
        ///		pause again and return, otherwise push new chunk and return.
        ///
        ///	-   Inside a generic chunk.
        ///		Push a new context and return.
        ///
        ///	-   Inside a non-generic chunk.
        ///		Pause and return.
        /// </summary>
        /// <returns>The state.</returns>
        private int NextState()
        {
            ContextNode top;
            int         err;
            uint        topId;

            /* deal with the case of the first chunk */
            if (_newIO)
            {
                err     = PushChunkRead(true);
                _newIO  = false;
                _paused = false;
                if (err < 0)
                {
                    return(err);
                }

                top = GetCurrentContext();

                if ((top.Id != GenericChunkIds.ID_FORM) &&
                    (top.Id != GenericChunkIds.ID_CAT) &&
                    (top.Id != GenericChunkIds.ID_LIST) &&
                    (!IsContainerId(top.Id)))
                {
                    return((int)ParserStatus.NotIFF);
                }

                if ((top.Size & 1) == 1)
                {
                    /* containers must inherently be word-aligned */
                    return((int)ParserStatus.Mangled);
                }

                return(ReadGenericType());
            }

            /* In the PAUSE state, do the deferred PopChunk() */
            if (_paused)
            {
                err = PopChunk();
                if (err < 0)
                {
                    return(err);
                }
                _paused = false;
            }

            /* If no top context node then the file is exhausted. */
            if ((top = GetCurrentContext()) == null)
            {
                return((int)ParserStatus.EndOfFile);
            }

            topId = top.Id;
            if (IdUtility.IsGenericId(topId) || IsContainerId(topId))
            {
                /* If inside a generic chunk, and not exhausted, push a subchunk. */
                if (top.Offset < top.Size)
                {
                    err = PushChunkRead(false);
                    if (err < 0)
                    {
                        return(err);
                    }

                    top = GetCurrentContext();

                    /* If non-generic, we're done, but if the containing chunk is not
                     * FORM or PROP, it's an IFF syntax error.
                     */
                    if (!IdUtility.IsGenericId(top.Id))
                    {
                        if ((topId != GenericChunkIds.ID_FORM) &&
                            (topId != GenericChunkIds.ID_PROP) &&
                            (!IsContainerId(topId)))
                        {
                            return((int)ParserStatus.SyntaxError);
                        }

                        return(0);
                    }

                    /* If this new chunk is generic, and is a PROP, test to see if it's
                     * in the right place --  containing chunk should be a LIST.
                     */
                    if ((top.Id == GenericChunkIds.ID_PROP) &&
                        (topId != GenericChunkIds.ID_LIST))
                    {
                        return((int)ParserStatus.SyntaxError);
                    }

                    /* since it's an ok generic, get its type and return */
                    return(ReadGenericType());
                }
                else if (top.Offset != top.Size)
                {
                    /* If not exhaused, this is a junky IFF file */
                    return((int)ParserStatus.Mangled);
                }
            }

            /* If the generic is exhausted, or this is a non-generic chunk,
             * enter the pause state and return flag.
             */
            _paused = true;

            return((int)ParserStatus.EndOfContext);
        }
Exemplo n.º 3
0
        private int PushChunkWrite(uint type, uint id, uint size)
        {
            ContextNode cn;
            int         err;
            uint        parentType;
            Chunk       chunk;
            SmallChunk  smallChunk;
            bool        firstChunk;

            byte[] buffer;

            if ((cn = GetCurrentContext()) != null)
            {
                parentType = cn.Type;
                firstChunk = false;
            }
            else if (_newIO)
            {
                parentType = 0;
                firstChunk = true;
                _newIO     = false;

                /* first chunk must be FORM, CAT, or LIST */
                if ((id != GenericChunkIds.ID_FORM) &&
                    (id != GenericChunkIds.ID_CAT) &&
                    (id != GenericChunkIds.ID_LIST))
                {
                    return((int)ParserStatus.NotIFF);
                }
            }
            else
            {
                return((int)ParserStatus.EndOfFile);
            }
            if (!IdUtility.IsGoodId(id))
            {
                return((int)ParserStatus.SyntaxError);
            }
            if (IdUtility.IsGenericId(id))
            {
                if (id == GenericChunkIds.ID_PROP)
                {
                    /* the containing context for PROP must be a LIST */
                    if (cn.Id != GenericChunkIds.ID_LIST)
                    {
                        return((int)ParserStatus.SyntaxError);
                    }
                }
                /* Generic ID.  Check the validity of its subtype. */
                if (!IdUtility.IsGoodType(type))
                {
                    return((int)ParserStatus.NotIFF);
                }
            }
            else
            {
                /* Non-generic ID.  Containing context must be PROP or FORM or container */
                if ((cn.Id != GenericChunkIds.ID_FORM) &&
                    (cn.Id != GenericChunkIds.ID_PROP) &&
                    (!IsContainerId(cn.Id)))
                {
                    return((int)ParserStatus.SyntaxError);
                }
            }

            /* Write the chunk header: ID and size (if IFF_SIZE_UNKNOWN, it will
             * be patched later by PopChunkW()).
             */
            if ((size >= (uint)ChunkSize.Reserved) &&
                (size != (uint)ChunkSize.Unknown32Bit))
            {
                chunk.Id     = id;
                chunk.Filler = (uint)ChunkSize.Known64Bit;
                chunk.Size   = size;

                buffer = Marshal.StructToBytes(chunk);

                if (firstChunk)
                {
                    err = _streamOperations.Write(_ioContext, buffer, 0, buffer.Length);
                }
                else
                {
                    /* Update parent's count of bytes written. */
                    err = WriteChunkInternal(cn, buffer, 0, buffer.Length);
                }
            }
            else
            {
                smallChunk.Id   = id;
                smallChunk.Size = size;
                buffer          = Marshal.StructToBytes(smallChunk);

                if (firstChunk)
                {
                    err = _streamOperations.Write(_ioContext, buffer, 0, buffer.Length);
                }
                else
                {
                    /* Update parent's count of bytes written. */
                    err = WriteChunkInternal(cn, buffer, 0, buffer.Length);
                }
            }
            if (err < 0)
            {
                return(err);
            }
            /* Allocate and fill in a ContextNode for the new chunk */
            cn             = new ContextNode(id, 0);
            cn.Size        = size;
            cn.Offset      = 0;
            cn.CurrentSize = 0;
            _stack.AddHead(cn);

            /* For generic chunks, write the type out now that
             * the chunk context node is initialized.
             */
            if (IdUtility.IsGenericId(id) || IsContainerId(id))
            {
                if (IdUtility.IsGenericId(id))
                {
                    var bigEndianType = type;
                    Swap(ref bigEndianType);
                    buffer  = BitConverter.GetBytes(bigEndianType);
                    err     = WriteChunkInternal(cn, buffer, 0, buffer.Length);
                    cn.Type = type;
                }
                else
                {
                    cn.Type = 0;
                }
            }
            else
            {
                cn.Type = parentType;
            }
            return(err);
        }