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); }
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); } } }
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); }
/// <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()); }
/// <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); }
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); }
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); }