Example #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="WADFileBase" /> class.
        /// </summary>
        /// <param name="format">
        /// The value for the <see cref="WADFileBase.Format" /> property.
        /// </param>
        /// <param name="stream">
        /// The value for the <see cref="WADFileBase.Stream" /> property.
        /// </param>
        /// <param name="ownsStream">
        /// The value for the <see cref="WADFileBase._OWNS_STREAM" /> field.
        /// </param>
        /// <param name="sync">
        /// The custom value for the <see cref="WADObject._SYNC" /> field.
        /// </param>
        /// <exception cref="ArgumentException">
        /// <paramref name="stream" /> is not readable / seekable.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="stream" /> is <see langword="null" />.
        /// </exception>
        protected WADFileBase(WADFormat format, Stream stream, bool ownsStream = true, object sync = null)
            : base(sync: sync)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            if (stream.CanRead == false)
            {
                throw new ArgumentException("Not readable!", "stream");
            }

            if (stream.CanSeek == false)
            {
                throw new ArgumentException("Not seekable!", "stream");
            }

            this._FORMAT      = format;
            this._STREAM      = stream;
            this._OWNS_STREAM = ownsStream;
        }
Example #2
0
        /// <summary>
        /// Creates instances from a stream.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="stream">The stream.</param>
        /// <param name="bufferSize">The custom buffer size to use to read from <paramref name="stream" />.</param>
        /// <returns>The list of lazy loaded instances.</returns>
        /// <exception cref="ArgumentException">
        /// <paramref name="stream" /> is not readable.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="stream" /> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="bufferSize" /> is less than 1.
        /// </exception>
        public static IEnumerable <IWADFile> FromStream(Stream stream, WADFormat format = WADFormat.Default, int?bufferSize = null)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            if (stream.CanRead == false)
            {
                throw new ArgumentException("stream");
            }

            if (bufferSize < 1)
            {
                throw new ArgumentOutOfRangeException("bufferSize", bufferSize,
                                                      "Is less than 1!");
            }

            bool hasNext;

            do
            {
                hasNext = false;

                byte[] buffer;

                buffer = new byte[4];
                if (stream.Read(buffer, 0, buffer.Length) != buffer.Length)
                {
                    continue;
                }

                var header = Encoding.ASCII.GetString(buffer).ToUpper().Trim();

                IWADFile result = null;

                var wadStream = new MemoryStream();
                try
                {
                    Action copyToWadStream = () =>
                    {
                        if (!bufferSize.HasValue)
                        {
                            stream.CopyTo(wadStream);
                        }
                        else
                        {
                            stream.CopyTo(wadStream, bufferSize.Value);
                        }

                        wadStream.Position = 0;
                    };

                    switch (header)
                    {
                    case "IWAD":
                        copyToWadStream();

                        result = new IWAD(format, wadStream, true);
                        break;

                    case "PWAD":
                        copyToWadStream();

                        result = new PWAD(format, wadStream, true);
                        break;
                    }
                }
                catch (Exception ex)
                {
                    wadStream.Dispose();

                    throw ex;
                }

                if (result != null)
                {
                    hasNext = true;

                    yield return(result);
                }
            }while (hasNext);
        }
