/// <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; }
/// <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); }
/// <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, })); }
internal IWAD(WADFormat format, Stream stream, bool ownsStream = true, object sync = null) : base(format: format, stream: stream, ownsStream: ownsStream, sync: sync) { }
/// <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); }
/// <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, }); }