diff --git a/SharpCompress.Test/Tar/TarArchiveTests.cs b/SharpCompress.Test/Tar/TarArchiveTests.cs index b7a8124c..72a1e1ab 100644 --- a/SharpCompress.Test/Tar/TarArchiveTests.cs +++ b/SharpCompress.Test/Tar/TarArchiveTests.cs @@ -145,5 +145,16 @@ namespace SharpCompress.Test } CompareArchivesByPath(modified, scratchPath); } + + [TestMethod] + public void Tar_Containing_Rar_Archive() + { + string archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsRar.tar"); + using (Stream stream = File.OpenRead(archiveFullPath)) + using (IArchive archive = ArchiveFactory.Open(stream)) + { + Assert.IsTrue(archive.Type == ArchiveType.Tar); + } + } } } diff --git a/SharpCompress.Test/Tar/TarReaderTests.cs b/SharpCompress.Test/Tar/TarReaderTests.cs index 69963df5..af8e63bd 100644 --- a/SharpCompress.Test/Tar/TarReaderTests.cs +++ b/SharpCompress.Test/Tar/TarReaderTests.cs @@ -2,6 +2,7 @@ using System.IO; using Microsoft.VisualStudio.TestTools.UnitTesting; using SharpCompress.Common; +using SharpCompress.Reader; using SharpCompress.Reader.Tar; namespace SharpCompress.Test @@ -88,5 +89,16 @@ namespace SharpCompress.Test Assert.AreEqual(names.Count, 3); } } + + [TestMethod] + public void Tar_Containing_Rar_Reader() + { + string archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsRar.tar"); + using (Stream stream = File.OpenRead(archiveFullPath)) + using (IReader reader = ReaderFactory.Open(stream)) + { + Assert.IsTrue(reader.ArchiveType == ArchiveType.Tar); + } + } } } diff --git a/SharpCompress/Archive/ArchiveFactory.cs b/SharpCompress/Archive/ArchiveFactory.cs index 278e9e10..8dddbe82 100644 --- a/SharpCompress/Archive/ArchiveFactory.cs +++ b/SharpCompress/Archive/ArchiveFactory.cs @@ -43,7 +43,7 @@ namespace SharpCompress.Archive return GZipArchive.Open(stream, options); } stream.Seek(0, SeekOrigin.Begin); - if(RarArchive.IsRarFile(stream, Options.LookForHeader | Options.KeepStreamsOpen)) + if (RarArchive.IsRarFile(stream, options)) { stream.Seek(0, SeekOrigin.Begin); return RarArchive.Open(stream, options); @@ -138,7 +138,7 @@ namespace SharpCompress.Archive return GZipArchive.Open(fileInfo, options); } stream.Seek(0, SeekOrigin.Begin); - if(RarArchive.IsRarFile(stream, Options.LookForHeader | Options.KeepStreamsOpen)) + if (RarArchive.IsRarFile(stream, options)) { stream.Dispose(); return RarArchive.Open(fileInfo, options); diff --git a/SharpCompress/Archive/Rar/FileInfoRarFilePart.cs b/SharpCompress/Archive/Rar/FileInfoRarFilePart.cs index 558cd14a..8c64e3b3 100644 --- a/SharpCompress/Archive/Rar/FileInfoRarFilePart.cs +++ b/SharpCompress/Archive/Rar/FileInfoRarFilePart.cs @@ -6,12 +6,9 @@ namespace SharpCompress.Archive.Rar { internal class FileInfoRarFilePart : SeekableFilePart { - private readonly FileInfoRarArchiveVolume volume; - internal FileInfoRarFilePart(FileInfoRarArchiveVolume volume, MarkHeader mh, FileHeader fh, FileInfo fi) : base(mh, fh, volume.Stream, volume.Password) { - this.volume = volume; FileInfo = fi; } diff --git a/SharpCompress/Archive/Rar/RarArchive.cs b/SharpCompress/Archive/Rar/RarArchive.cs index 4eaada0a..0eff6bc5 100644 --- a/SharpCompress/Archive/Rar/RarArchive.cs +++ b/SharpCompress/Archive/Rar/RarArchive.cs @@ -14,9 +14,6 @@ namespace SharpCompress.Archive.Rar { public class RarArchive : AbstractArchive { - internal IEnumerator SolidEntryEnumerator; - internal List SolidReadedEntries=new List(); - private readonly Unpack unpack = new Unpack(); internal Unpack Unpack @@ -155,12 +152,8 @@ namespace SharpCompress.Archive.Rar try { var headerFactory = new RarHeaderFactory(StreamingMode.Seekable, options); - RarHeader header = headerFactory.ReadHeaders(stream).FirstOrDefault(); - if (header == null) - { - return false; - } - return Enum.IsDefined(typeof (HeaderType), header.HeaderType); + var markHeader = headerFactory.ReadHeaders(stream).FirstOrDefault() as MarkHeader; + return markHeader != null && markHeader.IsValid(); } catch { diff --git a/SharpCompress/Archive/Rar/RarArchiveEntry.cs b/SharpCompress/Archive/Rar/RarArchiveEntry.cs index ab033514..9b69100b 100644 --- a/SharpCompress/Archive/Rar/RarArchiveEntry.cs +++ b/SharpCompress/Archive/Rar/RarArchiveEntry.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -70,43 +71,12 @@ namespace SharpCompress.Archive.Rar return parts.Aggregate(0L, (total, fp) => { return total + fp.FileHeader.CompressedSize; }); } } - private readonly byte[] skipBuffer = new byte[4096]; - private void Skip(RarArchiveEntry en) - { - using (var s = new RarStream(archive.Unpack, en.FileHeader, new MultiVolumeReadOnlyStream(en.parts, archive))) - { - while (s.Read(skipBuffer, 0, skipBuffer.Length) > 0); - } - } - - private void MoveNext() - { - archive.SolidReadedEntries.Add(archive.SolidEntryEnumerator.Current); - if (!archive.SolidEntryEnumerator.MoveNext()) - { - archive.SolidEntryEnumerator = archive.Entries.GetEnumerator(); - archive.SolidReadedEntries = new List(); - archive.SolidEntryEnumerator.MoveNext(); - } - } public Stream OpenEntryStream() { if (archive.IsSolid) { - - if ((archive.SolidEntryEnumerator == null) || (archive.SolidReadedEntries.Any(b=>b.FileHeader==FileHeader))) - { - archive.SolidEntryEnumerator = archive.Entries.GetEnumerator(); - archive.SolidReadedEntries = new List(); - archive.SolidEntryEnumerator.MoveNext(); - } - while (archive.SolidEntryEnumerator.Current.FileHeader != FileHeader) - { - Skip(archive.SolidEntryEnumerator.Current); - MoveNext(); - } - MoveNext(); + throw new InvalidOperationException("Use ExtractAllEntries to extract SOLID archives."); } return new RarStream(archive.Unpack, FileHeader, new MultiVolumeReadOnlyStream(Parts.Cast(), archive)); } diff --git a/SharpCompress/Archive/SevenZip/SevenZipArchiveEntry.cs b/SharpCompress/Archive/SevenZip/SevenZipArchiveEntry.cs index ca893e22..c5c2aaba 100644 --- a/SharpCompress/Archive/SevenZip/SevenZipArchiveEntry.cs +++ b/SharpCompress/Archive/SevenZip/SevenZipArchiveEntry.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using SharpCompress.Common.SevenZip; namespace SharpCompress.Archive.SevenZip diff --git a/SharpCompress/Common/GZip/GZipFilePart.cs b/SharpCompress/Common/GZip/GZipFilePart.cs index 5aab3dba..673e50ea 100644 --- a/SharpCompress/Common/GZip/GZipFilePart.cs +++ b/SharpCompress/Common/GZip/GZipFilePart.cs @@ -3,6 +3,7 @@ using System.IO; using SharpCompress.Common.Tar.Headers; using SharpCompress.Compressor; using SharpCompress.Compressor.Deflate; +using SharpCompress.Converter; namespace SharpCompress.Common.GZip { @@ -50,7 +51,7 @@ namespace SharpCompress.Common.GZip if (header[0] != 0x1F || header[1] != 0x8B || header[2] != 8) throw new ZlibException("Bad GZIP header."); - Int32 timet = BitConverter.ToInt32(header, 4); + Int32 timet = DataConverter.LittleEndian.GetInt32(header, 4); DateModified = TarHeader.Epoch.AddSeconds(timet); if ((header[3] & 0x04) == 0x04) { diff --git a/SharpCompress/Common/GZip/GZipVolume.cs b/SharpCompress/Common/GZip/GZipVolume.cs index 82c7fd7f..0b49f649 100644 --- a/SharpCompress/Common/GZip/GZipVolume.cs +++ b/SharpCompress/Common/GZip/GZipVolume.cs @@ -4,10 +4,6 @@ namespace SharpCompress.Common.GZip { public class GZipVolume : Volume { -#if !PORTABLE && !NETFX_CORE - private readonly FileInfo fileInfo; -#endif - public GZipVolume(Stream stream, Options options) : base(stream, options) { @@ -17,7 +13,6 @@ namespace SharpCompress.Common.GZip public GZipVolume(FileInfo fileInfo, Options options) : base(fileInfo.OpenRead(), options) { - this.fileInfo = fileInfo; } #endif diff --git a/SharpCompress/Common/Rar/Headers/MarkHeader.cs b/SharpCompress/Common/Rar/Headers/MarkHeader.cs index 41214b46..9df32170 100644 --- a/SharpCompress/Common/Rar/Headers/MarkHeader.cs +++ b/SharpCompress/Common/Rar/Headers/MarkHeader.cs @@ -10,48 +10,15 @@ namespace SharpCompress.Common.Rar.Headers internal bool IsValid() { - if (!(HeadCRC == 0x6152)) - { - return false; - } - if (!(HeaderType == HeaderType.MarkHeader)) - { - return false; - } - if (!(Flags == 0x1a21)) - { - return false; - } - if (!(HeaderSize == BaseBlockSize)) - { - return false; - } - return true; - } + // Rar old signature: 52 45 7E 5E (not supported) - internal bool IsSignature() - { - bool valid = false; - /*byte[] d = new byte[BaseBlock.BaseBlockSize]; - BinaryWriter writer = new BinaryWriter(); - writer.Write(HeadCRC); - writer.Write((byte)HeaderType); - writer.Write(flags); - writer.Write(HeaderSize); - writer.Flush - - if (d[0] == 0x52) { - if (d[1]==0x45 && d[2]==0x7e && d[3]==0x5e) { - oldFormat=true; - valid=true; - } - else if (d[1]==0x61 && d[2]==0x72 && d[3]==0x21 && d[4]==0x1a && - d[5]==0x07 && d[6]==0x00) { - oldFormat=false; - valid=true; - } - }*/ - return valid; + // Rar4 signature: 52 61 72 21 1A 07 00 + return HeadCRC == 0x6152 && + HeaderType == HeaderType.MarkHeader && + Flags == 0x1A21 && + HeaderSize == 0x07; + + // Rar5 signature: 52 61 72 21 1A 07 10 00 (not supported yet) } internal bool OldFormat { get; private set; } diff --git a/SharpCompress/Common/SevenZip/ArchiveReader.cs b/SharpCompress/Common/SevenZip/ArchiveReader.cs index 31455ca3..0196120b 100644 --- a/SharpCompress/Common/SevenZip/ArchiveReader.cs +++ b/SharpCompress/Common/SevenZip/ArchiveReader.cs @@ -1198,14 +1198,12 @@ namespace SharpCompress.Common.SevenZip private class FolderUnpackStream : Stream { private ArchiveDatabase _db; - private int _otherIndex; private int _startIndex; private List _extractStatuses; public FolderUnpackStream(ArchiveDatabase db, int p, int startIndex, List list) { this._db = db; - this._otherIndex = p; this._startIndex = startIndex; this._extractStatuses = list; } @@ -1275,12 +1273,7 @@ namespace SharpCompress.Common.SevenZip private void OpenFile() { - bool skip = !_extractStatuses[_currentIndex]; int index = _startIndex + _currentIndex; - int realIndex = _otherIndex + index; - //string filename = @"D:\_testdump\" + _db.Files[index].Name; - //Directory.CreateDirectory(Path.GetDirectoryName(filename)); - //_stream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Delete); #if DEBUG Log.WriteLine(_db.Files[index].Name); #endif diff --git a/SharpCompress/Common/SevenZip/DataReader.cs b/SharpCompress/Common/SevenZip/DataReader.cs index 2b6f27cd..fe8d6435 100644 --- a/SharpCompress/Common/SevenZip/DataReader.cs +++ b/SharpCompress/Common/SevenZip/DataReader.cs @@ -34,7 +34,6 @@ namespace SharpCompress.Common.SevenZip #region Variables private byte[] _buffer; - private int _origin; private int _offset; private int _ending; @@ -45,7 +44,6 @@ namespace SharpCompress.Common.SevenZip public DataReader(byte[] buffer, int offset, int length) { _buffer = buffer; - _origin = offset; _offset = offset; _ending = offset + length; } diff --git a/SharpCompress/Common/Tar/Headers/TarHeader.cs b/SharpCompress/Common/Tar/Headers/TarHeader.cs index 8323fc3f..fa59c1c3 100644 --- a/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -4,6 +4,7 @@ using System.IO; using System.Net; #endif using System.Text; +using SharpCompress.Converter; namespace SharpCompress.Common.Tar.Headers { @@ -64,11 +65,7 @@ namespace SharpCompress.Common.Tar.Headers if (Size >= 0x1FFFFFFFF) { -#if PORTABLE || NETFX_CORE - byte[] bytes = BitConverter.GetBytes(Utility.HostToNetworkOrder(Size)); -#else - byte[] bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(Size)); -#endif + byte[] bytes = DataConverter.BigEndian.GetBytes(Size); var bytes12 = new byte[12]; bytes.CopyTo(bytes12, 12 - bytes.Length); bytes12[0] |= 0x80; @@ -119,12 +116,7 @@ namespace SharpCompress.Common.Tar.Headers EntryType = (EntryType) buffer[156]; if ((buffer[124] & 0x80) == 0x80) // if size in binary { - long sizeBigEndian = BitConverter.ToInt64(buffer, 0x80); -#if PORTABLE || NETFX_CORE - Size = Utility.NetworkToHostOrder(sizeBigEndian); -#else - Size = IPAddress.NetworkToHostOrder(sizeBigEndian); -#endif + Size = DataConverter.BigEndian.GetInt64(buffer, 0x80); } else { diff --git a/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs b/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs index f5a813ed..08b4772e 100644 --- a/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs +++ b/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Text; +using SharpCompress.Converter; namespace SharpCompress.Common.Zip.Headers { @@ -68,13 +69,13 @@ namespace SharpCompress.Common.Zip.Headers { for (int i = 0; i < extra.Length-4;) { - ExtraDataType type = (ExtraDataType) BitConverter.ToUInt16(extra, i); + ExtraDataType type = (ExtraDataType)DataConverter.LittleEndian.GetUInt16(extra, i); if (!Enum.IsDefined(typeof (ExtraDataType), type)) { type = ExtraDataType.NotImplementedExtraData; } - ushort length = BitConverter.ToUInt16(extra, i + 2); + ushort length = DataConverter.LittleEndian.GetUInt16(extra, i + 2); byte[] data = new byte[length]; Buffer.BlockCopy(extra, i + 4, data, 0, length); Extra.Add(LocalEntryHeaderExtraFactory.Create(type,length,data)); diff --git a/SharpCompress/Common/Zip/WinzipAesCryptoStream.Portable.cs b/SharpCompress/Common/Zip/WinzipAesCryptoStream.Portable.cs index 1acbeefd..8611a76a 100644 --- a/SharpCompress/Common/Zip/WinzipAesCryptoStream.Portable.cs +++ b/SharpCompress/Common/Zip/WinzipAesCryptoStream.Portable.cs @@ -3,6 +3,7 @@ using System.IO; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Parameters; +using SharpCompress.Converter; namespace SharpCompress.Common.Zip { @@ -113,7 +114,7 @@ namespace SharpCompress.Common.Zip : bytesRemaining; // update the counter - Array.Copy(BitConverter.GetBytes(nonce++), 0, counter, 0, 4); + DataConverter.LittleEndian.PutBytes(counter, 0, nonce++); // Determine if this is the final block if ((bytesToRead == bytesRemaining) && (totalBytesLeftToRead == 0)) diff --git a/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs b/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs index 9d8e14ca..ead9d548 100644 --- a/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs +++ b/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Security.Cryptography; +using SharpCompress.Converter; namespace SharpCompress.Common.Zip { @@ -117,7 +118,7 @@ namespace SharpCompress.Common.Zip : bytesRemaining; // update the counter - Array.Copy(BitConverter.GetBytes(nonce++), 0, counter, 0, 4); + DataConverter.LittleEndian.PutBytes(counter, 0, nonce++); // Determine if this is the final block if ((bytesToRead == bytesRemaining) && (totalBytesLeftToRead == 0)) diff --git a/SharpCompress/Common/Zip/WinzipAesEncryptionData.Portable.cs b/SharpCompress/Common/Zip/WinzipAesEncryptionData.Portable.cs index 0fe7050d..79a405cc 100644 --- a/SharpCompress/Common/Zip/WinzipAesEncryptionData.Portable.cs +++ b/SharpCompress/Common/Zip/WinzipAesEncryptionData.Portable.cs @@ -1,5 +1,6 @@ using System; using System.Text; +using SharpCompress.Converter; using SharpCompress.Crypto; namespace SharpCompress.Common.Zip @@ -56,10 +57,10 @@ namespace SharpCompress.Common.Zip generatedVerifyValue = paramz.GetBytes(2); - short verify = BitConverter.ToInt16(passwordVerifyValue, 0); + short verify = DataConverter.LittleEndian.GetInt16(passwordVerifyValue, 0); if (password != null) { - short generated = BitConverter.ToInt16(generatedVerifyValue, 0); + short generated = DataConverter.LittleEndian.GetInt16(generatedVerifyValue, 0); if (verify != generated) throw new InvalidFormatException("bad password"); } diff --git a/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs b/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs index eb37ac98..a5de3294 100644 --- a/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs +++ b/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs @@ -1,4 +1,5 @@ using System; +using SharpCompress.Converter; namespace SharpCompress.Common.Zip { @@ -54,10 +55,10 @@ namespace SharpCompress.Common.Zip IvBytes = rfc2898.GetBytes(KeySizeInBytes); generatedVerifyValue = rfc2898.GetBytes(2); - short verify = BitConverter.ToInt16(passwordVerifyValue, 0); + short verify = DataConverter.LittleEndian.GetInt16(passwordVerifyValue, 0); if (password != null) { - short generated = BitConverter.ToInt16(generatedVerifyValue, 0); + short generated = DataConverter.LittleEndian.GetInt16(generatedVerifyValue, 0); if (verify != generated) throw new InvalidFormatException("bad password"); } diff --git a/SharpCompress/Common/Zip/ZipFilePart.cs b/SharpCompress/Common/Zip/ZipFilePart.cs index 6052d593..43ec7122 100644 --- a/SharpCompress/Common/Zip/ZipFilePart.cs +++ b/SharpCompress/Common/Zip/ZipFilePart.cs @@ -7,6 +7,7 @@ using SharpCompress.Compressor.BZip2; using SharpCompress.Compressor.Deflate; using SharpCompress.Compressor.LZMA; using SharpCompress.Compressor.PPMd; +using SharpCompress.Converter; using SharpCompress.IO; namespace SharpCompress.Common.Zip @@ -108,19 +109,19 @@ namespace SharpCompress.Common.Zip { throw new InvalidFormatException("Winzip data length is not 7."); } - ushort method = BitConverter.ToUInt16(data.DataBytes, 0); + ushort method = DataConverter.LittleEndian.GetUInt16(data.DataBytes, 0); if (method != 0x01 && method != 0x02) { throw new InvalidFormatException("Unexpected vendor version number for WinZip AES metadata"); } - ushort vendorId = BitConverter.ToUInt16(data.DataBytes, 2); + ushort vendorId = DataConverter.LittleEndian.GetUInt16(data.DataBytes, 2); if (vendorId != 0x4541) { throw new InvalidFormatException("Unexpected vendor ID for WinZip AES metadata"); } - Header.CompressionMethod = (ZipCompressionMethod)BitConverter.ToUInt16(data.DataBytes, 5); + Header.CompressionMethod = (ZipCompressionMethod)DataConverter.LittleEndian.GetUInt16(data.DataBytes, 5); return CreateDecompressionStream(stream); } default: diff --git a/SharpCompress/Compressor/Deflate/GZipStream.cs b/SharpCompress/Compressor/Deflate/GZipStream.cs index 7b3215d9..308bc692 100644 --- a/SharpCompress/Compressor/Deflate/GZipStream.cs +++ b/SharpCompress/Compressor/Deflate/GZipStream.cs @@ -30,6 +30,7 @@ using System; using System.IO; using SharpCompress.Common; +using SharpCompress.Converter; namespace SharpCompress.Compressor.Deflate { @@ -417,7 +418,7 @@ namespace SharpCompress.Compressor.Deflate LastModified = DateTime.Now; TimeSpan delta = LastModified.Value - UnixEpoch; var timet = (Int32) delta.TotalSeconds; - Array.Copy(BitConverter.GetBytes(timet), 0, header, i, 4); + DataConverter.LittleEndian.PutBytes(header, i, timet); i += 4; // xflg diff --git a/SharpCompress/Compressor/Deflate/ZlibBaseStream.cs b/SharpCompress/Compressor/Deflate/ZlibBaseStream.cs index 1bfe1f6e..7d753dff 100644 --- a/SharpCompress/Compressor/Deflate/ZlibBaseStream.cs +++ b/SharpCompress/Compressor/Deflate/ZlibBaseStream.cs @@ -27,6 +27,7 @@ using System; using SharpCompress.Common; using SharpCompress.Common.Tar.Headers; +using SharpCompress.Converter; namespace SharpCompress.Compressor.Deflate { @@ -221,9 +222,9 @@ namespace SharpCompress.Compressor.Deflate { // Emit the GZIP trailer: CRC32 and size mod 2^32 int c1 = crc.Crc32Result; - _stream.Write(BitConverter.GetBytes(c1), 0, 4); + _stream.Write(DataConverter.LittleEndian.GetBytes(c1), 0, 4); int c2 = (Int32)(crc.TotalBytesRead & 0x00000000FFFFFFFF); - _stream.Write(BitConverter.GetBytes(c2), 0, 4); + _stream.Write(DataConverter.LittleEndian.GetBytes(c2), 0, 4); } else { @@ -267,9 +268,9 @@ namespace SharpCompress.Compressor.Deflate } - Int32 crc32_expected = BitConverter.ToInt32(trailer, 0); + Int32 crc32_expected = DataConverter.LittleEndian.GetInt32(trailer, 0); Int32 crc32_actual = crc.Crc32Result; - Int32 isize_expected = BitConverter.ToInt32(trailer, 4); + Int32 isize_expected = DataConverter.LittleEndian.GetInt32(trailer, 4); Int32 isize_actual = (Int32)(_z.TotalBytesOut & 0x00000000FFFFFFFF); if (crc32_actual != crc32_expected) @@ -405,7 +406,7 @@ namespace SharpCompress.Compressor.Deflate if (header[0] != 0x1F || header[1] != 0x8B || header[2] != 8) throw new ZlibException("Bad GZIP header."); - Int32 timet = BitConverter.ToInt32(header, 4); + Int32 timet = DataConverter.LittleEndian.GetInt32(header, 4); _GzipMtime = TarHeader.Epoch.AddSeconds(timet); totalBytesRead += n; if ((header[3] & 0x04) == 0x04) diff --git a/SharpCompress/Compressor/LZMA/Bcj2DecoderStream.cs b/SharpCompress/Compressor/LZMA/Bcj2DecoderStream.cs index c13f34b6..8034cd7a 100644 --- a/SharpCompress/Compressor/LZMA/Bcj2DecoderStream.cs +++ b/SharpCompress/Compressor/LZMA/Bcj2DecoderStream.cs @@ -99,7 +99,6 @@ namespace SharpCompress.Compressor.LZMA private RangeDecoder mRangeDecoder; private StatusDecoder[] mStatusDecoder; private long mWritten; - private long mLimit; private IEnumerator mIter; private bool mFinished; private bool isDisposed; @@ -112,7 +111,6 @@ namespace SharpCompress.Compressor.LZMA if (streams.Length != 4) throw new NotSupportedException(); - mLimit = limit; mMainStream = streams[0]; mCallStream = streams[1]; mJumpStream = streams[2]; diff --git a/SharpCompress/Compressor/LZMA/LzmaStream.cs b/SharpCompress/Compressor/LZMA/LzmaStream.cs index 22522f9d..bc046e70 100644 --- a/SharpCompress/Compressor/LZMA/LzmaStream.cs +++ b/SharpCompress/Compressor/LZMA/LzmaStream.cs @@ -1,6 +1,7 @@ using System; using System.IO; using SharpCompress.Compressor.LZMA.LZ; +using SharpCompress.Converter; namespace SharpCompress.Compressor.LZMA { @@ -56,7 +57,7 @@ namespace SharpCompress.Compressor.LZMA if (!isLZMA2) { - dictionarySize = BitConverter.ToInt32(properties, 1); + dictionarySize = DataConverter.LittleEndian.GetInt32(properties, 1); outWindow.Create(dictionarySize); if (presetDictionary != null) outWindow.Train(presetDictionary); diff --git a/SharpCompress/Compressor/PPMd/H/FreqData.cs b/SharpCompress/Compressor/PPMd/H/FreqData.cs index a37ea93a..b94e01dd 100644 --- a/SharpCompress/Compressor/PPMd/H/FreqData.cs +++ b/SharpCompress/Compressor/PPMd/H/FreqData.cs @@ -1,4 +1,5 @@ using System.Text; +using SharpCompress.Converter; namespace SharpCompress.Compressor.PPMd.H { @@ -19,9 +20,9 @@ namespace SharpCompress.Compressor.PPMd.H internal int SummFreq { - get { return Utility.readShortLittleEndian(Memory, Address) & 0xffff; } + get { return DataConverter.LittleEndian.GetInt16(Memory, Address) & 0xffff; } - set { Utility.WriteLittleEndian(Memory, Address, (short) value); } + set { DataConverter.LittleEndian.PutBytes(Memory, Address, (short)value); } } internal FreqData Initialize(byte[] mem) @@ -31,12 +32,14 @@ namespace SharpCompress.Compressor.PPMd.H internal void IncrementSummFreq(int dSummFreq) { - Utility.incShortLittleEndian(Memory, Address, (short) dSummFreq); + short summFreq = DataConverter.LittleEndian.GetInt16(Memory, Address); + summFreq += (short)dSummFreq; + DataConverter.LittleEndian.PutBytes(Memory, Address, summFreq); } internal int GetStats() { - return Utility.readIntLittleEndian(Memory, Address + 2); + return DataConverter.LittleEndian.GetInt32(Memory, Address + 2); } internal virtual void SetStats(State state) @@ -46,7 +49,7 @@ namespace SharpCompress.Compressor.PPMd.H internal void SetStats(int state) { - Utility.WriteLittleEndian(Memory, Address + 2, state); + DataConverter.LittleEndian.PutBytes(Memory, Address + 2, state); } public override System.String ToString() diff --git a/SharpCompress/Compressor/PPMd/H/PPMContext.cs b/SharpCompress/Compressor/PPMd/H/PPMContext.cs index 8b36bf6d..f2029f96 100644 --- a/SharpCompress/Compressor/PPMd/H/PPMContext.cs +++ b/SharpCompress/Compressor/PPMd/H/PPMContext.cs @@ -1,4 +1,5 @@ using System.Text; +using SharpCompress.Converter; namespace SharpCompress.Compressor.PPMd.H { @@ -21,7 +22,7 @@ namespace SharpCompress.Compressor.PPMd.H { if (Memory != null) { - numStats = Utility.readShortLittleEndian(Memory, Address) & 0xffff; + numStats = DataConverter.LittleEndian.GetInt16(Memory, Address) & 0xffff; } return numStats; } @@ -31,7 +32,7 @@ namespace SharpCompress.Compressor.PPMd.H this.numStats = value & 0xffff; if (Memory != null) { - Utility.WriteLittleEndian(Memory, Address, (short) value); + DataConverter.LittleEndian.PutBytes(Memory, Address, (short) value); } } } @@ -103,7 +104,7 @@ namespace SharpCompress.Compressor.PPMd.H { if (Memory != null) { - suffix = Utility.readIntLittleEndian(Memory, Address + 8); + suffix = DataConverter.LittleEndian.GetInt32(Memory, Address + 8); } return suffix; } @@ -118,7 +119,7 @@ namespace SharpCompress.Compressor.PPMd.H this.suffix = suffix; if (Memory != null) { - Utility.WriteLittleEndian(Memory, Address + 8, suffix); + DataConverter.LittleEndian.PutBytes(Memory, Address + 8, suffix); } } diff --git a/SharpCompress/Compressor/PPMd/H/RarMemBlock.cs b/SharpCompress/Compressor/PPMd/H/RarMemBlock.cs index 52f601d8..0a71c529 100644 --- a/SharpCompress/Compressor/PPMd/H/RarMemBlock.cs +++ b/SharpCompress/Compressor/PPMd/H/RarMemBlock.cs @@ -1,3 +1,5 @@ +using SharpCompress.Converter; + namespace SharpCompress.Compressor.PPMd.H { internal class RarMemBlock : Pointer @@ -19,7 +21,7 @@ namespace SharpCompress.Compressor.PPMd.H { if (Memory != null) { - stamp = Utility.readShortLittleEndian(Memory, Address) & 0xffff; + stamp = DataConverter.LittleEndian.GetInt16(Memory, Address) & 0xffff; } return stamp; } @@ -29,7 +31,7 @@ namespace SharpCompress.Compressor.PPMd.H this.stamp = value; if (Memory != null) { - Utility.WriteLittleEndian(Memory, Address, (short) value); + DataConverter.LittleEndian.PutBytes(Memory, Address, (short)value); } } } @@ -60,7 +62,7 @@ namespace SharpCompress.Compressor.PPMd.H { if (Memory != null) { - next = Utility.readIntLittleEndian(Memory, Address + 4); + next = DataConverter.LittleEndian.GetInt32(Memory, Address + 4); } return next; } @@ -75,7 +77,7 @@ namespace SharpCompress.Compressor.PPMd.H this.next = next; if (Memory != null) { - Utility.WriteLittleEndian(Memory, Address + 4, next); + DataConverter.LittleEndian.PutBytes(Memory, Address + 4, next); } } @@ -83,7 +85,7 @@ namespace SharpCompress.Compressor.PPMd.H { if (Memory != null) { - NU = Utility.readShortLittleEndian(Memory, Address + 2) & 0xffff; + NU = DataConverter.LittleEndian.GetInt16(Memory, Address + 2) & 0xffff; } return NU; } @@ -93,7 +95,7 @@ namespace SharpCompress.Compressor.PPMd.H NU = nu & 0xffff; if (Memory != null) { - Utility.WriteLittleEndian(Memory, Address + 2, (short) nu); + DataConverter.LittleEndian.PutBytes(Memory, Address + 2, (short)nu); } } @@ -101,7 +103,7 @@ namespace SharpCompress.Compressor.PPMd.H { if (Memory != null) { - prev = Utility.readIntLittleEndian(Memory, Address + 8); + prev = DataConverter.LittleEndian.GetInt32(Memory, Address + 8); } return prev; } @@ -116,7 +118,7 @@ namespace SharpCompress.Compressor.PPMd.H this.prev = prev; if (Memory != null) { - Utility.WriteLittleEndian(Memory, Address + 8, prev); + DataConverter.LittleEndian.PutBytes(Memory, Address + 8, prev); } } } diff --git a/SharpCompress/Compressor/PPMd/H/RarNode.cs b/SharpCompress/Compressor/PPMd/H/RarNode.cs index 2369fb5a..ffb75c50 100644 --- a/SharpCompress/Compressor/PPMd/H/RarNode.cs +++ b/SharpCompress/Compressor/PPMd/H/RarNode.cs @@ -1,4 +1,5 @@ using System.Text; +using SharpCompress.Converter; namespace SharpCompress.Compressor.PPMd.H { @@ -17,7 +18,7 @@ namespace SharpCompress.Compressor.PPMd.H { if (Memory != null) { - next = Utility.readIntLittleEndian(Memory, Address); + next = DataConverter.LittleEndian.GetInt32(Memory, Address); } return next; } @@ -32,7 +33,7 @@ namespace SharpCompress.Compressor.PPMd.H this.next = next; if (Memory != null) { - Utility.WriteLittleEndian(Memory, Address, next); + DataConverter.LittleEndian.PutBytes(Memory, Address, next); } } diff --git a/SharpCompress/Compressor/PPMd/H/State.cs b/SharpCompress/Compressor/PPMd/H/State.cs index a459321e..687883c4 100644 --- a/SharpCompress/Compressor/PPMd/H/State.cs +++ b/SharpCompress/Compressor/PPMd/H/State.cs @@ -1,5 +1,6 @@ using System; using System.Text; +using SharpCompress.Converter; namespace SharpCompress.Compressor.PPMd.H { @@ -38,7 +39,7 @@ namespace SharpCompress.Compressor.PPMd.H internal int GetSuccessor() { - return Utility.readIntLittleEndian(Memory, Address + 2); + return DataConverter.LittleEndian.GetInt32(Memory, Address + 2); } internal void SetSuccessor(PPMContext successor) @@ -48,7 +49,7 @@ namespace SharpCompress.Compressor.PPMd.H internal void SetSuccessor(int successor) { - Utility.WriteLittleEndian(Memory, Address + 2, successor); + DataConverter.LittleEndian.PutBytes(Memory, Address + 2, successor); } internal void SetValues(StateRef state) diff --git a/SharpCompress/Compressor/PPMd/PpmdProperties.cs b/SharpCompress/Compressor/PPMd/PpmdProperties.cs index 9527835b..5875bcac 100644 --- a/SharpCompress/Compressor/PPMd/PpmdProperties.cs +++ b/SharpCompress/Compressor/PPMd/PpmdProperties.cs @@ -1,4 +1,5 @@ using System; +using SharpCompress.Converter; namespace SharpCompress.Compressor.PPMd { @@ -39,7 +40,7 @@ namespace SharpCompress.Compressor.PPMd { if (properties.Length == 2) { - ushort props = BitConverter.ToUInt16(properties, 0); + ushort props = DataConverter.LittleEndian.GetUInt16(properties, 0); AllocatorSize = (((props >> 4) & 0xff) + 1) << 20; ModelOrder = (props & 0x0f) + 1; ModelRestorationMethod = (I1.ModelRestorationMethod) (props >> 12); @@ -47,7 +48,7 @@ namespace SharpCompress.Compressor.PPMd else if (properties.Length == 5) { Version = PpmdVersion.H7z; - AllocatorSize = BitConverter.ToInt32(properties, 1); + AllocatorSize = DataConverter.LittleEndian.GetInt32(properties, 1); ModelOrder = properties[0]; } } @@ -72,7 +73,7 @@ namespace SharpCompress.Compressor.PPMd get { return - BitConverter.GetBytes( + DataConverter.LittleEndian.GetBytes( (ushort) ((ModelOrder - 1) + (((AllocatorSize >> 20) - 1) << 4) + ((ushort) ModelRestorationMethod << 12))); } diff --git a/SharpCompress/Compressor/Rar/VM/RarVM.cs b/SharpCompress/Compressor/Rar/VM/RarVM.cs index f1f25d34..27990a33 100644 --- a/SharpCompress/Compressor/Rar/VM/RarVM.cs +++ b/SharpCompress/Compressor/Rar/VM/RarVM.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using SharpCompress.Converter; namespace SharpCompress.Compressor.Rar.VM { @@ -77,11 +78,12 @@ namespace SharpCompress.Compressor.Rar.VM { if (IsVMMem(mem)) { - return Utility.readIntLittleEndian(mem, offset); + return DataConverter.LittleEndian.GetInt32(mem, offset); } else { - return Utility.readIntBigEndian(mem, offset); + return DataConverter.BigEndian.GetInt32(mem, offset); + } } } @@ -103,19 +105,11 @@ namespace SharpCompress.Compressor.Rar.VM { if (IsVMMem(mem)) { - Utility.WriteLittleEndian(mem, offset, value); - // Mem[offset + 0] = (byte) value; - // Mem[offset + 1] = (byte) (value >>> 8); - // Mem[offset + 2] = (byte) (value >>> 16); - // Mem[offset + 3] = (byte) (value >>> 24); + DataConverter.LittleEndian.PutBytes(mem, offset, value); } else { - Utility.writeIntBigEndian(mem, offset, value); - // Mem[offset + 3] = (byte) value; - // Mem[offset + 2] = (byte) (value >>> 8); - // Mem[offset + 1] = (byte) (value >>> 16); - // Mem[offset + 0] = (byte) (value >>> 24); + DataConverter.BigEndian.PutBytes(mem, offset, value); } } // #define SET_VALUE(ByteMode,Addr,Value) SetValue(ByteMode,(uint @@ -136,12 +130,12 @@ namespace SharpCompress.Compressor.Rar.VM if (cmdOp.Type == VMOpType.VM_OPREGMEM) { int pos = (cmdOp.Offset + cmdOp.Base) & VM_MEMMASK; - ret = Utility.readIntLittleEndian(Mem, pos); + ret = DataConverter.LittleEndian.GetInt32(Mem, pos); } else { int pos = cmdOp.Offset; - ret = Utility.readIntLittleEndian(Mem, pos); + ret = DataConverter.LittleEndian.GetInt32(Mem, pos); } return ret; } diff --git a/SharpCompress/Converter/DataConverter.Portable.cs b/SharpCompress/Converter/DataConverter.Portable.cs new file mode 100644 index 00000000..eec9846b --- /dev/null +++ b/SharpCompress/Converter/DataConverter.Portable.cs @@ -0,0 +1,237 @@ +using System; + +namespace SharpCompress.Converter +{ + // This is a portable version of Mono's DataConverter class with just the small subset of functionality + // needed by SharpCompress. Portable in this case means that it contains no unsafe code. + // + // This class simply wraps BitConverter and reverses byte arrays when endianess doesn't match the host's. + // + // Everything public in this class must match signatures in Mono's DataConverter. + + abstract class DataConverter + { + static readonly DataConverter copyConverter = new CopyConverter(); + static readonly DataConverter swapConverter = new SwapConverter(); + + static readonly bool isLittleEndian = BitConverter.IsLittleEndian; + + public static DataConverter LittleEndian + { + get { return isLittleEndian ? copyConverter : swapConverter; } + } + + public static DataConverter BigEndian + { + get { return isLittleEndian ? swapConverter : copyConverter; } + } + + public abstract Int16 GetInt16(byte[] data, int index); + public abstract UInt16 GetUInt16(byte[] data, int index); + public abstract Int32 GetInt32(byte[] data, int index); + public abstract UInt32 GetUInt32(byte[] data, int index); + public abstract Int64 GetInt64(byte[] data, int index); + public abstract UInt64 GetUInt64(byte[] data, int index); + + public abstract byte[] GetBytes(Int16 value); + public abstract byte[] GetBytes(UInt16 value); + public abstract byte[] GetBytes(Int32 value); + public abstract byte[] GetBytes(UInt32 value); + public abstract byte[] GetBytes(Int64 value); + public abstract byte[] GetBytes(UInt64 value); + + public void PutBytes(byte[] data, int index, Int16 value) + { + byte[] temp = GetBytes(value); + Array.Copy(temp, 0, data, index, 2); + } + + public void PutBytes(byte[] data, int index, UInt16 value) + { + byte[] temp = GetBytes(value); + Array.Copy(temp, 0, data, index, 2); + } + + public void PutBytes(byte[] data, int index, Int32 value) + { + byte[] temp = GetBytes(value); + Array.Copy(temp, 0, data, index, 4); + } + + public void PutBytes(byte[] data, int index, UInt32 value) + { + byte[] temp = GetBytes(value); + Array.Copy(temp, 0, data, index, 4); + } + + public void PutBytes(byte[] data, int index, Int64 value) + { + byte[] temp = GetBytes(value); + Array.Copy(temp, 0, data, index, 8); + } + + public void PutBytes(byte[] data, int index, UInt64 value) + { + byte[] temp = GetBytes(value); + Array.Copy(temp, 0, data, index, 8); + } + + // CopyConverter wraps BitConverter making all conversions host endian + class CopyConverter : DataConverter + { + public override Int16 GetInt16(byte[] data, int index) + { + return BitConverter.ToInt16(data, index); + } + + public override UInt16 GetUInt16(byte[] data, int index) + { + return BitConverter.ToUInt16(data, index); + } + + public override Int32 GetInt32(byte[] data, int index) + { + return BitConverter.ToInt32(data, index); + } + + public override UInt32 GetUInt32(byte[] data, int index) + { + return BitConverter.ToUInt32(data, index); + } + + public override Int64 GetInt64(byte[] data, int index) + { + return BitConverter.ToInt64(data, index); + } + + public override UInt64 GetUInt64(byte[] data, int index) + { + return BitConverter.ToUInt64(data, index); + } + + public override byte[] GetBytes(Int16 value) + { + return BitConverter.GetBytes(value); + } + + public override byte[] GetBytes(UInt16 value) + { + return BitConverter.GetBytes(value); + } + + public override byte[] GetBytes(Int32 value) + { + return BitConverter.GetBytes(value); + } + + public override byte[] GetBytes(UInt32 value) + { + return BitConverter.GetBytes(value); + } + + public override byte[] GetBytes(Int64 value) + { + return BitConverter.GetBytes(value); + } + + public override byte[] GetBytes(UInt64 value) + { + return BitConverter.GetBytes(value); + } + } + + // SwapConverter wraps and reverses BitConverter making all conversions the opposite of host endian + class SwapConverter : DataConverter + { + public override Int16 GetInt16(byte[] data, int index) + { + byte[] temp = new byte[2]; + Array.Copy(data, index, temp, 0, 2); + Array.Reverse(temp); + return BitConverter.ToInt16(temp, 0); + } + + public override UInt16 GetUInt16(byte[] data, int index) + { + byte[] temp = new byte[2]; + Array.Copy(data, index, temp, 0, 2); + Array.Reverse(temp); + return BitConverter.ToUInt16(temp, 0); + } + + public override Int32 GetInt32(byte[] data, int index) + { + byte[] temp = new byte[4]; + Array.Copy(data, index, temp, 0, 4); + Array.Reverse(temp); + return BitConverter.ToInt32(temp, 0); + } + + public override UInt32 GetUInt32(byte[] data, int index) + { + byte[] temp = new byte[4]; + Array.Copy(data, index, temp, 0, 4); + Array.Reverse(temp); + return BitConverter.ToUInt32(temp, 0); + } + + public override Int64 GetInt64(byte[] data, int index) + { + byte[] temp = new byte[8]; + Array.Copy(data, index, temp, 0, 8); + Array.Reverse(temp); + return BitConverter.ToInt64(temp, 0); + } + + public override UInt64 GetUInt64(byte[] data, int index) + { + byte[] temp = new byte[8]; + Array.Copy(data, index, temp, 0, 8); + Array.Reverse(temp); + return BitConverter.ToUInt64(temp, 0); + } + + public override byte[] GetBytes(Int16 value) + { + byte[] ret = BitConverter.GetBytes(value); + Array.Reverse(ret); + return ret; + } + + public override byte[] GetBytes(UInt16 value) + { + byte[] ret = BitConverter.GetBytes(value); + Array.Reverse(ret); + return ret; + } + + public override byte[] GetBytes(Int32 value) + { + byte[] ret = BitConverter.GetBytes(value); + Array.Reverse(ret); + return ret; + } + + public override byte[] GetBytes(UInt32 value) + { + byte[] ret = BitConverter.GetBytes(value); + Array.Reverse(ret); + return ret; + } + + public override byte[] GetBytes(Int64 value) + { + byte[] ret = BitConverter.GetBytes(value); + Array.Reverse(ret); + return ret; + } + + public override byte[] GetBytes(UInt64 value) + { + byte[] ret = BitConverter.GetBytes(value); + Array.Reverse(ret); + return ret; + } + } + } +} \ No newline at end of file diff --git a/SharpCompress/Converter/DataConverter.cs b/SharpCompress/Converter/DataConverter.cs new file mode 100644 index 00000000..0b2acd9f --- /dev/null +++ b/SharpCompress/Converter/DataConverter.cs @@ -0,0 +1,1849 @@ +// +// Authors: +// Miguel de Icaza (miguel@novell.com) +// +// See the following url for documentation: +// http://www.mono-project.com/Mono_DataConvert +// +// Compilation Options: +// MONO_DATACONVERTER_PUBLIC: +// Makes the class public instead of the default internal. +// +// MONO_DATACONVERTER_STATIC_METHODS: +// Exposes the public static methods. +// +// TODO: +// Support for "DoubleWordsAreSwapped" for ARM devices +// +// Copyright (C) 2006 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.Collections; +using System.Text; +using System.Collections.Generic; + +#pragma warning disable 3021 + +namespace SharpCompress.Converter { + +#if MONO_DATACONVERTER_PUBLIC + public +#endif + unsafe abstract class DataConverter { + +// Disables the warning: CLS compliance checking will not be performed on +// `XXXX' because it is not visible from outside this assembly +#pragma warning disable 3019 + static readonly DataConverter SwapConv = new SwapConverter (); + static readonly DataConverter CopyConv = new CopyConverter (); + + public static readonly bool IsLittleEndian = BitConverter.IsLittleEndian; + + public abstract double GetDouble (byte [] data, int index); + public abstract float GetFloat (byte [] data, int index); + public abstract long GetInt64 (byte [] data, int index); + public abstract int GetInt32 (byte [] data, int index); + + public abstract short GetInt16 (byte [] data, int index); + + [CLSCompliant (false)] + public abstract uint GetUInt32 (byte [] data, int index); + [CLSCompliant (false)] + public abstract ushort GetUInt16 (byte [] data, int index); + [CLSCompliant (false)] + public abstract ulong GetUInt64 (byte [] data, int index); + + public abstract void PutBytes (byte [] dest, int destIdx, double value); + public abstract void PutBytes (byte [] dest, int destIdx, float value); + public abstract void PutBytes (byte [] dest, int destIdx, int value); + public abstract void PutBytes (byte [] dest, int destIdx, long value); + public abstract void PutBytes (byte [] dest, int destIdx, short value); + + [CLSCompliant (false)] + public abstract void PutBytes (byte [] dest, int destIdx, ushort value); + [CLSCompliant (false)] + public abstract void PutBytes (byte [] dest, int destIdx, uint value); + [CLSCompliant (false)] + public abstract void PutBytes (byte [] dest, int destIdx, ulong value); + + public byte[] GetBytes (double value) + { + byte [] ret = new byte [8]; + PutBytes (ret, 0, value); + return ret; + } + + public byte[] GetBytes (float value) + { + byte [] ret = new byte [4]; + PutBytes (ret, 0, value); + return ret; + } + + public byte[] GetBytes (int value) + { + byte [] ret = new byte [4]; + PutBytes (ret, 0, value); + return ret; + } + + public byte[] GetBytes (long value) + { + byte [] ret = new byte [8]; + PutBytes (ret, 0, value); + return ret; + } + + public byte[] GetBytes (short value) + { + byte [] ret = new byte [2]; + PutBytes (ret, 0, value); + return ret; + } + + [CLSCompliant (false)] + public byte[] GetBytes (ushort value) + { + byte [] ret = new byte [2]; + PutBytes (ret, 0, value); + return ret; + } + + [CLSCompliant (false)] + public byte[] GetBytes (uint value) + { + byte [] ret = new byte [4]; + PutBytes (ret, 0, value); + return ret; + } + + [CLSCompliant (false)] + public byte[] GetBytes (ulong value) + { + byte [] ret = new byte [8]; + PutBytes (ret, 0, value); + return ret; + } + + static public DataConverter LittleEndian { + get { + return BitConverter.IsLittleEndian ? CopyConv : SwapConv; + } + } + + static public DataConverter BigEndian { + get { + return BitConverter.IsLittleEndian ? SwapConv : CopyConv; + } + } + + static public DataConverter Native { + get { + return CopyConv; + } + } + + static int Align (int current, int align) + { + return ((current + align - 1) / align) * align; + } + + class PackContext { + // Buffer + public byte [] buffer; + int next; + + public string description; + public int i; // position in the description + public DataConverter conv; + public int repeat; + + // + // if align == -1, auto align to the size of the byte array + // if align == 0, do not do alignment + // Any other values aligns to that particular size + // + public int align; + + public void Add (byte [] group) + { + //Console.WriteLine ("Adding {0} bytes to {1} (next={2}", group.Length, + // buffer == null ? "null" : buffer.Length.ToString (), next); + + if (buffer == null){ + buffer = group; + next = group.Length; + return; + } + if (align != 0){ + if (align == -1) + next = Align (next, group.Length); + else + next = Align (next, align); + align = 0; + } + + if (next + group.Length > buffer.Length){ + byte [] nb = new byte [System.Math.Max (next, 16) * 2 + group.Length]; + Array.Copy (buffer, nb, buffer.Length); + Array.Copy (group, 0, nb, next, group.Length); + next = next + group.Length; + buffer = nb; + } else { + Array.Copy (group, 0, buffer, next, group.Length); + next += group.Length; + } + } + + public byte [] Get () + { + if (buffer == null) + return new byte [0]; + + if (buffer.Length != next){ + byte [] b = new byte [next]; + Array.Copy (buffer, b, next); + return b; + } + return buffer; + } + } + + // + // Format includes: + // Control: + // ^ Switch to big endian encoding + // _ Switch to little endian encoding + // % Switch to host (native) encoding + // ! aligns the next data type to its natural boundary (for strings this is 4). + // + // Types: + // s Int16 + // S UInt16 + // i Int32 + // I UInt32 + // l Int64 + // L UInt64 + // f float + // d double + // b byte + // c 1-byte signed character + // C 1-byte unsigned character + // z8 string encoded as UTF8 with 1-byte null terminator + // z6 string encoded as UTF16 with 2-byte null terminator + // z7 string encoded as UTF7 with 1-byte null terminator + // zb string encoded as BigEndianUnicode with 2-byte null terminator + // z3 string encoded as UTF32 with 4-byte null terminator + // z4 string encoded as UTF32 big endian with 4-byte null terminator + // $8 string encoded as UTF8 + // $6 string encoded as UTF16 + // $7 string encoded as UTF7 + // $b string encoded as BigEndianUnicode + // $3 string encoded as UTF32 + // $4 string encoded as UTF-32 big endian encoding + // x null byte + // + // Repeats, these are prefixes: + // N a number between 1 and 9, indicates a repeat count (process N items + // with the following datatype + // [N] For numbers larger than 9, use brackets, for example [20] + // * Repeat the next data type until the arguments are exhausted + // + static public byte [] Pack (string description, params object [] args) + { + int argn = 0; + PackContext b = new PackContext (); + b.conv = CopyConv; + b.description = description; + + for (b.i = 0; b.i < description.Length; ){ + object oarg; + + if (argn < args.Length) + oarg = args [argn]; + else { + if (b.repeat != 0) + break; + + oarg = null; + } + + int save = b.i; + + if (PackOne (b, oarg)){ + argn++; + if (b.repeat > 0){ + if (--b.repeat > 0) + b.i = save; + else + b.i++; + } else + b.i++; + } else + b.i++; + } + return b.Get (); + } + + static public byte [] PackEnumerable (string description, IEnumerable args) + { + PackContext b = new PackContext (); + b.conv = CopyConv; + b.description = description; + + IEnumerator enumerator = args.GetEnumerator (); + bool ok = enumerator.MoveNext (); + + for (b.i = 0; b.i < description.Length; ){ + object oarg; + + if (ok) + oarg = enumerator.Current; + else { + if (b.repeat != 0) + break; + oarg = null; + } + + int save = b.i; + + if (PackOne (b, oarg)){ + ok = enumerator.MoveNext (); + if (b.repeat > 0){ + if (--b.repeat > 0) + b.i = save; + else + b.i++; + } else + b.i++; + } else + b.i++; + } + return b.Get (); + } + + // + // Packs one datum `oarg' into the buffer `b', using the string format + // in `description' at position `i' + // + // Returns: true if we must pick the next object from the list + // + static bool PackOne (PackContext b, object oarg) + { + int n; + + switch (b.description [b.i]){ + case '^': + b.conv = BigEndian; + return false; + case '_': + b.conv = LittleEndian; + return false; + case '%': + b.conv = Native; + return false; + + case '!': + b.align = -1; + return false; + + case 'x': + b.Add (new byte [] { 0 }); + return false; + + // Type Conversions + case 'i': + b.Add (b.conv.GetBytes (Convert.ToInt32 (oarg))); + break; + + case 'I': + b.Add (b.conv.GetBytes (Convert.ToUInt32 (oarg))); + break; + + case 's': + b.Add (b.conv.GetBytes (Convert.ToInt16 (oarg))); + break; + + case 'S': + b.Add (b.conv.GetBytes (Convert.ToUInt16 (oarg))); + break; + + case 'l': + b.Add (b.conv.GetBytes (Convert.ToInt64 (oarg))); + break; + + case 'L': + b.Add (b.conv.GetBytes (Convert.ToUInt64 (oarg))); + break; + + case 'f': + b.Add (b.conv.GetBytes (Convert.ToSingle (oarg))); + break; + + case 'd': + b.Add (b.conv.GetBytes (Convert.ToDouble (oarg))); + break; + + case 'b': + b.Add (new byte [] { Convert.ToByte (oarg) }); + break; + + case 'c': + b.Add (new byte [] { (byte) (Convert.ToSByte (oarg)) }); + break; + + case 'C': + b.Add (new byte [] { Convert.ToByte (oarg) }); + break; + + // Repeat acount; + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + b.repeat = ((short) b.description [b.i]) - ((short) '0'); + return false; + + case '*': + b.repeat = Int32.MaxValue; + return false; + + case '[': + int count = -1, j; + + for (j = b.i+1; j < b.description.Length; j++){ + if (b.description [j] == ']') + break; + n = ((short) b.description [j]) - ((short) '0'); + if (n >= 0 && n <= 9){ + if (count == -1) + count = n; + else + count = count * 10 + n; + } + } + if (count == -1) + throw new ArgumentException ("invalid size specification"); + b.i = j; + b.repeat = count; + return false; + + case '$': case 'z': + bool add_null = b.description [b.i] == 'z'; + b.i++; + if (b.i >= b.description.Length) + throw new ArgumentException ("$ description needs a type specified", "description"); + char d = b.description [b.i]; + Encoding e; + + switch (d){ + case '8': + e = Encoding.UTF8; + n = 1; + break; + case '6': + e = Encoding.Unicode; + n = 2; + break; + case '7': +#if PCL + e = Encoding.GetEncoding ("utf-7"); +#else + e = Encoding.UTF7; +#endif + n = 1; + break; + case 'b': + e = Encoding.BigEndianUnicode; + n = 2; + break; + case '3': +#if PCL + e = Encoding.GetEncoding ("utf-32"); +#else + e = Encoding.GetEncoding (12000); +#endif + n = 4; + break; + case '4': +#if PCL + e = Encoding.GetEncoding ("utf-32BE"); +#else + e = Encoding.GetEncoding (12001); +#endif + n = 4; + break; + + default: + throw new ArgumentException ("Invalid format for $ specifier", "description"); + } + if (b.align == -1) + b.align = 4; + b.Add (e.GetBytes (Convert.ToString (oarg))); + if (add_null) + b.Add (new byte [n]); + break; + default: + throw new ArgumentException (String.Format ("invalid format specified `{0}'", + b.description [b.i])); + } + return true; + } + + static bool Prepare (byte [] buffer, ref int idx, int size, ref bool align) + { + if (align){ + idx = Align (idx, size); + align = false; + } + if (idx + size > buffer.Length){ + idx = buffer.Length; + return false; + } + return true; + } + + static public IList Unpack (string description, byte [] buffer, int startIndex) + { + DataConverter conv = CopyConv; + var result = new List (); + int idx = startIndex; + bool align = false; + int repeat = 0, n; + + for (int i = 0; i < description.Length && idx < buffer.Length; ){ + int save = i; + + switch (description [i]){ + case '^': + conv = BigEndian; + break; + case '_': + conv = LittleEndian; + break; + case '%': + conv = Native; + break; + case 'x': + idx++; + break; + + case '!': + align = true; + break; + + // Type Conversions + case 'i': + if (Prepare (buffer, ref idx, 4, ref align)){ + result.Add (conv.GetInt32 (buffer, idx)); + idx += 4; + } + break; + + case 'I': + if (Prepare (buffer, ref idx, 4, ref align)){ + result.Add (conv.GetUInt32 (buffer, idx)); + idx += 4; + } + break; + + case 's': + if (Prepare (buffer, ref idx, 2, ref align)){ + result.Add (conv.GetInt16 (buffer, idx)); + idx += 2; + } + break; + + case 'S': + if (Prepare (buffer, ref idx, 2, ref align)){ + result.Add (conv.GetUInt16 (buffer, idx)); + idx += 2; + } + break; + + case 'l': + if (Prepare (buffer, ref idx, 8, ref align)){ + result.Add (conv.GetInt64 (buffer, idx)); + idx += 8; + } + break; + + case 'L': + if (Prepare (buffer, ref idx, 8, ref align)){ + result.Add (conv.GetUInt64 (buffer, idx)); + idx += 8; + } + break; + + case 'f': + if (Prepare (buffer, ref idx, 4, ref align)){ + result.Add (conv.GetFloat (buffer, idx)); + idx += 4; + } + break; + + case 'd': + if (Prepare (buffer, ref idx, 8, ref align)){ + result.Add (conv.GetDouble (buffer, idx)); + idx += 8; + } + break; + + case 'b': + if (Prepare (buffer, ref idx, 1, ref align)){ + result.Add (buffer [idx]); + idx++; + } + break; + + case 'c': case 'C': + if (Prepare (buffer, ref idx, 1, ref align)){ + char c; + + if (description [i] == 'c') + c = ((char) ((sbyte)buffer [idx])); + else + c = ((char) ((byte)buffer [idx])); + + result.Add (c); + idx++; + } + break; + + // Repeat acount; + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + repeat = ((short) description [i]) - ((short) '0'); + save = i + 1; + break; + + case '*': + repeat = Int32.MaxValue; + break; + + case '[': + int count = -1, j; + + for (j = i+1; j < description.Length; j++){ + if (description [j] == ']') + break; + n = ((short) description [j]) - ((short) '0'); + if (n >= 0 && n <= 9){ + if (count == -1) + count = n; + else + count = count * 10 + n; + } + } + if (count == -1) + throw new ArgumentException ("invalid size specification"); + i = j; + save = i + 1; + repeat = count; + break; + + case '$': case 'z': + // bool with_null = description [i] == 'z'; + i++; + if (i >= description.Length) + throw new ArgumentException ("$ description needs a type specified", "description"); + char d = description [i]; + Encoding e; + if (align){ + idx = Align (idx, 4); + align = false; + } + if (idx >= buffer.Length) + break; + + switch (d){ + case '8': + e = Encoding.UTF8; + n = 1; + break; + case '6': + e = Encoding.Unicode; + n = 2; + break; + case '7': + e = Encoding.UTF7; + n = 1; + break; + case 'b': + e = Encoding.BigEndianUnicode; + n = 2; + break; + case '3': + e = Encoding.GetEncoding (12000); + n = 4; + break; + case '4': + e = Encoding.GetEncoding (12001); + n = 4; + break; + + default: + throw new ArgumentException ("Invalid format for $ specifier", "description"); + } + int k = idx; + switch (n){ + case 1: + for (; k < buffer.Length && buffer [k] != 0; k++) + ; + result.Add (e.GetChars (buffer, idx, k-idx)); + if (k == buffer.Length) + idx = k; + else + idx = k+1; + break; + + case 2: + for (; k < buffer.Length; k++){ + if (k+1 == buffer.Length){ + k++; + break; + } + if (buffer [k] == 0 && buffer [k+1] == 0) + break; + } + result.Add (e.GetChars (buffer, idx, k-idx)); + if (k == buffer.Length) + idx = k; + else + idx = k+2; + break; + + case 4: + for (; k < buffer.Length; k++){ + if (k+3 >= buffer.Length){ + k = buffer.Length; + break; + } + if (buffer[k]==0 && buffer[k+1] == 0 && buffer[k+2] == 0 && buffer[k+3]== 0) + break; + } + result.Add (e.GetChars (buffer, idx, k-idx)); + if (k == buffer.Length) + idx = k; + else + idx = k+4; + break; + } + break; + default: + throw new ArgumentException (String.Format ("invalid format specified `{0}'", + description [i])); + } + + if (repeat > 0){ + if (--repeat > 0) + i = save; + } else + i++; + } + return result; + } + + internal void Check (byte [] dest, int destIdx, int size) + { + if (dest == null) + throw new ArgumentNullException ("dest"); + if (destIdx < 0 || destIdx > dest.Length - size) + throw new ArgumentException ("destIdx"); + } + + class CopyConverter : DataConverter { + public override double GetDouble (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 8) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + double ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 8; i++) + b [i] = data [index+i]; + + return ret; + } + + public override ulong GetUInt64 (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 8) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + ulong ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 8; i++) + b [i] = data [index+i]; + + return ret; + } + + public override long GetInt64 (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 8) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + long ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 8; i++) + b [i] = data [index+i]; + + return ret; + } + + public override float GetFloat (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 4) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + float ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 4; i++) + b [i] = data [index+i]; + + return ret; + } + + public override int GetInt32 (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 4) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + int ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 4; i++) + b [i] = data [index+i]; + + return ret; + } + + public override uint GetUInt32 (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 4) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + uint ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 4; i++) + b [i] = data [index+i]; + + return ret; + } + + public override short GetInt16 (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 2) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + short ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 2; i++) + b [i] = data [index+i]; + + return ret; + } + + public override ushort GetUInt16 (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 2) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + ushort ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 2; i++) + b [i] = data [index+i]; + + return ret; + } + + public override void PutBytes (byte [] dest, int destIdx, double value) + { + Check (dest, destIdx, 8); + fixed (byte *target = &dest [destIdx]){ + long *source = (long *) &value; + + *((long *)target) = *source; + } + } + + public override void PutBytes (byte [] dest, int destIdx, float value) + { + Check (dest, destIdx, 4); + fixed (byte *target = &dest [destIdx]){ + uint *source = (uint *) &value; + + *((uint *)target) = *source; + } + } + + public override void PutBytes (byte [] dest, int destIdx, int value) + { + Check (dest, destIdx, 4); + fixed (byte *target = &dest [destIdx]){ + uint *source = (uint *) &value; + + *((uint *)target) = *source; + } + } + + public override void PutBytes (byte [] dest, int destIdx, uint value) + { + Check (dest, destIdx, 4); + fixed (byte *target = &dest [destIdx]){ + uint *source = (uint *) &value; + + *((uint *)target) = *source; + } + } + + public override void PutBytes (byte [] dest, int destIdx, long value) + { + Check (dest, destIdx, 8); + fixed (byte *target = &dest [destIdx]){ + long *source = (long *) &value; + + *((long*)target) = *source; + } + } + + public override void PutBytes (byte [] dest, int destIdx, ulong value) + { + Check (dest, destIdx, 8); + fixed (byte *target = &dest [destIdx]){ + ulong *source = (ulong *) &value; + + *((ulong *) target) = *source; + } + } + + public override void PutBytes (byte [] dest, int destIdx, short value) + { + Check (dest, destIdx, 2); + fixed (byte *target = &dest [destIdx]){ + ushort *source = (ushort *) &value; + + *((ushort *)target) = *source; + } + } + + public override void PutBytes (byte [] dest, int destIdx, ushort value) + { + Check (dest, destIdx, 2); + fixed (byte *target = &dest [destIdx]){ + ushort *source = (ushort *) &value; + + *((ushort *)target) = *source; + } + } + } + + class SwapConverter : DataConverter { + public override double GetDouble (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 8) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + double ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 8; i++) + b [7-i] = data [index+i]; + + return ret; + } + + public override ulong GetUInt64 (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 8) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + ulong ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 8; i++) + b [7-i] = data [index+i]; + + return ret; + } + + public override long GetInt64 (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 8) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + long ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 8; i++) + b [7-i] = data [index+i]; + + return ret; + } + + public override float GetFloat (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 4) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + float ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 4; i++) + b [3-i] = data [index+i]; + + return ret; + } + + public override int GetInt32 (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 4) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + int ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 4; i++) + b [3-i] = data [index+i]; + + return ret; + } + + public override uint GetUInt32 (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 4) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + uint ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 4; i++) + b [3-i] = data [index+i]; + + return ret; + } + + public override short GetInt16 (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 2) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + short ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 2; i++) + b [1-i] = data [index+i]; + + return ret; + } + + public override ushort GetUInt16 (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 2) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + ushort ret; + byte *b = (byte *)&ret; + + for (int i = 0; i < 2; i++) + b [1-i] = data [index+i]; + + return ret; + } + + public override void PutBytes (byte [] dest, int destIdx, double value) + { + Check (dest, destIdx, 8); + + fixed (byte *target = &dest [destIdx]){ + byte *source = (byte *) &value; + + for (int i = 0; i < 8; i++) + target [i] = source [7-i]; + } + } + + public override void PutBytes (byte [] dest, int destIdx, float value) + { + Check (dest, destIdx, 4); + + fixed (byte *target = &dest [destIdx]){ + byte *source = (byte *) &value; + + for (int i = 0; i < 4; i++) + target [i] = source [3-i]; + } + } + + public override void PutBytes (byte [] dest, int destIdx, int value) + { + Check (dest, destIdx, 4); + + fixed (byte *target = &dest [destIdx]){ + byte *source = (byte *) &value; + + for (int i = 0; i < 4; i++) + target [i] = source [3-i]; + } + } + + public override void PutBytes (byte [] dest, int destIdx, uint value) + { + Check (dest, destIdx, 4); + + fixed (byte *target = &dest [destIdx]){ + byte *source = (byte *) &value; + + for (int i = 0; i < 4; i++) + target [i] = source [3-i]; + } + } + + public override void PutBytes (byte [] dest, int destIdx, long value) + { + Check (dest, destIdx, 8); + + fixed (byte *target = &dest [destIdx]){ + byte *source = (byte *) &value; + + for (int i = 0; i < 8; i++) + target [i] = source [7-i]; + } + } + + public override void PutBytes (byte [] dest, int destIdx, ulong value) + { + Check (dest, destIdx, 8); + + fixed (byte *target = &dest [destIdx]){ + byte *source = (byte *) &value; + + for (int i = 0; i < 8; i++) + target [i] = source [7-i]; + } + } + + public override void PutBytes (byte [] dest, int destIdx, short value) + { + Check (dest, destIdx, 2); + + fixed (byte *target = &dest [destIdx]){ + byte *source = (byte *) &value; + + for (int i = 0; i < 2; i++) + target [i] = source [1-i]; + } + } + + public override void PutBytes (byte [] dest, int destIdx, ushort value) + { + Check (dest, destIdx, 2); + + fixed (byte *target = &dest [destIdx]){ + byte *source = (byte *) &value; + + for (int i = 0; i < 2; i++) + target [i] = source [1-i]; + } + } + } + +#if MONO_DATACONVERTER_STATIC_METHODS + static unsafe void PutBytesLE (byte *dest, byte *src, int count) + { + int i = 0; + + if (BitConverter.IsLittleEndian){ + for (; i < count; i++) + *dest++ = *src++; + } else { + dest += count; + for (; i < count; i++) + *(--dest) = *src++; + } + } + + static unsafe void PutBytesBE (byte *dest, byte *src, int count) + { + int i = 0; + + if (BitConverter.IsLittleEndian){ + dest += count; + for (; i < count; i++) + *(--dest) = *src++; + } else { + for (; i < count; i++) + *dest++ = *src++; + } + } + + static unsafe void PutBytesNative (byte *dest, byte *src, int count) + { + int i = 0; + + for (; i < count; i++) + dest [i-count] = *src++; + } + + static public unsafe double DoubleFromLE (byte[] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 8) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + double ret; + fixed (byte *src = &data[index]){ + PutBytesLE ((byte *) &ret, src, 8); + } + return ret; + } + + static public unsafe float FloatFromLE (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 4) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + float ret; + fixed (byte *src = &data[index]){ + PutBytesLE ((byte *) &ret, src, 4); + } + return ret; + } + + static public unsafe long Int64FromLE (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 8) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + long ret; + fixed (byte *src = &data[index]){ + PutBytesLE ((byte *) &ret, src, 8); + } + return ret; + } + + static public unsafe ulong UInt64FromLE (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 8) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + ulong ret; + fixed (byte *src = &data[index]){ + PutBytesLE ((byte *) &ret, src, 8); + } + return ret; + } + + static public unsafe int Int32FromLE (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 4) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + int ret; + fixed (byte *src = &data[index]){ + PutBytesLE ((byte *) &ret, src, 4); + } + return ret; + } + + static public unsafe uint UInt32FromLE (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 4) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + uint ret; + fixed (byte *src = &data[index]){ + PutBytesLE ((byte *) &ret, src, 4); + } + return ret; + } + + static public unsafe short Int16FromLE (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 2) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + short ret; + fixed (byte *src = &data[index]){ + PutBytesLE ((byte *) &ret, src, 2); + } + return ret; + } + + static public unsafe ushort UInt16FromLE (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 2) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + ushort ret; + fixed (byte *src = &data[index]){ + PutBytesLE ((byte *) &ret, src, 2); + } + return ret; + } + + static public unsafe double DoubleFromBE (byte[] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 8) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + double ret; + fixed (byte *src = &data[index]){ + PutBytesBE ((byte *) &ret, src, 8); + } + return ret; + } + + static public unsafe float FloatFromBE (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 4) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + float ret; + fixed (byte *src = &data[index]){ + PutBytesBE ((byte *) &ret, src, 4); + } + return ret; + } + + static public unsafe long Int64FromBE (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 8) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + long ret; + fixed (byte *src = &data[index]){ + PutBytesBE ((byte *) &ret, src, 8); + } + return ret; + } + + static public unsafe ulong UInt64FromBE (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 8) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + ulong ret; + fixed (byte *src = &data[index]){ + PutBytesBE ((byte *) &ret, src, 8); + } + return ret; + } + + static public unsafe int Int32FromBE (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 4) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + int ret; + fixed (byte *src = &data[index]){ + PutBytesBE ((byte *) &ret, src, 4); + } + return ret; + } + + static public unsafe uint UInt32FromBE (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 4) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + uint ret; + fixed (byte *src = &data[index]){ + PutBytesBE ((byte *) &ret, src, 4); + } + return ret; + } + + static public unsafe short Int16FromBE (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 2) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + short ret; + fixed (byte *src = &data[index]){ + PutBytesBE ((byte *) &ret, src, 2); + } + return ret; + } + + static public unsafe ushort UInt16FromBE (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 2) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + ushort ret; + fixed (byte *src = &data[index]){ + PutBytesBE ((byte *) &ret, src, 2); + } + return ret; + } + + static public unsafe double DoubleFromNative (byte[] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 8) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + double ret; + fixed (byte *src = &data[index]){ + PutBytesNative ((byte *) &ret, src, 8); + } + return ret; + } + + static public unsafe float FloatFromNative (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 4) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + float ret; + fixed (byte *src = &data[index]){ + PutBytesNative ((byte *) &ret, src, 4); + } + return ret; + } + + static public unsafe long Int64FromNative (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 8) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + long ret; + fixed (byte *src = &data[index]){ + PutBytesNative ((byte *) &ret, src, 8); + } + return ret; + } + + static public unsafe ulong UInt64FromNative (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 8) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + ulong ret; + fixed (byte *src = &data[index]){ + PutBytesNative ((byte *) &ret, src, 8); + } + return ret; + } + + static public unsafe int Int32FromNative (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 4) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + int ret; + fixed (byte *src = &data[index]){ + PutBytesNative ((byte *) &ret, src, 4); + } + return ret; + } + + static public unsafe uint UInt32FromNative (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 4) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + uint ret; + fixed (byte *src = &data[index]){ + PutBytesNative ((byte *) &ret, src, 4); + } + return ret; + } + + static public unsafe short Int16FromNative (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 2) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + short ret; + fixed (byte *src = &data[index]){ + PutBytesNative ((byte *) &ret, src, 2); + } + return ret; + } + + static public unsafe ushort UInt16FromNative (byte [] data, int index) + { + if (data == null) + throw new ArgumentNullException ("data"); + if (data.Length - index < 2) + throw new ArgumentException ("index"); + if (index < 0) + throw new ArgumentException ("index"); + + ushort ret; + fixed (byte *src = &data[index]){ + PutBytesNative ((byte *) &ret, src, 2); + } + return ret; + } + + unsafe static byte[] GetBytesPtr (byte *ptr, int count) + { + byte [] ret = new byte [count]; + + for (int i = 0; i < count; i++) { + ret [i] = ptr [i]; + } + + return ret; + } + + unsafe static byte[] GetBytesSwap (bool swap, byte *ptr, int count) + { + byte [] ret = new byte [count]; + + if (swap){ + int t = count-1; + for (int i = 0; i < count; i++) { + ret [t-i] = ptr [i]; + } + } else { + for (int i = 0; i < count; i++) { + ret [i] = ptr [i]; + } + } + return ret; + } + + unsafe public static byte[] GetBytesNative (bool value) + { + return GetBytesPtr ((byte *) &value, 1); + } + + unsafe public static byte[] GetBytesNative (char value) + { + return GetBytesPtr ((byte *) &value, 2); + } + + unsafe public static byte[] GetBytesNative (short value) + { + return GetBytesPtr ((byte *) &value, 2); + } + + unsafe public static byte[] GetBytesNative (int value) + { + return GetBytesPtr ((byte *) &value, 4); + } + + unsafe public static byte[] GetBytesNative (long value) + { + return GetBytesPtr ((byte *) &value, 8); + } + + [CLSCompliant (false)] + unsafe public static byte[] GetBytesNative (ushort value) + { + return GetBytesPtr ((byte *) &value, 2); + } + + [CLSCompliant (false)] + unsafe public static byte[] GetBytesNative (uint value) + { + return GetBytesPtr ((byte *) &value, 4); + } + + [CLSCompliant (false)] + unsafe public static byte[] GetBytesNative (ulong value) + { + return GetBytesPtr ((byte *) &value, 8); + } + + unsafe public static byte[] GetBytesNative (float value) + { + return GetBytesPtr ((byte *) &value, 4); + } + + unsafe public static byte[] GetBytesNative (double value) + { + return GetBytesPtr ((byte *) &value, 8); + } + + unsafe public static byte[] GetBytesLE (bool value) + { + return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 1); + } + + unsafe public static byte[] GetBytesLE (char value) + { + return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 2); + } + + unsafe public static byte[] GetBytesLE (short value) + { + return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 2); + } + + unsafe public static byte[] GetBytesLE (int value) + { + return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 4); + } + + unsafe public static byte[] GetBytesLE (long value) + { + return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 8); + } + + [CLSCompliant (false)] + unsafe public static byte[] GetBytesLE (ushort value) + { + return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 2); + } + + [CLSCompliant (false)] + unsafe public static byte[] GetBytesLE (uint value) + { + return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 4); + } + + [CLSCompliant (false)] + unsafe public static byte[] GetBytesLE (ulong value) + { + return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 8); + } + + unsafe public static byte[] GetBytesLE (float value) + { + return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 4); + } + + unsafe public static byte[] GetBytesLE (double value) + { + return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 8); + } + + unsafe public static byte[] GetBytesBE (bool value) + { + return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 1); + } + + unsafe public static byte[] GetBytesBE (char value) + { + return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 2); + } + + unsafe public static byte[] GetBytesBE (short value) + { + return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 2); + } + + unsafe public static byte[] GetBytesBE (int value) + { + return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 4); + } + + unsafe public static byte[] GetBytesBE (long value) + { + return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 8); + } + + [CLSCompliant (false)] + unsafe public static byte[] GetBytesBE (ushort value) + { + return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 2); + } + + [CLSCompliant (false)] + unsafe public static byte[] GetBytesBE (uint value) + { + return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 4); + } + + [CLSCompliant (false)] + unsafe public static byte[] GetBytesBE (ulong value) + { + return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 8); + } + + unsafe public static byte[] GetBytesBE (float value) + { + return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 4); + } + + unsafe public static byte[] GetBytesBE (double value) + { + return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 8); + } +#endif + + } +} diff --git a/SharpCompress/Crypto/PBKDF2.cs b/SharpCompress/Crypto/PBKDF2.cs index 7cb772ef..ae7f2c99 100644 --- a/SharpCompress/Crypto/PBKDF2.cs +++ b/SharpCompress/Crypto/PBKDF2.cs @@ -3,6 +3,7 @@ using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Macs; using Org.BouncyCastle.Crypto.Parameters; +using SharpCompress.Converter; namespace SharpCompress.Crypto { @@ -68,7 +69,7 @@ namespace SharpCompress.Crypto private byte[] Hash() { - byte[] array = UIntToOctet(block); + byte[] array = DataConverter.BigEndian.GetBytes(block); ICipherParameters param = new KeyParameter(password); hMac.Init(param); @@ -96,24 +97,6 @@ namespace SharpCompress.Crypto block += 1u; return array3; } - - internal static byte[] UIntToOctet(uint i) - { - byte[] bytes = BitConverter.GetBytes(i); - byte[] result = new[] - { - bytes[3], - bytes[2], - bytes[1], - bytes[0] - }; - if (!BitConverter.IsLittleEndian) - { - return bytes; - } - return result; - } - } } diff --git a/SharpCompress/IO/MarkingBinaryReader.cs b/SharpCompress/IO/MarkingBinaryReader.cs index a9a5d1be..07ddd16e 100644 --- a/SharpCompress/IO/MarkingBinaryReader.cs +++ b/SharpCompress/IO/MarkingBinaryReader.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Linq; +using SharpCompress.Converter; namespace SharpCompress.IO { @@ -36,7 +37,7 @@ namespace SharpCompress.IO public override bool ReadBoolean() { - return BitConverter.ToBoolean(ReadBytes(1), 0); + return ReadBytes(1).Single() != 0; } public override byte ReadByte() @@ -68,39 +69,28 @@ namespace SharpCompress.IO #if !PORTABLE public override decimal ReadDecimal() { - return ByteArrayToDecimal(ReadBytes(16), 0); - } - - private decimal ByteArrayToDecimal(byte[] src, int offset) - { - //http://stackoverflow.com/a/16984356/385387 - var i1 = BitConverter.ToInt32(src, offset); - var i2 = BitConverter.ToInt32(src, offset + 4); - var i3 = BitConverter.ToInt32(src, offset + 8); - var i4 = BitConverter.ToInt32(src, offset + 12); - - return new decimal(new[] { i1, i2, i3, i4 }); + throw new NotSupportedException(); } #endif public override double ReadDouble() { - return BitConverter.ToDouble(ReadBytes(8), 0); + throw new NotSupportedException(); } public override short ReadInt16() { - return BitConverter.ToInt16(ReadBytes(2), 0); + return DataConverter.LittleEndian.GetInt16(ReadBytes(2), 0); } public override int ReadInt32() { - return BitConverter.ToInt32(ReadBytes(4), 0); + return DataConverter.LittleEndian.GetInt32(ReadBytes(4), 0); } public override long ReadInt64() { - return BitConverter.ToInt64(ReadBytes(8), 0); + return DataConverter.LittleEndian.GetInt64(ReadBytes(8), 0); } public override sbyte ReadSByte() @@ -110,7 +100,7 @@ namespace SharpCompress.IO public override float ReadSingle() { - return BitConverter.ToSingle(ReadBytes(4), 0); + throw new NotSupportedException(); } public override string ReadString() @@ -120,17 +110,17 @@ namespace SharpCompress.IO public override ushort ReadUInt16() { - return BitConverter.ToUInt16(ReadBytes(2), 0); + return DataConverter.LittleEndian.GetUInt16(ReadBytes(2), 0); } public override uint ReadUInt32() { - return BitConverter.ToUInt32(ReadBytes(4), 0); + return DataConverter.LittleEndian.GetUInt32(ReadBytes(4), 0); } public override ulong ReadUInt64() { - return BitConverter.ToUInt64(ReadBytes(8), 0); + return DataConverter.LittleEndian.GetUInt64(ReadBytes(8), 0); } } } \ No newline at end of file diff --git a/SharpCompress/SharpCompress.Portable.csproj b/SharpCompress/SharpCompress.Portable.csproj index 2f331a30..bd7fe06b 100644 --- a/SharpCompress/SharpCompress.Portable.csproj +++ b/SharpCompress/SharpCompress.Portable.csproj @@ -270,6 +270,7 @@ + diff --git a/SharpCompress/SharpCompress.PortableTest.csproj b/SharpCompress/SharpCompress.PortableTest.csproj index 523e6901..10132b56 100644 --- a/SharpCompress/SharpCompress.PortableTest.csproj +++ b/SharpCompress/SharpCompress.PortableTest.csproj @@ -240,6 +240,7 @@ + diff --git a/SharpCompress/SharpCompress.Unsigned.csproj b/SharpCompress/SharpCompress.Unsigned.csproj index 86c4aa0f..7f41cc55 100644 --- a/SharpCompress/SharpCompress.Unsigned.csproj +++ b/SharpCompress/SharpCompress.Unsigned.csproj @@ -245,6 +245,7 @@ + Code diff --git a/SharpCompress/SharpCompress.WindowsStore.csproj b/SharpCompress/SharpCompress.WindowsStore.csproj index 02f9e09b..4d4865e6 100644 --- a/SharpCompress/SharpCompress.WindowsStore.csproj +++ b/SharpCompress/SharpCompress.WindowsStore.csproj @@ -256,6 +256,7 @@ + diff --git a/SharpCompress/SharpCompress.csproj b/SharpCompress/SharpCompress.csproj index 0fd10026..acbd0c10 100644 --- a/SharpCompress/SharpCompress.csproj +++ b/SharpCompress/SharpCompress.csproj @@ -243,8 +243,9 @@ - - + + + Code diff --git a/SharpCompress/Utility.cs b/SharpCompress/Utility.cs index 6a7c4d72..d6599187 100644 --- a/SharpCompress/Utility.cs +++ b/SharpCompress/Utility.cs @@ -2,9 +2,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using SharpCompress.Archive; -using SharpCompress.Common; -using SharpCompress.IO; namespace SharpCompress { @@ -29,17 +26,6 @@ namespace SharpCompress return (number >> bits) + (2 << ~bits); } - /// - /// Performs an unsigned bitwise right shift with the specified number - /// - /// Number to operate on - /// Ammount of bits to shift - /// The resulting number from the shift operation - public static int URShift(int number, long bits) - { - return URShift(number, (int)bits); - } - /// /// Performs an unsigned bitwise right shift with the specified number /// @@ -54,17 +40,6 @@ namespace SharpCompress return (number >> bits) + (2L << ~bits); } - /// - /// Performs an unsigned bitwise right shift with the specified number - /// - /// Number to operate on - /// Ammount of bits to shift - /// The resulting number from the shift operation - public static long URShift(long number, long bits) - { - return URShift(number, (int)bits); - } - /// /// Fills the array with an specific value from an specific index to an specific index. /// @@ -120,139 +95,6 @@ namespace SharpCompress } } - /// Read a int value from the byte array at the given position (Big Endian) - /// - /// - /// the array to read from - /// - /// the offset - /// - /// the value - /// - public static int readIntBigEndian(byte[] array, int pos) - { - int temp = 0; - temp |= array[pos] & 0xff; - temp <<= 8; - temp |= array[pos + 1] & 0xff; - temp <<= 8; - temp |= array[pos + 2] & 0xff; - temp <<= 8; - temp |= array[pos + 3] & 0xff; - return temp; - } - - /// Read a short value from the byte array at the given position (little - /// Endian) - /// - /// - /// the array to read from - /// - /// the offset - /// - /// the value - /// - public static short readShortLittleEndian(byte[] array, int pos) - { - return BitConverter.ToInt16(array, pos); - } - - /// Read an int value from the byte array at the given position (little - /// Endian) - /// - /// - /// the array to read from - /// - /// the offset - /// - /// the value - /// - public static int readIntLittleEndian(byte[] array, int pos) - { - return BitConverter.ToInt32(array, pos); - } - - /// Write an int value into the byte array at the given position (Big endian) - /// - /// - /// the array - /// - /// the offset - /// - /// the value to write - /// - public static void writeIntBigEndian(byte[] array, int pos, int value) - { - array[pos] = (byte)((Utility.URShift(value, 24)) & 0xff); - array[pos + 1] = (byte)((Utility.URShift(value, 16)) & 0xff); - array[pos + 2] = (byte)((Utility.URShift(value, 8)) & 0xff); - array[pos + 3] = (byte)((value) & 0xff); - } - - /// Write a short value into the byte array at the given position (little - /// endian) - /// - /// - /// the array - /// - /// the offset - /// - /// the value to write - /// - public static void WriteLittleEndian(byte[] array, int pos, short value) - { - byte[] newBytes = BitConverter.GetBytes(value); - - if (!BitConverter.IsLittleEndian) - Array.Reverse(newBytes); - - Array.Copy(newBytes, 0, array, pos, newBytes.Length); - } - - /// Increment a short value at the specified position by the specified amount - /// (little endian). - /// - public static void incShortLittleEndian(byte[] array, int pos, short incrementValue) - { - short existingValue = BitConverter.ToInt16(array, pos); - existingValue += incrementValue; - WriteLittleEndian(array, pos, existingValue); - //int c = Utility.URShift(((array[pos] & 0xff) + (dv & 0xff)), 8); - //array[pos] = (byte)(array[pos] + (dv & 0xff)); - //if ((c > 0) || ((dv & 0xff00) != 0)) - //{ - // array[pos + 1] = (byte)(array[pos + 1] + ((Utility.URShift(dv, 8)) & 0xff) + c); - //} - } - - /// Write an int value into the byte array at the given position (little - /// endian) - /// - /// - /// the array - /// - /// the offset - /// - /// the value to write - /// - public static void WriteLittleEndian(byte[] array, int pos, int value) - { - byte[] newBytes = BitConverter.GetBytes(value); - - if (!BitConverter.IsLittleEndian) - Array.Reverse(newBytes); - - Array.Copy(newBytes, 0, array, pos, newBytes.Length); - } - - public static void Initialize(this T[] array, Func func) - { - for (int i = 0; i < array.Length; i++) - { - array[i] = func(); - } - } - public static void AddRange(this ICollection destination, IEnumerable source) { foreach (T item in source) @@ -324,18 +166,6 @@ namespace SharpCompress } while (source.Read(buffer, 0, buffer.Length) == buffer.Length); } - - public static byte[] UInt32ToBigEndianBytes(uint x) - { - return new byte[] - { - (byte) ((x >> 24) & 0xff), - (byte) ((x >> 16) & 0xff), - (byte) ((x >> 8) & 0xff), - (byte) (x & 0xff) - }; - } - public static DateTime DosDateToDateTime(UInt16 iDate, UInt16 iTime) { int year = iDate / 512 + 1980; @@ -450,33 +280,6 @@ namespace SharpCompress { Array.Copy(array, 0, destination, index, array.Length); } - - public static long HostToNetworkOrder(long host) - { - return (int)((long)HostToNetworkOrder((int)host) - & unchecked((long)(unchecked((ulong)-1))) << 32 - | ((long)HostToNetworkOrder((int)((int)host >> 32)) & unchecked((long)(unchecked((ulong)-1))))); - } - public static int HostToNetworkOrder(int host) - { - return (int)((int)(HostToNetworkOrder((short)host) & -1) << 16 | (HostToNetworkOrder((short)(host >> 16)) & -1)); - } - public static short HostToNetworkOrder(short host) - { - return (short)((int)(host & 255) << 8 | ((int)host >> 8 & 255)); - } - public static long NetworkToHostOrder(long network) - { - return HostToNetworkOrder(network); - } - public static int NetworkToHostOrder(int network) - { - return HostToNetworkOrder(network); - } - public static short NetworkToHostOrder(short network) - { - return HostToNetworkOrder(network); - } #endif } } \ No newline at end of file diff --git a/SharpCompress/Writer/Zip/ZipCentralDirectoryEntry.cs b/SharpCompress/Writer/Zip/ZipCentralDirectoryEntry.cs index c1a4c1e8..1448d3fd 100644 --- a/SharpCompress/Writer/Zip/ZipCentralDirectoryEntry.cs +++ b/SharpCompress/Writer/Zip/ZipCentralDirectoryEntry.cs @@ -3,6 +3,7 @@ using System.IO; using System.Text; using SharpCompress.Common.Zip; using SharpCompress.Common.Zip.Headers; +using SharpCompress.Converter; namespace SharpCompress.Writer.Zip { @@ -32,23 +33,23 @@ namespace SharpCompress.Writer.Zip flags |= HeaderFlags.Bit1; // eos marker } } - outputStream.Write(BitConverter.GetBytes((ushort) flags), 0, 2); - outputStream.Write(BitConverter.GetBytes((ushort) compression), 0, 2); // zipping method - outputStream.Write(BitConverter.GetBytes(ModificationTime.DateTimeToDosTime()), 0, 4); + outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) flags), 0, 2); + outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) compression), 0, 2); // zipping method + outputStream.Write(DataConverter.LittleEndian.GetBytes(ModificationTime.DateTimeToDosTime()), 0, 4); // zipping date and time - outputStream.Write(BitConverter.GetBytes(Crc), 0, 4); // file CRC - outputStream.Write(BitConverter.GetBytes(Compressed), 0, 4); // compressed file size - outputStream.Write(BitConverter.GetBytes(Decompressed), 0, 4); // uncompressed file size - outputStream.Write(BitConverter.GetBytes((ushort) encodedFilename.Length), 0, 2); // Filename in zip - outputStream.Write(BitConverter.GetBytes((ushort) 0), 0, 2); // extra length - outputStream.Write(BitConverter.GetBytes((ushort) encodedComment.Length), 0, 2); + outputStream.Write(DataConverter.LittleEndian.GetBytes(Crc), 0, 4); // file CRC + outputStream.Write(DataConverter.LittleEndian.GetBytes(Compressed), 0, 4); // compressed file size + outputStream.Write(DataConverter.LittleEndian.GetBytes(Decompressed), 0, 4); // uncompressed file size + outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) encodedFilename.Length), 0, 2); // Filename in zip + outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) 0), 0, 2); // extra length + outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) encodedComment.Length), 0, 2); - outputStream.Write(BitConverter.GetBytes((ushort) 0), 0, 2); // disk=0 - outputStream.Write(BitConverter.GetBytes((ushort) 0), 0, 2); // file type: binary - outputStream.Write(BitConverter.GetBytes((ushort) 0), 0, 2); // Internal file attributes - outputStream.Write(BitConverter.GetBytes((ushort) 0x8100), 0, 2); + outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) 0), 0, 2); // disk=0 + outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) 0), 0, 2); // file type: binary + outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) 0), 0, 2); // Internal file attributes + outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) 0x8100), 0, 2); // External file attributes (normal/readable) - outputStream.Write(BitConverter.GetBytes(HeaderOffset), 0, 4); // Offset of header + outputStream.Write(DataConverter.LittleEndian.GetBytes(HeaderOffset), 0, 4); // Offset of header outputStream.Write(encodedFilename, 0, encodedFilename.Length); outputStream.Write(encodedComment, 0, encodedComment.Length); diff --git a/SharpCompress/Writer/Zip/ZipWriter.cs b/SharpCompress/Writer/Zip/ZipWriter.cs index 4f44fe5d..1831db22 100644 --- a/SharpCompress/Writer/Zip/ZipWriter.cs +++ b/SharpCompress/Writer/Zip/ZipWriter.cs @@ -10,6 +10,7 @@ using SharpCompress.Compressor.BZip2; using SharpCompress.Compressor.Deflate; using SharpCompress.Compressor.LZMA; using SharpCompress.Compressor.PPMd; +using SharpCompress.Converter; using SharpCompress.IO; using DeflateStream = SharpCompress.Compressor.Deflate.DeflateStream; @@ -93,7 +94,7 @@ namespace SharpCompress.Writer.Zip var explicitZipCompressionInfo = compressionInfo != null ? new ZipCompressionInfo(compressionInfo) : this.zipCompressionInfo; byte[] encodedFilename = ArchiveEncoding.Default.GetBytes(filename); - OutputStream.Write(BitConverter.GetBytes(ZipHeaderFactory.ENTRY_HEADER_BYTES), 0, 4); + OutputStream.Write(DataConverter.LittleEndian.GetBytes(ZipHeaderFactory.ENTRY_HEADER_BYTES), 0, 4); if (explicitZipCompressionInfo.Compression == ZipCompressionMethod.Deflate) { OutputStream.Write(new byte[] {20, 0}, 0, 2); //older version which is more compatible @@ -111,14 +112,14 @@ namespace SharpCompress.Writer.Zip flags |= HeaderFlags.Bit1; // eos marker } } - OutputStream.Write(BitConverter.GetBytes((ushort) flags), 0, 2); - OutputStream.Write(BitConverter.GetBytes((ushort)explicitZipCompressionInfo.Compression), 0, 2); // zipping method - OutputStream.Write(BitConverter.GetBytes(modificationTime.DateTimeToDosTime()), 0, 4); + OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) flags), 0, 2); + OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)explicitZipCompressionInfo.Compression), 0, 2); // zipping method + OutputStream.Write(DataConverter.LittleEndian.GetBytes(modificationTime.DateTimeToDosTime()), 0, 4); // zipping date and time OutputStream.Write(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 12); // unused CRC, un/compressed size, updated later - OutputStream.Write(BitConverter.GetBytes((ushort) encodedFilename.Length), 0, 2); // filename length - OutputStream.Write(BitConverter.GetBytes((ushort) 0), 0, 2); // extra length + OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) encodedFilename.Length), 0, 2); // filename length + OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) 0), 0, 2); // extra length OutputStream.Write(encodedFilename, 0, encodedFilename.Length); return 6 + 2 + 2 + 4 + 12 + 2 + 2 + encodedFilename.Length; @@ -126,9 +127,9 @@ namespace SharpCompress.Writer.Zip private void WriteFooter(uint crc, uint compressed, uint uncompressed) { - OutputStream.Write(BitConverter.GetBytes(crc), 0, 4); - OutputStream.Write(BitConverter.GetBytes(compressed), 0, 4); - OutputStream.Write(BitConverter.GetBytes(uncompressed), 0, 4); + OutputStream.Write(DataConverter.LittleEndian.GetBytes(crc), 0, 4); + OutputStream.Write(DataConverter.LittleEndian.GetBytes(compressed), 0, 4); + OutputStream.Write(DataConverter.LittleEndian.GetBytes(uncompressed), 0, 4); } private void WriteEndRecord(uint size) @@ -136,11 +137,11 @@ namespace SharpCompress.Writer.Zip byte[] encodedComment = ArchiveEncoding.Default.GetBytes(zipComment); OutputStream.Write(new byte[] {80, 75, 5, 6, 0, 0, 0, 0}, 0, 8); - OutputStream.Write(BitConverter.GetBytes((ushort) entries.Count), 0, 2); - OutputStream.Write(BitConverter.GetBytes((ushort) entries.Count), 0, 2); - OutputStream.Write(BitConverter.GetBytes(size), 0, 4); - OutputStream.Write(BitConverter.GetBytes((uint) streamPosition), 0, 4); - OutputStream.Write(BitConverter.GetBytes((ushort) encodedComment.Length), 0, 2); + OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) entries.Count), 0, 2); + OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) entries.Count), 0, 2); + OutputStream.Write(DataConverter.LittleEndian.GetBytes(size), 0, 4); + OutputStream.Write(DataConverter.LittleEndian.GetBytes((uint) streamPosition), 0, 4); + OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) encodedComment.Length), 0, 2); OutputStream.Write(encodedComment, 0, encodedComment.Length); } @@ -254,7 +255,7 @@ namespace SharpCompress.Writer.Zip } else { - originalStream.Write(BitConverter.GetBytes(ZipHeaderFactory.POST_DATA_DESCRIPTOR), 0, 4); + originalStream.Write(DataConverter.LittleEndian.GetBytes(ZipHeaderFactory.POST_DATA_DESCRIPTOR), 0, 4); writer.WriteFooter(entry.Crc, counting.Count, decompressed); writer.streamPosition += entry.Compressed + 16; } diff --git a/TestArchives/Archives/Tar.ContainsRar.tar b/TestArchives/Archives/Tar.ContainsRar.tar new file mode 100644 index 00000000..621ab2ab Binary files /dev/null and b/TestArchives/Archives/Tar.ContainsRar.tar differ