Example #3
0
        /// <summary>
        /// Builds a file.
        /// </summary>
        /// <param name="initialLumpName">Name of the initial lump.</param>
        /// <param name="format">The format to use.</param>
        /// <returns>The created file.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="initialLumpName" /> is invalid.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="initialLumpName" /> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Length of <paramref name="initialLumpName" /> is greater than 8.
        /// </exception>
        public IWADFile Build(string initialLumpName, WADFormat format = WADFormat.Default)
        {
            if (initialLumpName == null)
            {
                throw new ArgumentNullException("initialLumpName");
            }

            initialLumpName = initialLumpName.ToUpper().Trim();
            if (initialLumpName == string.Empty)
            {
                throw new ArgumentException("initialLumpName");
            }

            var initialLumpNameLength = Encoding.ASCII.GetBytes(initialLumpName).Length;

            if (initialLumpNameLength > 8)
            {
                throw new ArgumentOutOfRangeException("initialLumpName.Length", initialLumpNameLength,
                                                      "Cannot be larger than 8 chars!");
            }

            return(this.InvokeForDisposable(
                       func: (obj, state) =>
            {
                var builder = (WADFileBuilder)obj;

                using (var temp = new MemoryStream())
                {
                    // header
                    temp.Write(Encoding.ASCII.GetBytes("PWAD"), 0, 4);

                    // these are overwritten later
                    temp.Write(new byte[8], 0, 8);

                    var newLumpList = new List <Lump>();

                    var firstLump = new Lump();
                    firstLump.Name = state.FirstLumpName;
                    firstLump.Position = 12;
                    firstLump.Size = 0;
                    newLumpList.Add(firstLump);

                    // write lump data
                    foreach (var lump in builder._LUMPS)
                    {
                        using (var lumpStream = lump.GetStream())
                        {
                            var newLump = new Lump();
                            newLump.Name = lump.Name;
                            newLump.Position = (int)temp.Position;
                            newLump.Size = (int)lumpStream.Length;

                            lumpStream.CopyTo(temp);

                            newLumpList.Add(newLump);
                        }
                    }

                    var secondLump = newLumpList.Skip(1).FirstOrDefault();
                    if (secondLump != null)
                    {
                        firstLump.Position = secondLump.Position;
                    }

                    var numberOfLumps = newLumpList.Count;
                    var posOfEntries = (int)temp.Position;

                    // now write entries
                    foreach (var nl in newLumpList)
                    {
                        var lumpNameChars = new List <byte>(Encoding.ASCII.GetBytes(nl.Name ?? string.Empty));
                        while (lumpNameChars.Count < 8)
                        {
                            lumpNameChars.Add(0);          // fill with zero chars
                        }

                        if (lumpNameChars.Count > 8)
                        {
                            throw new ArgumentOutOfRangeException("lumpNameChars.Count", lumpNameChars.Count,
                                                                  "Cannot be larger than 8 chars!");
                        }

                        var lumpPos = GetBytes(nl.Position);
                        var lumpSize = GetBytes(nl.Size);
                        var lumpName = lumpNameChars.ToArray();

                        temp.Write(lumpPos, 0, lumpPos.Length);
                        temp.Write(lumpSize, 0, lumpSize.Length);
                        temp.Write(lumpName, 0, lumpName.Length);
                    }

                    // update header
                    temp.Position = 4;
                    temp.Write(GetBytes(numberOfLumps), 0, 4);
                    temp.Write(GetBytes(posOfEntries), 0, 4);

                    temp.Position = 0;
                    return WADFileFactory.FromStream(temp, state.Format).Single();
                }
            },
                       funcState: new
            {
                FirstLumpName = initialLumpName,
                Format = format,
            }));
        }
Example #4
0
 internal IWAD(WADFormat format, Stream stream, bool ownsStream = true, object sync = null)
     : base(format: format,
            stream: stream, ownsStream: ownsStream,
            sync: sync)
 {
 }
Example #5
0
 internal IWAD(WADFormat format, Stream stream, bool ownsStream = true, object sync = null)
     : base(format: format,
            stream: stream, ownsStream: ownsStream,
            sync: sync)
 {
 }
Example #6
0
        /// <summary>
        /// Creates instances from a stream.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="stream">The stream.</param>
        /// <param name="bufferSize">The custom buffer size to use to read from <paramref name="stream" />.</param>
        /// <returns>The list of lazy loaded instances.</returns>
        /// <exception cref="ArgumentException">
        /// <paramref name="stream" /> is not readable.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="stream" /> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="bufferSize" /> is less than 1.
        /// </exception>
        public static IEnumerable<IWADFile> FromStream(Stream stream, WADFormat format = WADFormat.Default, int? bufferSize = null)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            if (stream.CanRead == false)
            {
                throw new ArgumentException("stream");
            }

            if (bufferSize < 1)
            {
                throw new ArgumentOutOfRangeException("bufferSize", bufferSize,
                                                      "Is less than 1!");
            }

            bool hasNext;

            do
            {
                hasNext = false;

                byte[] buffer;

                buffer = new byte[4];
                if (stream.Read(buffer, 0, buffer.Length) != buffer.Length)
                {
                    continue;
                }

                var header = Encoding.ASCII.GetString(buffer).ToUpper().Trim();

                IWADFile result = null;

                var wadStream = new MemoryStream();
                try
                {
                    Action copyToWadStream = () =>
                        {
                            if (!bufferSize.HasValue)
                            {
                                stream.CopyTo(wadStream);
                            }
                            else
                            {
                                stream.CopyTo(wadStream, bufferSize.Value);
                            }

                            wadStream.Position = 0;
                        };

                    switch (header)
                    {
                        case "IWAD":
                            copyToWadStream();

                            result = new IWAD(format, wadStream, true);
                            break;

                        case "PWAD":
                            copyToWadStream();

                            result = new PWAD(format, wadStream, true);
                            break;
                    }
                }
                catch (Exception ex)
                {
                    wadStream.Dispose();

                    throw ex;
                }

                if (result != null)
                {
                    hasNext = true;

                    yield return result;
                }
            }
            while (hasNext);
        }
