Exemplo n.º 1
0
        private int ReadGenericType()
        {
            ContextNode top;
            int         result;

            if ((top = GetCurrentContext()) != null)
            {
                var buffer = new byte[sizeof(uint)];
                result = ReadChunk(buffer, 0, buffer.Length);
                var type = BitConverter.ToUInt32(buffer, 0);
                Swap(ref type);
                top.Type = type;
                if (result == sizeof(uint))
                {
                    if (IdUtility.IsGoodType(top.Type))
                    {
                        return(0);
                    }
                    return((int)ParserStatus.Mangled);
                }
                if (result >= 0)
                {
                    result = (int)ParserStatus.PrematureEndOfFile;
                }
                return(result);
            }
            return((int)ParserStatus.EndOfFile);
        }
Exemplo n.º 2
0
        private void CheckInternal(string fileName, Action <int> assertAction)
        {
            using (var fs = new FileStream(Path.Combine(TestContext.CurrentContext.TestDirectory, fileName), FileMode.Open)) {
                using (var iffParser = new IFFParser(fs, false)) {
                    var error = 0;
                    while (true)
                    {
                        error = iffParser.Parse(ParseMode.RawStep);
                        if (error == (int)ParserStatus.EndOfContext)
                        {
                            continue;
                        }
                        else if (error != 0)
                        {
                            break;
                        }
                        var top = iffParser.GetCurrentContext();
                        if (top == null)
                        {
                            continue;
                        }
                        for (var parent = iffParser.GetParentContext(top);
                             parent != null;
                             parent = iffParser.GetParentContext(parent))
                        {
                            Console.Write(".");
                        }
                        Console.Write("{0} {1} ", IdUtility.IdToString(top.Id), top.Size);
                        Console.Write("{0}\n", IdUtility.IdToString(top.Type));
                    }

                    assertAction(error);
                }
            }
        }
Exemplo n.º 3
0
        public void CreateArticleId_WithSpaceCharacter_ShouldEncode()
        {
            var articleSlug = "TestArticleTitle Test";

            string id       = IdUtility.CreateArticleId(articleSlug);
            string idSuffix = GetIdSuffix(id);

            bool matches3986 = Rfc3986Regex.IsMatch(idSuffix);

            Assert.IsTrue(matches3986);
        }
Exemplo n.º 4
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));
        }
 static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
 {
     ProcessIDs <ProxyBuilding>((building) => building.ID = IdUtility.FindId <ProxyBuilding>());
     ProcessIDs <DisasterTemplate>((disaster) => disaster.ResetID());
 }
Exemplo n.º 6
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.º 7
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);
        }
Exemplo n.º 8
0
        private int PushChunkRead(bool firstChunk)
        {
            Chunk chunk;
            int   err;

            byte[] buffer;

            var top = GetCurrentContext();

            if (top == null && !firstChunk)
            {
                return((int)ParserStatus.EndOfFile);
            }
            var type = top != null ? top.Type : 0;

            if (firstChunk)
            {
                buffer = new byte[Marshal.SizeOf <SmallChunk>()];
                err    = _streamOperations.Read(_ioContext, buffer, 0, buffer.Length);
                if (err != Marshal.SizeOf <SmallChunk>())
                {
                    if (err >= 0)
                    {
                        err = (int)ParserStatus.NotIFF;
                    }
                    return(err);
                }
                var smallChunk = Marshal.BytesToStruct <SmallChunk>(buffer);
                chunk.Id   = smallChunk.Id;
                chunk.Size = smallChunk.Size;

                if (chunk.Size == (ulong)ChunkSize.Known64Bit)
                {
                    buffer = new byte[chunk.Size];
                    err    = _streamOperations.Read(_ioContext, buffer, 0, buffer.Length);
                    if ((ulong)err != chunk.Size)
                    {
                        if (err >= 0)
                        {
                            err = (int)ParserStatus.NotIFF;
                        }
                        return(err);
                    }
                    chunk.Size = BitConverter.ToUInt32(buffer, 0);
                }
                else if (chunk.Size >= (ulong)ChunkSize.Reserved)
                {
                    return((int)ParserStatus.Mangled);
                }
            }
            else
            {
                /* Using ReadChunk() causes these bytes to go into the
                 * parent's scan count
                 */
                buffer = new byte[Marshal.SizeOf <SmallChunk>()];
                err    = ReadChunk(buffer, 0, buffer.Length);
                if (err != Marshal.SizeOf <SmallChunk>())
                {
                    if (err >= 0)
                    {
                        err = (int)ParserStatus.PrematureEndOfFile;
                    }
                    return(err);
                }

                var smallChunk = Marshal.BytesToStruct <SmallChunk>(buffer);
                chunk.Id   = smallChunk.Id;
                chunk.Size = smallChunk.Size;

                if (chunk.Size == (ulong)ChunkSize.Known64Bit)
                {
                    buffer = new byte[chunk.Size];
                    err    = _streamOperations.Read(_ioContext, buffer, 0, buffer.Length);
                    if ((ulong)err != chunk.Size)
                    {
                        if (err >= 0)
                        {
                            err = (int)ParserStatus.NotIFF;
                        }
                        return(err);
                    }
                    chunk.Size = BitConverter.ToUInt32(buffer, 0);
                }
                else if (chunk.Size >= (ulong)ChunkSize.Reserved)
                {
                    return((int)ParserStatus.Mangled);
                }
                if (chunk.Size > (top.Size - top.Offset))
                {
                    return((int)ParserStatus.Mangled);
                }
            }
            if (IdUtility.IsGoodId(chunk.Id))
            {
                try {
                    var contextNode = new ContextNode(chunk.Id, type);
                    contextNode.Size        = chunk.Size;
                    contextNode.Offset      = 0;
                    contextNode.CurrentSize = chunk.Size;

                    _stack.AddHead(contextNode);
                    return(0);
                } catch (OutOfMemoryException) {
                    return((int)ParserStatus.OutOfMemory);
                }
            }
            if (this._newIO)
            {
                return((int)ParserStatus.NotIFF);
            }
            return((int)ParserStatus.SyntaxError);
        }