Example #7
0
        /// <summary>
        /// Builds a file.
        /// </summary>
        /// <param name="initialLumpName">Name of the initial lump.</param>
        /// <param name="format">The format to use.</param>
        /// <returns>The created file.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="initialLumpName" /> is invalid.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="initialLumpName" /> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Length of <paramref name="initialLumpName" /> is greater than 8.
        /// </exception>
        public IWADFile Build(string initialLumpName, WADFormat format = WADFormat.Default)
        {
            if (initialLumpName == null)
            {
                throw new ArgumentNullException("initialLumpName");
            }

            initialLumpName = initialLumpName.ToUpper().Trim();
            if (initialLumpName == string.Empty)
            {
                throw new ArgumentException("initialLumpName");
            }

            var initialLumpNameLength = Encoding.ASCII.GetBytes(initialLumpName).Length;
            if (initialLumpNameLength > 8)
            {
                throw new ArgumentOutOfRangeException("initialLumpName.Length", initialLumpNameLength,
                                                      "Cannot be larger than 8 chars!");
            }

            return this.InvokeForDisposable(
                func: (obj, state) =>
                    {
                        var builder = (WADFileBuilder)obj;

                        using (var temp = new MemoryStream())
                        {
                            // header
                            temp.Write(Encoding.ASCII.GetBytes("PWAD"), 0, 4);

                            // these are overwritten later
                            temp.Write(new byte[8], 0, 8);

                            var newLumpList = new List<Lump>();

                            var firstLump = new Lump();
                            firstLump.Name = state.FirstLumpName;
                            firstLump.Position = 12;
                            firstLump.Size = 0;
                            newLumpList.Add(firstLump);

                            // write lump data
                            foreach (var lump in builder._LUMPS)
                            {
                                using (var lumpStream = lump.GetStream())
                                {
                                    var newLump = new Lump();
                                    newLump.Name = lump.Name;
                                    newLump.Position = (int)temp.Position;
                                    newLump.Size = (int)lumpStream.Length;

                                    lumpStream.CopyTo(temp);

                                    newLumpList.Add(newLump);
                                }
                            }

                            var secondLump = newLumpList.Skip(1).FirstOrDefault();
                            if (secondLump != null)
                            {
                                firstLump.Position = secondLump.Position;
                            }

                            var numberOfLumps = newLumpList.Count;
                            var posOfEntries = (int)temp.Position;

                            // now write entries
                            foreach (var nl in newLumpList)
                            {
                                var lumpNameChars = new List<byte>(Encoding.ASCII.GetBytes(nl.Name ?? string.Empty));
                                while (lumpNameChars.Count < 8)
                                {
                                    lumpNameChars.Add(0);  // fill with zero chars
                                }

                                if (lumpNameChars.Count > 8)
                                {
                                    throw new ArgumentOutOfRangeException("lumpNameChars.Count", lumpNameChars.Count,
                                                                          "Cannot be larger than 8 chars!");
                                }

                                var lumpPos = GetBytes(nl.Position);
                                var lumpSize = GetBytes(nl.Size);
                                var lumpName = lumpNameChars.ToArray();

                                temp.Write(lumpPos, 0, lumpPos.Length);
                                temp.Write(lumpSize, 0, lumpSize.Length);
                                temp.Write(lumpName, 0, lumpName.Length);
                            }

                            // update header
                            temp.Position = 4;
                            temp.Write(GetBytes(numberOfLumps), 0, 4);
                            temp.Write(GetBytes(posOfEntries), 0, 4);

                            temp.Position = 0;
                            return WADFileFactory.FromStream(temp, state.Format).Single();
                        }
                    },
                funcState: new
                    {
                        FirstLumpName = initialLumpName,
                        Format = format,
                    });
        }