Remove dotnet-archive and Microsoft.Dotnet.Archive
This commit is contained in:
parent
7d3461eed4
commit
0e4db81898
|
|
@ -1,6 +1,6 @@
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26507.0
|
VisualStudioVersion = 15.0.26510.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ED834E68-51C3-4ADE-ACC8-6BA6D4207C09}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ED834E68-51C3-4ADE-ACC8-6BA6D4207C09}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -39,10 +39,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StartRequestDelegateUrlApp"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CreateDefaultBuilderApp", "test\TestSites\CreateDefaultBuilderApp\CreateDefaultBuilderApp.csproj", "{79CF58CE-B020-45D8-BDB5-2D8036BEAD14}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CreateDefaultBuilderApp", "test\TestSites\CreateDefaultBuilderApp\CreateDefaultBuilderApp.csproj", "{79CF58CE-B020-45D8-BDB5-2D8036BEAD14}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-archive", "src\dotnet-archive\dotnet-archive.csproj", "{AE4216BF-D471-471B-82F3-6B6D004F7D17}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Archive", "src\Microsoft.DotNet.Archive\Microsoft.DotNet.Archive.csproj", "{302400A0-98BB-4C04-88D4-C32DC2D4B945}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TrimDeps", "tools\TrimDeps\TrimDeps.csproj", "{67E4C92F-6D12-4C52-BB79-B8D11BFC6B82}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TrimDeps", "tools\TrimDeps\TrimDeps.csproj", "{67E4C92F-6D12-4C52-BB79-B8D11BFC6B82}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DependencyInjectionApp", "test\TestSites\DependencyInjectionApp\DependencyInjectionApp.csproj", "{65FE2E38-4529-4C93-A7B0-CF12DD7A70C3}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DependencyInjectionApp", "test\TestSites\DependencyInjectionApp\DependencyInjectionApp.csproj", "{65FE2E38-4529-4C93-A7B0-CF12DD7A70C3}"
|
||||||
|
|
@ -85,14 +81,6 @@ Global
|
||||||
{79CF58CE-B020-45D8-BDB5-2D8036BEAD14}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{79CF58CE-B020-45D8-BDB5-2D8036BEAD14}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{79CF58CE-B020-45D8-BDB5-2D8036BEAD14}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{79CF58CE-B020-45D8-BDB5-2D8036BEAD14}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{79CF58CE-B020-45D8-BDB5-2D8036BEAD14}.Release|Any CPU.Build.0 = Release|Any CPU
|
{79CF58CE-B020-45D8-BDB5-2D8036BEAD14}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{AE4216BF-D471-471B-82F3-6B6D004F7D17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{AE4216BF-D471-471B-82F3-6B6D004F7D17}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{AE4216BF-D471-471B-82F3-6B6D004F7D17}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{AE4216BF-D471-471B-82F3-6B6D004F7D17}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{302400A0-98BB-4C04-88D4-C32DC2D4B945}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{302400A0-98BB-4C04-88D4-C32DC2D4B945}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{302400A0-98BB-4C04-88D4-C32DC2D4B945}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{302400A0-98BB-4C04-88D4-C32DC2D4B945}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{67E4C92F-6D12-4C52-BB79-B8D11BFC6B82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{67E4C92F-6D12-4C52-BB79-B8D11BFC6B82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{67E4C92F-6D12-4C52-BB79-B8D11BFC6B82}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{67E4C92F-6D12-4C52-BB79-B8D11BFC6B82}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{67E4C92F-6D12-4C52-BB79-B8D11BFC6B82}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{67E4C92F-6D12-4C52-BB79-B8D11BFC6B82}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
|
@ -116,8 +104,6 @@ Global
|
||||||
{3A85FA52-F601-422E-A42E-9F187DB28492} = {EC22261D-0DE1-47DE-8F7C-072675D6F5B4}
|
{3A85FA52-F601-422E-A42E-9F187DB28492} = {EC22261D-0DE1-47DE-8F7C-072675D6F5B4}
|
||||||
{401C741B-6C7C-4E08-9F09-C3D43D22C0DE} = {EC22261D-0DE1-47DE-8F7C-072675D6F5B4}
|
{401C741B-6C7C-4E08-9F09-C3D43D22C0DE} = {EC22261D-0DE1-47DE-8F7C-072675D6F5B4}
|
||||||
{79CF58CE-B020-45D8-BDB5-2D8036BEAD14} = {EC22261D-0DE1-47DE-8F7C-072675D6F5B4}
|
{79CF58CE-B020-45D8-BDB5-2D8036BEAD14} = {EC22261D-0DE1-47DE-8F7C-072675D6F5B4}
|
||||||
{AE4216BF-D471-471B-82F3-6B6D004F7D17} = {ED834E68-51C3-4ADE-ACC8-6BA6D4207C09}
|
|
||||||
{302400A0-98BB-4C04-88D4-C32DC2D4B945} = {ED834E68-51C3-4ADE-ACC8-6BA6D4207C09}
|
|
||||||
{67E4C92F-6D12-4C52-BB79-B8D11BFC6B82} = {ED834E68-51C3-4ADE-ACC8-6BA6D4207C09}
|
{67E4C92F-6D12-4C52-BB79-B8D11BFC6B82} = {ED834E68-51C3-4ADE-ACC8-6BA6D4207C09}
|
||||||
{65FE2E38-4529-4C93-A7B0-CF12DD7A70C3} = {EC22261D-0DE1-47DE-8F7C-072675D6F5B4}
|
{65FE2E38-4529-4C93-A7B0-CF12DD7A70C3} = {EC22261D-0DE1-47DE-8F7C-072675D6F5B4}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,5 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ExcludeFromPack Include="$(RepositoryRoot)src\Microsoft.AspNetCore.RuntimeStore\Microsoft.AspNetCore.RuntimeStore.csproj" />
|
<ExcludeFromPack Include="$(RepositoryRoot)src\Microsoft.AspNetCore.RuntimeStore\Microsoft.AspNetCore.RuntimeStore.csproj" />
|
||||||
<ExcludeFromPack Include="$(RepositoryRoot)src\Archive.AspNetCore.All\Archive.AspNetCore.All.csproj" />
|
<ExcludeFromPack Include="$(RepositoryRoot)src\Archive.AspNetCore.All\Archive.AspNetCore.All.csproj" />
|
||||||
<ExcludeFromPack Include="$(RepositoryRoot)src\dotnet-archive\dotnet-archive.csproj" />
|
|
||||||
<ExcludeFromPack Include="$(RepositoryRoot)src\Microsoft.DotNet.Archive\Microsoft.DotNet.Archive.csproj" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@
|
||||||
<!-- Project for building the NuGet Fallback Archive (LZMA for CLI) -->
|
<!-- Project for building the NuGet Fallback Archive (LZMA for CLI) -->
|
||||||
<FallbackArchiveDir>$(RepositoryRoot)src\Archive.AspNetCore.All\</FallbackArchiveDir>
|
<FallbackArchiveDir>$(RepositoryRoot)src\Archive.AspNetCore.All\</FallbackArchiveDir>
|
||||||
<FallbackArchiveProj>$(FallbackArchiveDir)Archive.AspNetCore.All.csproj</FallbackArchiveProj>
|
<FallbackArchiveProj>$(FallbackArchiveDir)Archive.AspNetCore.All.csproj</FallbackArchiveProj>
|
||||||
<ArchiverProject>$(RepositoryRoot)src\dotnet-archive\dotnet-archive.csproj</ArchiverProject>
|
|
||||||
<ArchiverBinary>$(RepositoryRoot)src\dotnet-archive\bin\$(Configuration)\netcoreapp2.0\dotnet-archive.dll</ArchiverBinary>
|
|
||||||
|
|
||||||
<!-- Determine ASP.NET Package Version -->
|
<!-- Determine ASP.NET Package Version -->
|
||||||
<NoTimestampSuffix Condition="'$(TIMESTAMP_FREE_VERSION)' != ''">$(TIMESTAMP_FREE_VERSION)</NoTimestampSuffix>
|
<NoTimestampSuffix Condition="'$(TIMESTAMP_FREE_VERSION)' != ''">$(TIMESTAMP_FREE_VERSION)</NoTimestampSuffix>
|
||||||
|
|
@ -274,10 +272,6 @@
|
||||||
<TimestampSource>$(COHERENCE_SIGNED_DROP_LOCATION)\Signed\Packages</TimestampSource>
|
<TimestampSource>$(COHERENCE_SIGNED_DROP_LOCATION)\Signed\Packages</TimestampSource>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Build the dotnet-archiver project -->
|
|
||||||
<MSBuild Projects="$(ArchiverProject)" Targets="Restore" Properties="Configuration=$(Configuration)" />
|
|
||||||
<MSBuild Projects="$(ArchiverProject)" Targets="Build" Properties="Configuration=$(Configuration)" />
|
|
||||||
|
|
||||||
<!-- Run the actual target twice, once for timestamped packages, once for non-timestamped packages -->
|
<!-- Run the actual target twice, once for timestamped packages, once for non-timestamped packages -->
|
||||||
<!-- Here, we're re-invoking KoreBuild, but limiting it to a specific target. -->
|
<!-- Here, we're re-invoking KoreBuild, but limiting it to a specific target. -->
|
||||||
<!-- This won't rerun the whole build, but it ensures that the necessary MSBuild Tasks and Properties are initialized -->
|
<!-- This won't rerun the whole build, but it ensures that the necessary MSBuild Tasks and Properties are initialized -->
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<Import Project="..\..\build\dependencies.props" />
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
|
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
|
||||||
|
|
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
using SevenZip;
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Archive
|
|
||||||
{
|
|
||||||
internal static class CompressionUtility
|
|
||||||
{
|
|
||||||
enum MeasureBy
|
|
||||||
{
|
|
||||||
Input,
|
|
||||||
Output
|
|
||||||
}
|
|
||||||
|
|
||||||
private class LzmaProgress : ICodeProgress
|
|
||||||
{
|
|
||||||
private IProgress<ProgressReport> progress;
|
|
||||||
private long totalSize;
|
|
||||||
private string phase;
|
|
||||||
private MeasureBy measureBy;
|
|
||||||
|
|
||||||
public LzmaProgress(IProgress<ProgressReport> progress, string phase, long totalSize, MeasureBy measureBy)
|
|
||||||
{
|
|
||||||
this.progress = progress;
|
|
||||||
this.totalSize = totalSize;
|
|
||||||
this.phase = phase;
|
|
||||||
this.measureBy = measureBy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetProgress(long inSize, long outSize)
|
|
||||||
{
|
|
||||||
progress.Report(phase, measureBy == MeasureBy.Input ? inSize : outSize, totalSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Compress(Stream inStream, Stream outStream, IProgress<ProgressReport> progress)
|
|
||||||
{
|
|
||||||
SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder();
|
|
||||||
|
|
||||||
CoderPropID[] propIDs =
|
|
||||||
{
|
|
||||||
CoderPropID.DictionarySize,
|
|
||||||
CoderPropID.PosStateBits,
|
|
||||||
CoderPropID.LitContextBits,
|
|
||||||
CoderPropID.LitPosBits,
|
|
||||||
CoderPropID.Algorithm,
|
|
||||||
CoderPropID.NumFastBytes,
|
|
||||||
CoderPropID.MatchFinder,
|
|
||||||
CoderPropID.EndMarker
|
|
||||||
};
|
|
||||||
object[] properties =
|
|
||||||
{
|
|
||||||
(Int32)(1 << 26),
|
|
||||||
(Int32)(1),
|
|
||||||
(Int32)(8),
|
|
||||||
(Int32)(0),
|
|
||||||
(Int32)(2),
|
|
||||||
(Int32)(96),
|
|
||||||
"bt4",
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
encoder.SetCoderProperties(propIDs, properties);
|
|
||||||
encoder.WriteCoderProperties(outStream);
|
|
||||||
|
|
||||||
Int64 inSize = inStream.Length;
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
outStream.WriteByte((Byte)(inSize >> (8 * i)));
|
|
||||||
}
|
|
||||||
|
|
||||||
var lzmaProgress = new LzmaProgress(progress, "Compressing", inSize, MeasureBy.Input);
|
|
||||||
lzmaProgress.SetProgress(0, 0);
|
|
||||||
encoder.Code(inStream, outStream, -1, -1, lzmaProgress);
|
|
||||||
lzmaProgress.SetProgress(inSize, outStream.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Decompress(Stream inStream, Stream outStream, IProgress<ProgressReport> progress)
|
|
||||||
{
|
|
||||||
byte[] properties = new byte[5];
|
|
||||||
|
|
||||||
if (inStream.Read(properties, 0, 5) != 5)
|
|
||||||
throw (new Exception("input .lzma is too short"));
|
|
||||||
|
|
||||||
SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();
|
|
||||||
decoder.SetDecoderProperties(properties);
|
|
||||||
|
|
||||||
long outSize = 0;
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
int v = inStream.ReadByte();
|
|
||||||
if (v < 0)
|
|
||||||
throw (new Exception("Can't Read 1"));
|
|
||||||
outSize |= ((long)(byte)v) << (8 * i);
|
|
||||||
}
|
|
||||||
|
|
||||||
long compressedSize = inStream.Length - inStream.Position;
|
|
||||||
var lzmaProgress = new LzmaProgress(progress, "Decompressing", outSize, MeasureBy.Output);
|
|
||||||
lzmaProgress.SetProgress(0, 0);
|
|
||||||
decoder.Code(inStream, outStream, compressedSize, outSize, lzmaProgress);
|
|
||||||
lzmaProgress.SetProgress(inStream.Length, outSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Archive
|
|
||||||
{
|
|
||||||
public class ConsoleProgressReport : IProgress<ProgressReport>
|
|
||||||
{
|
|
||||||
private string _currentPhase;
|
|
||||||
private int _lastLineLength = 0;
|
|
||||||
private double _lastProgress = -1;
|
|
||||||
private Stopwatch _stopwatch;
|
|
||||||
private object _stateLock = new object();
|
|
||||||
|
|
||||||
public void Report(ProgressReport value)
|
|
||||||
{
|
|
||||||
long progress = (long)(100 * ((double)value.Ticks / value.Total));
|
|
||||||
|
|
||||||
if (progress == _lastProgress && value.Phase == _currentPhase)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_lastProgress = progress;
|
|
||||||
|
|
||||||
lock (_stateLock)
|
|
||||||
{
|
|
||||||
string line = $"{value.Phase} {progress}%";
|
|
||||||
if (value.Phase == _currentPhase)
|
|
||||||
{
|
|
||||||
if (Console.IsOutputRedirected)
|
|
||||||
{
|
|
||||||
Console.Write($"...{progress}%");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.Write(new string('\b', _lastLineLength));
|
|
||||||
Console.Write(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastLineLength = line.Length;
|
|
||||||
|
|
||||||
if (progress == 100)
|
|
||||||
{
|
|
||||||
Console.WriteLine($" {_stopwatch.ElapsedMilliseconds} ms");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.Write(line);
|
|
||||||
_currentPhase = value.Phase;
|
|
||||||
_lastLineLength = line.Length;
|
|
||||||
_stopwatch = Stopwatch.StartNew();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,541 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.IO.Compression;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Archive
|
|
||||||
{
|
|
||||||
public class IndexedArchive : IDisposable
|
|
||||||
{
|
|
||||||
private class DestinationFileInfo
|
|
||||||
{
|
|
||||||
public DestinationFileInfo(string destinationPath, string hash)
|
|
||||||
{
|
|
||||||
// Normalize the path
|
|
||||||
DestinationPath = destinationPath.Replace(Path.DirectorySeparatorChar, '/');
|
|
||||||
Hash = hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string DestinationPath { get; }
|
|
||||||
public string Hash { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ArchiveSource
|
|
||||||
{
|
|
||||||
public ArchiveSource(string sourceArchive, string sourceFile, string archivePath, string hash, long size)
|
|
||||||
{
|
|
||||||
Hash = hash;
|
|
||||||
Size = size;
|
|
||||||
|
|
||||||
// Normalize the paths
|
|
||||||
SourceArchive = sourceArchive?.Replace(Path.DirectorySeparatorChar, '/');
|
|
||||||
SourceFile = sourceFile.Replace(Path.DirectorySeparatorChar, '/');
|
|
||||||
ArchivePath = archivePath.Replace(Path.DirectorySeparatorChar, '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
public string SourceArchive { get; set; }
|
|
||||||
public string SourceFile { get; set; }
|
|
||||||
public string ArchivePath { get; }
|
|
||||||
public string Hash { get; }
|
|
||||||
public string FileName { get { return Path.GetFileNameWithoutExtension(ArchivePath); } }
|
|
||||||
public string Extension { get { return Path.GetExtension(ArchivePath); } }
|
|
||||||
public long Size { get; }
|
|
||||||
|
|
||||||
public void CopyTo(Stream destination)
|
|
||||||
{
|
|
||||||
if (!String.IsNullOrEmpty(SourceArchive))
|
|
||||||
{
|
|
||||||
using (var zip = new ZipArchive(File.OpenRead(SourceArchive), ZipArchiveMode.Read))
|
|
||||||
using (var sourceStream = zip.GetEntry(SourceFile)?.Open())
|
|
||||||
{
|
|
||||||
if (sourceStream == null)
|
|
||||||
{
|
|
||||||
throw new Exception($"Couldn't find entry {SourceFile} in archive {SourceArchive}");
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceStream.CopyTo(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
using (var sourceStream = File.OpenRead(SourceFile))
|
|
||||||
{
|
|
||||||
sourceStream.CopyTo(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static string[] ZipExtensions = new[] { ".zip", ".nupkg" };
|
|
||||||
static string IndexFileName = "index.txt";
|
|
||||||
|
|
||||||
// maps file hash to archve path
|
|
||||||
// $ prefix indicates that the file is not in the archive and path is a hash
|
|
||||||
private Dictionary<string, ArchiveSource> _archiveFiles = new Dictionary<string, ArchiveSource>();
|
|
||||||
// maps file hash to external path
|
|
||||||
private Dictionary<string, string> _externalFiles = new Dictionary<string, string>();
|
|
||||||
// lists all extracted files & hashes
|
|
||||||
private List<DestinationFileInfo> _destFiles = new List<DestinationFileInfo>();
|
|
||||||
private bool _disposed = false;
|
|
||||||
private ThreadLocal<SHA256> _sha = new ThreadLocal<SHA256>(() => SHA256.Create());
|
|
||||||
|
|
||||||
public IndexedArchive()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
private static Stream CreateTemporaryStream()
|
|
||||||
{
|
|
||||||
string temp = Path.GetTempPath();
|
|
||||||
string tempFile = Path.Combine(temp, Guid.NewGuid().ToString());
|
|
||||||
return File.Create(tempFile, 4096, FileOptions.DeleteOnClose);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static FileStream CreateTemporaryFileStream()
|
|
||||||
{
|
|
||||||
string temp = Path.GetTempPath();
|
|
||||||
string tempFile = Path.Combine(temp, Guid.NewGuid().ToString());
|
|
||||||
return new FileStream(tempFile, FileMode.Create, FileAccess.ReadWrite, FileShare.Read | FileShare.Delete, 4096, FileOptions.DeleteOnClose);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Save(string archivePath, IProgress<ProgressReport> progress)
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
|
|
||||||
using (var archiveStream = CreateTemporaryStream())
|
|
||||||
{
|
|
||||||
using (var archive = new ZipArchive(archiveStream, ZipArchiveMode.Create, true))
|
|
||||||
{
|
|
||||||
BuildArchive(archive, progress);
|
|
||||||
} // close archive
|
|
||||||
|
|
||||||
archiveStream.Seek(0, SeekOrigin.Begin);
|
|
||||||
|
|
||||||
using (var lzmaStream = File.Create(archivePath))
|
|
||||||
{
|
|
||||||
CompressionUtility.Compress(archiveStream, lzmaStream, progress);
|
|
||||||
}
|
|
||||||
} // close archiveStream
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BuildArchive(ZipArchive archive, IProgress<ProgressReport> progress)
|
|
||||||
{
|
|
||||||
// write the file index
|
|
||||||
var indexEntry = archive.CreateEntry(IndexFileName, CompressionLevel.NoCompression);
|
|
||||||
|
|
||||||
using (var stream = indexEntry.Open())
|
|
||||||
using (var textWriter = new StreamWriter(stream))
|
|
||||||
{
|
|
||||||
foreach (var entry in _destFiles)
|
|
||||||
{
|
|
||||||
var archiveFile = _archiveFiles[entry.Hash];
|
|
||||||
string archivePath = _archiveFiles[entry.Hash].ArchivePath;
|
|
||||||
if (archiveFile.SourceFile == null)
|
|
||||||
{
|
|
||||||
archivePath = "$" + archivePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
textWriter.WriteLine($"{entry.DestinationPath}|{archivePath}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort the files so that similar files are close together
|
|
||||||
var filesToArchive = _archiveFiles.Values.ToList();
|
|
||||||
filesToArchive.Sort((f1, f2) =>
|
|
||||||
{
|
|
||||||
// first sort by extension
|
|
||||||
var comp = String.Compare(f1.Extension, f2.Extension, StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
if (comp == 0)
|
|
||||||
{
|
|
||||||
// then sort by filename
|
|
||||||
comp = String.Compare(f1.FileName, f2.FileName, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (comp == 0)
|
|
||||||
{
|
|
||||||
// sort by file size (helps differentiate ref/lib/facade)
|
|
||||||
comp = f1.Size.CompareTo(f2.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (comp == 0)
|
|
||||||
{
|
|
||||||
// finally sort by full archive path so we have stable output
|
|
||||||
comp = String.Compare(f1.ArchivePath, f2.ArchivePath, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
return comp;
|
|
||||||
});
|
|
||||||
|
|
||||||
int filesAdded = 0;
|
|
||||||
// add all the files
|
|
||||||
foreach (var fileToArchive in filesToArchive)
|
|
||||||
{
|
|
||||||
var entry = archive.CreateEntry(fileToArchive.ArchivePath, CompressionLevel.NoCompression);
|
|
||||||
using (var entryStream = entry.Open())
|
|
||||||
{
|
|
||||||
fileToArchive.CopyTo(entryStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
progress.Report("Archiving files", ++filesAdded, filesToArchive.Count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private abstract class ExtractOperation
|
|
||||||
{
|
|
||||||
public ExtractOperation(string destinationPath)
|
|
||||||
{
|
|
||||||
DestinationPath = destinationPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string DestinationPath { get; }
|
|
||||||
public virtual void DoOperation()
|
|
||||||
{
|
|
||||||
string directory = Path.GetDirectoryName(DestinationPath);
|
|
||||||
|
|
||||||
if (!Directory.Exists(directory))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(directory);
|
|
||||||
}
|
|
||||||
|
|
||||||
Execute();
|
|
||||||
}
|
|
||||||
protected abstract void Execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CopyOperation : ExtractOperation
|
|
||||||
{
|
|
||||||
public CopyOperation(ExtractSource source, string destinationPath) : base(destinationPath)
|
|
||||||
{
|
|
||||||
Source = source;
|
|
||||||
}
|
|
||||||
public ExtractSource Source { get; }
|
|
||||||
protected override void Execute()
|
|
||||||
{
|
|
||||||
if (Source.LocalPath != null)
|
|
||||||
{
|
|
||||||
File.Copy(Source.LocalPath, DestinationPath, true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
using (var destinationStream = File.Create(DestinationPath))
|
|
||||||
{
|
|
||||||
Source.CopyToStream(destinationStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ZipOperation : ExtractOperation
|
|
||||||
{
|
|
||||||
public ZipOperation(string destinationPath) : base(destinationPath)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Tuple<string, ExtractSource>> entries = new List<Tuple<string, ExtractSource>>();
|
|
||||||
|
|
||||||
public void AddEntry(string entryName, ExtractSource source)
|
|
||||||
{
|
|
||||||
entries.Add(Tuple.Create(entryName, source));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Execute()
|
|
||||||
{
|
|
||||||
using (var archiveStream = File.Create(DestinationPath))
|
|
||||||
using (var archive = new ZipArchive(archiveStream, ZipArchiveMode.Create))
|
|
||||||
{
|
|
||||||
foreach (var zipSource in entries)
|
|
||||||
{
|
|
||||||
var entry = archive.CreateEntry(zipSource.Item1, CompressionLevel.Optimal);
|
|
||||||
using (var entryStream = entry.Open())
|
|
||||||
{
|
|
||||||
zipSource.Item2.CopyToStream(entryStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ExtractSource
|
|
||||||
{
|
|
||||||
private string _entryName;
|
|
||||||
private readonly string _localPath;
|
|
||||||
private ThreadLocalZipArchive _archive;
|
|
||||||
|
|
||||||
public ExtractSource(string sourceString, Dictionary<string, string> externalFiles, ThreadLocalZipArchive archive)
|
|
||||||
{
|
|
||||||
if (sourceString[0] == '$')
|
|
||||||
{
|
|
||||||
var externalHash = sourceString.Substring(1);
|
|
||||||
if (!externalFiles.TryGetValue(externalHash, out _localPath))
|
|
||||||
{
|
|
||||||
throw new Exception("Could not find external file with hash {externalHash}.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_entryName = sourceString;
|
|
||||||
_archive = archive;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string LocalPath { get { return _localPath; } }
|
|
||||||
|
|
||||||
public void CopyToStream(Stream destinationStream)
|
|
||||||
{
|
|
||||||
if (_localPath != null)
|
|
||||||
{
|
|
||||||
using (var sourceStream = File.OpenRead(_localPath))
|
|
||||||
{
|
|
||||||
sourceStream.CopyTo(destinationStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
using (var sourceStream = _archive.Archive.GetEntry(_entryName).Open())
|
|
||||||
{
|
|
||||||
sourceStream.CopyTo(destinationStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static char[] pipeSeperator = new[] { '|' };
|
|
||||||
public void Extract(string compressedArchivePath, string outputDirectory, IProgress<ProgressReport> progress)
|
|
||||||
{
|
|
||||||
using (var archiveStream = CreateTemporaryFileStream())
|
|
||||||
{
|
|
||||||
// decompress the LZMA stream
|
|
||||||
using (var lzmaStream = File.OpenRead(compressedArchivePath))
|
|
||||||
{
|
|
||||||
CompressionUtility.Decompress(lzmaStream, archiveStream, progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
var archivePath = ((FileStream)archiveStream).Name;
|
|
||||||
|
|
||||||
// reset the uncompressed stream
|
|
||||||
archiveStream.Seek(0, SeekOrigin.Begin);
|
|
||||||
|
|
||||||
// read as a zip archive
|
|
||||||
using (var archive = new ZipArchive(archiveStream, ZipArchiveMode.Read))
|
|
||||||
using (var tlArchive = new ThreadLocalZipArchive(archivePath, archive))
|
|
||||||
{
|
|
||||||
List<ExtractOperation> extractOperations = new List<ExtractOperation>();
|
|
||||||
Dictionary<string, ExtractSource> sourceCache = new Dictionary<string, ExtractSource>();
|
|
||||||
|
|
||||||
// process the index to determine all extraction operations
|
|
||||||
var indexEntry = archive.GetEntry(IndexFileName);
|
|
||||||
using (var indexReader = new StreamReader(indexEntry.Open()))
|
|
||||||
{
|
|
||||||
Dictionary<string, ZipOperation> zipOperations = new Dictionary<string, ZipOperation>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
for (var line = indexReader.ReadLine(); line != null; line = indexReader.ReadLine())
|
|
||||||
{
|
|
||||||
var lineParts = line.Split(pipeSeperator);
|
|
||||||
if (lineParts.Length != 2)
|
|
||||||
{
|
|
||||||
throw new Exception("Unexpected index line format, too many '|'s.");
|
|
||||||
}
|
|
||||||
|
|
||||||
string target = lineParts[0];
|
|
||||||
string source = lineParts[1];
|
|
||||||
|
|
||||||
ExtractSource extractSource;
|
|
||||||
if (!sourceCache.TryGetValue(source, out extractSource))
|
|
||||||
{
|
|
||||||
sourceCache[source] = extractSource = new ExtractSource(source, _externalFiles, tlArchive);
|
|
||||||
}
|
|
||||||
|
|
||||||
var zipSeperatorIndex = target.IndexOf("::", StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
if (zipSeperatorIndex != -1)
|
|
||||||
{
|
|
||||||
string zipRelativePath = target.Substring(0, zipSeperatorIndex);
|
|
||||||
string zipEntryName = target.Substring(zipSeperatorIndex + 2);
|
|
||||||
string destinationPath = Path.Combine(outputDirectory, zipRelativePath);
|
|
||||||
|
|
||||||
// operations on a zip file will be sequential
|
|
||||||
ZipOperation currentZipOperation;
|
|
||||||
|
|
||||||
if (!zipOperations.TryGetValue(destinationPath, out currentZipOperation))
|
|
||||||
{
|
|
||||||
extractOperations.Add(currentZipOperation = new ZipOperation(destinationPath));
|
|
||||||
zipOperations.Add(destinationPath, currentZipOperation);
|
|
||||||
}
|
|
||||||
currentZipOperation.AddEntry(zipEntryName, extractSource);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string destinationPath = Path.Combine(outputDirectory, target);
|
|
||||||
extractOperations.Add(new CopyOperation(extractSource, destinationPath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int opsExecuted = 0;
|
|
||||||
// execute all operations
|
|
||||||
//foreach(var extractOperation in extractOperations)
|
|
||||||
extractOperations.AsParallel().ForAll(extractOperation =>
|
|
||||||
{
|
|
||||||
extractOperation.DoOperation();
|
|
||||||
progress.Report("Expanding", Interlocked.Increment(ref opsExecuted), extractOperations.Count);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddExternalDirectory(string externalDirectory)
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
foreach (var externalFile in Directory.EnumerateFiles(externalDirectory, "*", SearchOption.AllDirectories))
|
|
||||||
{
|
|
||||||
AddExternalFile(externalFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddExternalFile(string externalFile)
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
using (var fs = File.OpenRead(externalFile))
|
|
||||||
{
|
|
||||||
string hash = GetHash(fs);
|
|
||||||
// $ prefix indicates that the file is not in the archive and path is relative to an external directory
|
|
||||||
_archiveFiles[hash] = new ArchiveSource(null, null, "$" + hash, hash, fs.Length);
|
|
||||||
_externalFiles[hash] = externalFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void AddDirectory(string sourceDirectory, IProgress<ProgressReport> progress, string destinationDirectory = null)
|
|
||||||
{
|
|
||||||
var sourceFiles = Directory.EnumerateFiles(sourceDirectory, "*", SearchOption.AllDirectories).ToArray();
|
|
||||||
int filesAdded = 0;
|
|
||||||
sourceFiles.AsParallel().ForAll(sourceFile =>
|
|
||||||
{
|
|
||||||
// path relative to the destination/extracted directory to write the file
|
|
||||||
string destinationRelativePath = sourceFile.Substring(sourceDirectory.Length + 1);
|
|
||||||
|
|
||||||
if (destinationDirectory != null)
|
|
||||||
{
|
|
||||||
destinationRelativePath = Path.Combine(destinationDirectory, destinationRelativePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
string extension = Path.GetExtension(sourceFile);
|
|
||||||
|
|
||||||
if (ZipExtensions.Any(ze => ze.Equals(extension, StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
AddZip(sourceFile, destinationRelativePath);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AddFile(sourceFile, destinationRelativePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
progress.Report($"Adding {sourceDirectory}", Interlocked.Increment(ref filesAdded), sourceFiles.Length);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddZip(string sourceZipFile, string destinationZipFile)
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
|
|
||||||
using (var sourceArchive = new ZipArchive(File.OpenRead(sourceZipFile), ZipArchiveMode.Read))
|
|
||||||
{
|
|
||||||
foreach (var entry in sourceArchive.Entries)
|
|
||||||
{
|
|
||||||
string hash = null;
|
|
||||||
long size = entry.Length;
|
|
||||||
string destinationPath = $"{destinationZipFile}::{entry.FullName}";
|
|
||||||
using (var stream = entry.Open())
|
|
||||||
{
|
|
||||||
hash = GetHash(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddArchiveSource(sourceZipFile, entry.FullName, destinationPath, hash, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddFile(string sourceFilePath, string destinationPath)
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
|
|
||||||
string hash;
|
|
||||||
long size;
|
|
||||||
// lifetime of this stream is managed by AddStream
|
|
||||||
using (var stream = File.Open(sourceFilePath, FileMode.Open))
|
|
||||||
{
|
|
||||||
hash = GetHash(stream);
|
|
||||||
size = stream.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddArchiveSource(null, sourceFilePath, destinationPath, hash, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddArchiveSource(string sourceArchive, string sourceFile, string destinationPath, string hash, long size)
|
|
||||||
{
|
|
||||||
lock (_archiveFiles)
|
|
||||||
{
|
|
||||||
_destFiles.Add(new DestinationFileInfo(destinationPath, hash));
|
|
||||||
|
|
||||||
// see if we already have this file in the archive/external
|
|
||||||
ArchiveSource existing = null;
|
|
||||||
if (_archiveFiles.TryGetValue(hash, out existing))
|
|
||||||
{
|
|
||||||
// if we have raw source file, prefer that over a zipped source file
|
|
||||||
if (sourceArchive == null && existing.SourceArchive != null)
|
|
||||||
{
|
|
||||||
existing.SourceArchive = null;
|
|
||||||
existing.SourceFile = sourceFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var archivePath = Path.Combine(hash, Path.GetFileName(destinationPath));
|
|
||||||
|
|
||||||
_archiveFiles.Add(hash, new ArchiveSource(sourceArchive, sourceFile, archivePath, hash, size));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetHash(Stream stream)
|
|
||||||
{
|
|
||||||
var hashBytes = _sha.Value.ComputeHash(stream);
|
|
||||||
|
|
||||||
return GetHashString(hashBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetHashString(byte[] hashBytes)
|
|
||||||
{
|
|
||||||
StringBuilder builder = new StringBuilder(hashBytes.Length * 2);
|
|
||||||
foreach (var b in hashBytes)
|
|
||||||
{
|
|
||||||
builder.AppendFormat("{0:x2}", b);
|
|
||||||
}
|
|
||||||
return builder.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (!_disposed)
|
|
||||||
{
|
|
||||||
if (_sha != null)
|
|
||||||
{
|
|
||||||
_sha.Dispose();
|
|
||||||
_sha = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CheckDisposed()
|
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
{
|
|
||||||
throw new ObjectDisposedException(nameof(IndexedArchive));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
// Common/CRC.cs
|
|
||||||
|
|
||||||
namespace SevenZip
|
|
||||||
{
|
|
||||||
class CRC
|
|
||||||
{
|
|
||||||
public static readonly uint[] Table;
|
|
||||||
|
|
||||||
static CRC()
|
|
||||||
{
|
|
||||||
Table = new uint[256];
|
|
||||||
const uint kPoly = 0xEDB88320;
|
|
||||||
for (uint i = 0; i < 256; i++)
|
|
||||||
{
|
|
||||||
uint r = i;
|
|
||||||
for (int j = 0; j < 8; j++)
|
|
||||||
if ((r & 1) != 0)
|
|
||||||
r = (r >> 1) ^ kPoly;
|
|
||||||
else
|
|
||||||
r >>= 1;
|
|
||||||
Table[i] = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint _value = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
public void Init() { _value = 0xFFFFFFFF; }
|
|
||||||
|
|
||||||
public void UpdateByte(byte b)
|
|
||||||
{
|
|
||||||
_value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Update(byte[] data, uint offset, uint size)
|
|
||||||
{
|
|
||||||
for (uint i = 0; i < size; i++)
|
|
||||||
_value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint GetDigest() { return _value ^ 0xFFFFFFFF; }
|
|
||||||
|
|
||||||
static uint CalculateDigest(byte[] data, uint offset, uint size)
|
|
||||||
{
|
|
||||||
CRC crc = new CRC();
|
|
||||||
// crc.Init();
|
|
||||||
crc.Update(data, offset, size);
|
|
||||||
return crc.GetDigest();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
|
|
||||||
{
|
|
||||||
return (CalculateDigest(data, offset, size) == digest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
// InBuffer.cs
|
|
||||||
|
|
||||||
namespace SevenZip.Buffer
|
|
||||||
{
|
|
||||||
public class InBuffer
|
|
||||||
{
|
|
||||||
byte[] m_Buffer;
|
|
||||||
uint m_Pos;
|
|
||||||
uint m_Limit;
|
|
||||||
uint m_BufferSize;
|
|
||||||
System.IO.Stream m_Stream;
|
|
||||||
bool m_StreamWasExhausted;
|
|
||||||
ulong m_ProcessedSize;
|
|
||||||
|
|
||||||
public InBuffer(uint bufferSize)
|
|
||||||
{
|
|
||||||
m_Buffer = new byte[bufferSize];
|
|
||||||
m_BufferSize = bufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init(System.IO.Stream stream)
|
|
||||||
{
|
|
||||||
m_Stream = stream;
|
|
||||||
m_ProcessedSize = 0;
|
|
||||||
m_Limit = 0;
|
|
||||||
m_Pos = 0;
|
|
||||||
m_StreamWasExhausted = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ReadBlock()
|
|
||||||
{
|
|
||||||
if (m_StreamWasExhausted)
|
|
||||||
return false;
|
|
||||||
m_ProcessedSize += m_Pos;
|
|
||||||
int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize);
|
|
||||||
m_Pos = 0;
|
|
||||||
m_Limit = (uint)aNumProcessedBytes;
|
|
||||||
m_StreamWasExhausted = (aNumProcessedBytes == 0);
|
|
||||||
return (!m_StreamWasExhausted);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void ReleaseStream()
|
|
||||||
{
|
|
||||||
// m_Stream.Close();
|
|
||||||
m_Stream = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ReadByte(byte b) // check it
|
|
||||||
{
|
|
||||||
if (m_Pos >= m_Limit)
|
|
||||||
if (!ReadBlock())
|
|
||||||
return false;
|
|
||||||
b = m_Buffer[m_Pos++];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte ReadByte()
|
|
||||||
{
|
|
||||||
// return (byte)m_Stream.ReadByte();
|
|
||||||
if (m_Pos >= m_Limit)
|
|
||||||
if (!ReadBlock())
|
|
||||||
return 0xFF;
|
|
||||||
return m_Buffer[m_Pos++];
|
|
||||||
}
|
|
||||||
|
|
||||||
public ulong GetProcessedSize()
|
|
||||||
{
|
|
||||||
return m_ProcessedSize + m_Pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
// OutBuffer.cs
|
|
||||||
|
|
||||||
namespace SevenZip.Buffer
|
|
||||||
{
|
|
||||||
public class OutBuffer
|
|
||||||
{
|
|
||||||
byte[] m_Buffer;
|
|
||||||
uint m_Pos;
|
|
||||||
uint m_BufferSize;
|
|
||||||
System.IO.Stream m_Stream;
|
|
||||||
ulong m_ProcessedSize;
|
|
||||||
|
|
||||||
public OutBuffer(uint bufferSize)
|
|
||||||
{
|
|
||||||
m_Buffer = new byte[bufferSize];
|
|
||||||
m_BufferSize = bufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetStream(System.IO.Stream stream) { m_Stream = stream; }
|
|
||||||
public void FlushStream() { m_Stream.Flush(); }
|
|
||||||
public void CloseStream() { m_Stream.Dispose(); }
|
|
||||||
public void ReleaseStream() { m_Stream = null; }
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
m_ProcessedSize = 0;
|
|
||||||
m_Pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WriteByte(byte b)
|
|
||||||
{
|
|
||||||
m_Buffer[m_Pos++] = b;
|
|
||||||
if (m_Pos >= m_BufferSize)
|
|
||||||
FlushData();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void FlushData()
|
|
||||||
{
|
|
||||||
if (m_Pos == 0)
|
|
||||||
return;
|
|
||||||
m_Stream.Write(m_Buffer, 0, (int)m_Pos);
|
|
||||||
m_Pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
// IMatchFinder.cs
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZ
|
|
||||||
{
|
|
||||||
interface IInWindowStream
|
|
||||||
{
|
|
||||||
void SetStream(System.IO.Stream inStream);
|
|
||||||
void Init();
|
|
||||||
void ReleaseStream();
|
|
||||||
Byte GetIndexByte(Int32 index);
|
|
||||||
UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit);
|
|
||||||
UInt32 GetNumAvailableBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IMatchFinder : IInWindowStream
|
|
||||||
{
|
|
||||||
void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
|
|
||||||
UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
|
|
||||||
UInt32 GetMatches(UInt32[] distances);
|
|
||||||
void Skip(UInt32 num);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,370 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
// LzBinTree.cs
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZ
|
|
||||||
{
|
|
||||||
public class BinTree : InWindow, IMatchFinder
|
|
||||||
{
|
|
||||||
UInt32 _cyclicBufferPos;
|
|
||||||
UInt32 _cyclicBufferSize = 0;
|
|
||||||
UInt32 _matchMaxLen;
|
|
||||||
|
|
||||||
UInt32[] _son;
|
|
||||||
UInt32[] _hash;
|
|
||||||
|
|
||||||
UInt32 _cutValue = 0xFF;
|
|
||||||
UInt32 _hashMask;
|
|
||||||
UInt32 _hashSizeSum = 0;
|
|
||||||
|
|
||||||
bool HASH_ARRAY = true;
|
|
||||||
|
|
||||||
const UInt32 kHash2Size = 1 << 10;
|
|
||||||
const UInt32 kHash3Size = 1 << 16;
|
|
||||||
const UInt32 kBT2HashSize = 1 << 16;
|
|
||||||
const UInt32 kStartMaxLen = 1;
|
|
||||||
const UInt32 kHash3Offset = kHash2Size;
|
|
||||||
const UInt32 kEmptyHashValue = 0;
|
|
||||||
const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1;
|
|
||||||
|
|
||||||
UInt32 kNumHashDirectBytes = 0;
|
|
||||||
UInt32 kMinMatchCheck = 4;
|
|
||||||
UInt32 kFixHashSize = kHash2Size + kHash3Size;
|
|
||||||
|
|
||||||
public void SetType(int numHashBytes)
|
|
||||||
{
|
|
||||||
HASH_ARRAY = (numHashBytes > 2);
|
|
||||||
if (HASH_ARRAY)
|
|
||||||
{
|
|
||||||
kNumHashDirectBytes = 0;
|
|
||||||
kMinMatchCheck = 4;
|
|
||||||
kFixHashSize = kHash2Size + kHash3Size;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
kNumHashDirectBytes = 2;
|
|
||||||
kMinMatchCheck = 2 + 1;
|
|
||||||
kFixHashSize = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); }
|
|
||||||
public new void ReleaseStream() { base.ReleaseStream(); }
|
|
||||||
|
|
||||||
public new void Init()
|
|
||||||
{
|
|
||||||
base.Init();
|
|
||||||
for (UInt32 i = 0; i < _hashSizeSum; i++)
|
|
||||||
_hash[i] = kEmptyHashValue;
|
|
||||||
_cyclicBufferPos = 0;
|
|
||||||
ReduceOffsets(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public new void MovePos()
|
|
||||||
{
|
|
||||||
if (++_cyclicBufferPos >= _cyclicBufferSize)
|
|
||||||
_cyclicBufferPos = 0;
|
|
||||||
base.MovePos();
|
|
||||||
if (_pos == kMaxValForNormalize)
|
|
||||||
Normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); }
|
|
||||||
|
|
||||||
public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
|
|
||||||
{ return base.GetMatchLen(index, distance, limit); }
|
|
||||||
|
|
||||||
public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); }
|
|
||||||
|
|
||||||
public void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
|
|
||||||
UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
|
|
||||||
{
|
|
||||||
if (historySize > kMaxValForNormalize - 256)
|
|
||||||
throw new Exception();
|
|
||||||
_cutValue = 16 + (matchMaxLen >> 1);
|
|
||||||
|
|
||||||
UInt32 windowReservSize = (historySize + keepAddBufferBefore +
|
|
||||||
matchMaxLen + keepAddBufferAfter) / 2 + 256;
|
|
||||||
|
|
||||||
base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);
|
|
||||||
|
|
||||||
_matchMaxLen = matchMaxLen;
|
|
||||||
|
|
||||||
UInt32 cyclicBufferSize = historySize + 1;
|
|
||||||
if (_cyclicBufferSize != cyclicBufferSize)
|
|
||||||
_son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2];
|
|
||||||
|
|
||||||
UInt32 hs = kBT2HashSize;
|
|
||||||
|
|
||||||
if (HASH_ARRAY)
|
|
||||||
{
|
|
||||||
hs = historySize - 1;
|
|
||||||
hs |= (hs >> 1);
|
|
||||||
hs |= (hs >> 2);
|
|
||||||
hs |= (hs >> 4);
|
|
||||||
hs |= (hs >> 8);
|
|
||||||
hs >>= 1;
|
|
||||||
hs |= 0xFFFF;
|
|
||||||
if (hs > (1 << 24))
|
|
||||||
hs >>= 1;
|
|
||||||
_hashMask = hs;
|
|
||||||
hs++;
|
|
||||||
hs += kFixHashSize;
|
|
||||||
}
|
|
||||||
if (hs != _hashSizeSum)
|
|
||||||
_hash = new UInt32[_hashSizeSum = hs];
|
|
||||||
}
|
|
||||||
|
|
||||||
public UInt32 GetMatches(UInt32[] distances)
|
|
||||||
{
|
|
||||||
UInt32 lenLimit;
|
|
||||||
if (_pos + _matchMaxLen <= _streamPos)
|
|
||||||
lenLimit = _matchMaxLen;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lenLimit = _streamPos - _pos;
|
|
||||||
if (lenLimit < kMinMatchCheck)
|
|
||||||
{
|
|
||||||
MovePos();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 offset = 0;
|
|
||||||
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
|
|
||||||
UInt32 cur = _bufferOffset + _pos;
|
|
||||||
UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;
|
|
||||||
UInt32 hashValue, hash2Value = 0, hash3Value = 0;
|
|
||||||
|
|
||||||
if (HASH_ARRAY)
|
|
||||||
{
|
|
||||||
UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
|
|
||||||
hash2Value = temp & (kHash2Size - 1);
|
|
||||||
temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);
|
|
||||||
hash3Value = temp & (kHash3Size - 1);
|
|
||||||
hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);
|
|
||||||
|
|
||||||
UInt32 curMatch = _hash[kFixHashSize + hashValue];
|
|
||||||
if (HASH_ARRAY)
|
|
||||||
{
|
|
||||||
UInt32 curMatch2 = _hash[hash2Value];
|
|
||||||
UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
|
|
||||||
_hash[hash2Value] = _pos;
|
|
||||||
_hash[kHash3Offset + hash3Value] = _pos;
|
|
||||||
if (curMatch2 > matchMinPos)
|
|
||||||
if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])
|
|
||||||
{
|
|
||||||
distances[offset++] = maxLen = 2;
|
|
||||||
distances[offset++] = _pos - curMatch2 - 1;
|
|
||||||
}
|
|
||||||
if (curMatch3 > matchMinPos)
|
|
||||||
if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])
|
|
||||||
{
|
|
||||||
if (curMatch3 == curMatch2)
|
|
||||||
offset -= 2;
|
|
||||||
distances[offset++] = maxLen = 3;
|
|
||||||
distances[offset++] = _pos - curMatch3 - 1;
|
|
||||||
curMatch2 = curMatch3;
|
|
||||||
}
|
|
||||||
if (offset != 0 && curMatch2 == curMatch)
|
|
||||||
{
|
|
||||||
offset -= 2;
|
|
||||||
maxLen = kStartMaxLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_hash[kFixHashSize + hashValue] = _pos;
|
|
||||||
|
|
||||||
UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
|
|
||||||
UInt32 ptr1 = (_cyclicBufferPos << 1);
|
|
||||||
|
|
||||||
UInt32 len0, len1;
|
|
||||||
len0 = len1 = kNumHashDirectBytes;
|
|
||||||
|
|
||||||
if (kNumHashDirectBytes != 0)
|
|
||||||
{
|
|
||||||
if (curMatch > matchMinPos)
|
|
||||||
{
|
|
||||||
if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=
|
|
||||||
_bufferBase[cur + kNumHashDirectBytes])
|
|
||||||
{
|
|
||||||
distances[offset++] = maxLen = kNumHashDirectBytes;
|
|
||||||
distances[offset++] = _pos - curMatch - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 count = _cutValue;
|
|
||||||
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
if(curMatch <= matchMinPos || count-- == 0)
|
|
||||||
{
|
|
||||||
_son[ptr0] = _son[ptr1] = kEmptyHashValue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
UInt32 delta = _pos - curMatch;
|
|
||||||
UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
|
|
||||||
(_cyclicBufferPos - delta) :
|
|
||||||
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
|
|
||||||
|
|
||||||
UInt32 pby1 = _bufferOffset + curMatch;
|
|
||||||
UInt32 len = Math.Min(len0, len1);
|
|
||||||
if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
|
|
||||||
{
|
|
||||||
while(++len != lenLimit)
|
|
||||||
if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
|
|
||||||
break;
|
|
||||||
if (maxLen < len)
|
|
||||||
{
|
|
||||||
distances[offset++] = maxLen = len;
|
|
||||||
distances[offset++] = delta - 1;
|
|
||||||
if (len == lenLimit)
|
|
||||||
{
|
|
||||||
_son[ptr1] = _son[cyclicPos];
|
|
||||||
_son[ptr0] = _son[cyclicPos + 1];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
|
|
||||||
{
|
|
||||||
_son[ptr1] = curMatch;
|
|
||||||
ptr1 = cyclicPos + 1;
|
|
||||||
curMatch = _son[ptr1];
|
|
||||||
len1 = len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_son[ptr0] = curMatch;
|
|
||||||
ptr0 = cyclicPos;
|
|
||||||
curMatch = _son[ptr0];
|
|
||||||
len0 = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MovePos();
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Skip(UInt32 num)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
UInt32 lenLimit;
|
|
||||||
if (_pos + _matchMaxLen <= _streamPos)
|
|
||||||
lenLimit = _matchMaxLen;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lenLimit = _streamPos - _pos;
|
|
||||||
if (lenLimit < kMinMatchCheck)
|
|
||||||
{
|
|
||||||
MovePos();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
|
|
||||||
UInt32 cur = _bufferOffset + _pos;
|
|
||||||
|
|
||||||
UInt32 hashValue;
|
|
||||||
|
|
||||||
if (HASH_ARRAY)
|
|
||||||
{
|
|
||||||
UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
|
|
||||||
UInt32 hash2Value = temp & (kHash2Size - 1);
|
|
||||||
_hash[hash2Value] = _pos;
|
|
||||||
temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);
|
|
||||||
UInt32 hash3Value = temp & (kHash3Size - 1);
|
|
||||||
_hash[kHash3Offset + hash3Value] = _pos;
|
|
||||||
hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);
|
|
||||||
|
|
||||||
UInt32 curMatch = _hash[kFixHashSize + hashValue];
|
|
||||||
_hash[kFixHashSize + hashValue] = _pos;
|
|
||||||
|
|
||||||
UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
|
|
||||||
UInt32 ptr1 = (_cyclicBufferPos << 1);
|
|
||||||
|
|
||||||
UInt32 len0, len1;
|
|
||||||
len0 = len1 = kNumHashDirectBytes;
|
|
||||||
|
|
||||||
UInt32 count = _cutValue;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (curMatch <= matchMinPos || count-- == 0)
|
|
||||||
{
|
|
||||||
_son[ptr0] = _son[ptr1] = kEmptyHashValue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 delta = _pos - curMatch;
|
|
||||||
UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
|
|
||||||
(_cyclicBufferPos - delta) :
|
|
||||||
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
|
|
||||||
|
|
||||||
UInt32 pby1 = _bufferOffset + curMatch;
|
|
||||||
UInt32 len = Math.Min(len0, len1);
|
|
||||||
if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
|
|
||||||
{
|
|
||||||
while (++len != lenLimit)
|
|
||||||
if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
|
|
||||||
break;
|
|
||||||
if (len == lenLimit)
|
|
||||||
{
|
|
||||||
_son[ptr1] = _son[cyclicPos];
|
|
||||||
_son[ptr0] = _son[cyclicPos + 1];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
|
|
||||||
{
|
|
||||||
_son[ptr1] = curMatch;
|
|
||||||
ptr1 = cyclicPos + 1;
|
|
||||||
curMatch = _son[ptr1];
|
|
||||||
len1 = len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_son[ptr0] = curMatch;
|
|
||||||
ptr0 = cyclicPos;
|
|
||||||
curMatch = _son[ptr0];
|
|
||||||
len0 = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MovePos();
|
|
||||||
}
|
|
||||||
while (--num != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue)
|
|
||||||
{
|
|
||||||
for (UInt32 i = 0; i < numItems; i++)
|
|
||||||
{
|
|
||||||
UInt32 value = items[i];
|
|
||||||
if (value <= subValue)
|
|
||||||
value = kEmptyHashValue;
|
|
||||||
else
|
|
||||||
value -= subValue;
|
|
||||||
items[i] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Normalize()
|
|
||||||
{
|
|
||||||
UInt32 subValue = _pos - _cyclicBufferSize;
|
|
||||||
NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);
|
|
||||||
NormalizeLinks(_hash, _hashSizeSum, subValue);
|
|
||||||
ReduceOffsets((Int32)subValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
// LzInWindow.cs
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZ
|
|
||||||
{
|
|
||||||
public class InWindow
|
|
||||||
{
|
|
||||||
public Byte[] _bufferBase = null; // pointer to buffer with data
|
|
||||||
System.IO.Stream _stream;
|
|
||||||
UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done
|
|
||||||
bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
|
|
||||||
|
|
||||||
UInt32 _pointerToLastSafePosition;
|
|
||||||
|
|
||||||
public UInt32 _bufferOffset;
|
|
||||||
|
|
||||||
public UInt32 _blockSize; // Size of Allocated memory block
|
|
||||||
public UInt32 _pos; // offset (from _buffer) of curent byte
|
|
||||||
UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
|
|
||||||
UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
|
|
||||||
public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
|
|
||||||
|
|
||||||
public void MoveBlock()
|
|
||||||
{
|
|
||||||
UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore;
|
|
||||||
// we need one additional byte, since MovePos moves on 1 byte.
|
|
||||||
if (offset > 0)
|
|
||||||
offset--;
|
|
||||||
|
|
||||||
UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset;
|
|
||||||
|
|
||||||
// check negative offset ????
|
|
||||||
for (UInt32 i = 0; i < numBytes; i++)
|
|
||||||
_bufferBase[i] = _bufferBase[offset + i];
|
|
||||||
_bufferOffset -= offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void ReadBlock()
|
|
||||||
{
|
|
||||||
if (_streamEndWasReached)
|
|
||||||
return;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos);
|
|
||||||
if (size == 0)
|
|
||||||
return;
|
|
||||||
int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size);
|
|
||||||
if (numReadBytes == 0)
|
|
||||||
{
|
|
||||||
_posLimit = _streamPos;
|
|
||||||
UInt32 pointerToPostion = _bufferOffset + _posLimit;
|
|
||||||
if (pointerToPostion > _pointerToLastSafePosition)
|
|
||||||
_posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset);
|
|
||||||
|
|
||||||
_streamEndWasReached = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_streamPos += (UInt32)numReadBytes;
|
|
||||||
if (_streamPos >= _pos + _keepSizeAfter)
|
|
||||||
_posLimit = _streamPos - _keepSizeAfter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Free() { _bufferBase = null; }
|
|
||||||
|
|
||||||
public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
|
|
||||||
{
|
|
||||||
_keepSizeBefore = keepSizeBefore;
|
|
||||||
_keepSizeAfter = keepSizeAfter;
|
|
||||||
UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
|
|
||||||
if (_bufferBase == null || _blockSize != blockSize)
|
|
||||||
{
|
|
||||||
Free();
|
|
||||||
_blockSize = blockSize;
|
|
||||||
_bufferBase = new Byte[_blockSize];
|
|
||||||
}
|
|
||||||
_pointerToLastSafePosition = _blockSize - keepSizeAfter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetStream(System.IO.Stream stream) { _stream = stream; }
|
|
||||||
public void ReleaseStream() { _stream = null; }
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
_bufferOffset = 0;
|
|
||||||
_pos = 0;
|
|
||||||
_streamPos = 0;
|
|
||||||
_streamEndWasReached = false;
|
|
||||||
ReadBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MovePos()
|
|
||||||
{
|
|
||||||
_pos++;
|
|
||||||
if (_pos > _posLimit)
|
|
||||||
{
|
|
||||||
UInt32 pointerToPostion = _bufferOffset + _pos;
|
|
||||||
if (pointerToPostion > _pointerToLastSafePosition)
|
|
||||||
MoveBlock();
|
|
||||||
ReadBlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; }
|
|
||||||
|
|
||||||
// index + limit have not to exceed _keepSizeAfter;
|
|
||||||
public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
|
|
||||||
{
|
|
||||||
if (_streamEndWasReached)
|
|
||||||
if ((_pos + index) + limit > _streamPos)
|
|
||||||
limit = _streamPos - (UInt32)(_pos + index);
|
|
||||||
distance++;
|
|
||||||
// Byte *pby = _buffer + (size_t)_pos + index;
|
|
||||||
UInt32 pby = _bufferOffset + _pos + (UInt32)index;
|
|
||||||
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; }
|
|
||||||
|
|
||||||
public void ReduceOffsets(Int32 subValue)
|
|
||||||
{
|
|
||||||
_bufferOffset += (UInt32)subValue;
|
|
||||||
_posLimit -= (UInt32)subValue;
|
|
||||||
_pos -= (UInt32)subValue;
|
|
||||||
_streamPos -= (UInt32)subValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
// LzOutWindow.cs
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZ
|
|
||||||
{
|
|
||||||
public class OutWindow
|
|
||||||
{
|
|
||||||
byte[] _buffer = null;
|
|
||||||
uint _pos;
|
|
||||||
uint _windowSize = 0;
|
|
||||||
uint _streamPos;
|
|
||||||
System.IO.Stream _stream;
|
|
||||||
|
|
||||||
public uint TrainSize = 0;
|
|
||||||
|
|
||||||
public void Create(uint windowSize)
|
|
||||||
{
|
|
||||||
if (_windowSize != windowSize)
|
|
||||||
{
|
|
||||||
// System.GC.Collect();
|
|
||||||
_buffer = new byte[windowSize];
|
|
||||||
}
|
|
||||||
_windowSize = windowSize;
|
|
||||||
_pos = 0;
|
|
||||||
_streamPos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init(System.IO.Stream stream, bool solid)
|
|
||||||
{
|
|
||||||
ReleaseStream();
|
|
||||||
_stream = stream;
|
|
||||||
if (!solid)
|
|
||||||
{
|
|
||||||
_streamPos = 0;
|
|
||||||
_pos = 0;
|
|
||||||
TrainSize = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Train(System.IO.Stream stream)
|
|
||||||
{
|
|
||||||
long len = stream.Length;
|
|
||||||
uint size = (len < _windowSize) ? (uint)len : _windowSize;
|
|
||||||
TrainSize = size;
|
|
||||||
stream.Position = len - size;
|
|
||||||
_streamPos = _pos = 0;
|
|
||||||
while (size > 0)
|
|
||||||
{
|
|
||||||
uint curSize = _windowSize - _pos;
|
|
||||||
if (size < curSize)
|
|
||||||
curSize = size;
|
|
||||||
int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize);
|
|
||||||
if (numReadBytes == 0)
|
|
||||||
return false;
|
|
||||||
size -= (uint)numReadBytes;
|
|
||||||
_pos += (uint)numReadBytes;
|
|
||||||
_streamPos += (uint)numReadBytes;
|
|
||||||
if (_pos == _windowSize)
|
|
||||||
_streamPos = _pos = 0;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReleaseStream()
|
|
||||||
{
|
|
||||||
Flush();
|
|
||||||
_stream = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Flush()
|
|
||||||
{
|
|
||||||
uint size = _pos - _streamPos;
|
|
||||||
if (size == 0)
|
|
||||||
return;
|
|
||||||
_stream.Write(_buffer, (int)_streamPos, (int)size);
|
|
||||||
if (_pos >= _windowSize)
|
|
||||||
_pos = 0;
|
|
||||||
_streamPos = _pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CopyBlock(uint distance, uint len)
|
|
||||||
{
|
|
||||||
uint pos = _pos - distance - 1;
|
|
||||||
if (pos >= _windowSize)
|
|
||||||
pos += _windowSize;
|
|
||||||
for (; len > 0; len--)
|
|
||||||
{
|
|
||||||
if (pos >= _windowSize)
|
|
||||||
pos = 0;
|
|
||||||
_buffer[_pos++] = _buffer[pos++];
|
|
||||||
if (_pos >= _windowSize)
|
|
||||||
Flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PutByte(byte b)
|
|
||||||
{
|
|
||||||
_buffer[_pos++] = b;
|
|
||||||
if (_pos >= _windowSize)
|
|
||||||
Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte GetByte(uint distance)
|
|
||||||
{
|
|
||||||
uint pos = _pos - distance - 1;
|
|
||||||
if (pos >= _windowSize)
|
|
||||||
pos += _windowSize;
|
|
||||||
return _buffer[pos];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
// LzmaBase.cs
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZMA
|
|
||||||
{
|
|
||||||
internal abstract class Base
|
|
||||||
{
|
|
||||||
public const uint kNumRepDistances = 4;
|
|
||||||
public const uint kNumStates = 12;
|
|
||||||
|
|
||||||
// static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
|
|
||||||
// static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
|
|
||||||
// static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
|
|
||||||
// static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
|
|
||||||
|
|
||||||
public struct State
|
|
||||||
{
|
|
||||||
public uint Index;
|
|
||||||
public void Init() { Index = 0; }
|
|
||||||
public void UpdateChar()
|
|
||||||
{
|
|
||||||
if (Index < 4) Index = 0;
|
|
||||||
else if (Index < 10) Index -= 3;
|
|
||||||
else Index -= 6;
|
|
||||||
}
|
|
||||||
public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); }
|
|
||||||
public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); }
|
|
||||||
public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); }
|
|
||||||
public bool IsCharState() { return Index < 7; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public const int kNumPosSlotBits = 6;
|
|
||||||
public const int kDicLogSizeMin = 0;
|
|
||||||
// public const int kDicLogSizeMax = 30;
|
|
||||||
// public const uint kDistTableSizeMax = kDicLogSizeMax * 2;
|
|
||||||
|
|
||||||
public const int kNumLenToPosStatesBits = 2; // it's for speed optimization
|
|
||||||
public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits;
|
|
||||||
|
|
||||||
public const uint kMatchMinLen = 2;
|
|
||||||
|
|
||||||
public static uint GetLenToPosState(uint len)
|
|
||||||
{
|
|
||||||
len -= kMatchMinLen;
|
|
||||||
if (len < kNumLenToPosStates)
|
|
||||||
return len;
|
|
||||||
return (uint)(kNumLenToPosStates - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public const int kNumAlignBits = 4;
|
|
||||||
public const uint kAlignTableSize = 1 << kNumAlignBits;
|
|
||||||
public const uint kAlignMask = (kAlignTableSize - 1);
|
|
||||||
|
|
||||||
public const uint kStartPosModelIndex = 4;
|
|
||||||
public const uint kEndPosModelIndex = 14;
|
|
||||||
public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
|
|
||||||
|
|
||||||
public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2);
|
|
||||||
|
|
||||||
public const uint kNumLitPosStatesBitsEncodingMax = 4;
|
|
||||||
public const uint kNumLitContextBitsMax = 8;
|
|
||||||
|
|
||||||
public const int kNumPosStatesBitsMax = 4;
|
|
||||||
public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax);
|
|
||||||
public const int kNumPosStatesBitsEncodingMax = 4;
|
|
||||||
public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);
|
|
||||||
|
|
||||||
public const int kNumLowLenBits = 3;
|
|
||||||
public const int kNumMidLenBits = 3;
|
|
||||||
public const int kNumHighLenBits = 8;
|
|
||||||
public const uint kNumLowLenSymbols = 1 << kNumLowLenBits;
|
|
||||||
public const uint kNumMidLenSymbols = 1 << kNumMidLenBits;
|
|
||||||
public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols +
|
|
||||||
(1 << kNumHighLenBits);
|
|
||||||
public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,402 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
// LzmaDecoder.cs
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZMA
|
|
||||||
{
|
|
||||||
using RangeCoder;
|
|
||||||
|
|
||||||
public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream
|
|
||||||
{
|
|
||||||
class LenDecoder
|
|
||||||
{
|
|
||||||
BitDecoder m_Choice = new BitDecoder();
|
|
||||||
BitDecoder m_Choice2 = new BitDecoder();
|
|
||||||
BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
|
|
||||||
BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
|
|
||||||
BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits);
|
|
||||||
uint m_NumPosStates = 0;
|
|
||||||
|
|
||||||
public void Create(uint numPosStates)
|
|
||||||
{
|
|
||||||
for (uint posState = m_NumPosStates; posState < numPosStates; posState++)
|
|
||||||
{
|
|
||||||
m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits);
|
|
||||||
m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits);
|
|
||||||
}
|
|
||||||
m_NumPosStates = numPosStates;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
m_Choice.Init();
|
|
||||||
for (uint posState = 0; posState < m_NumPosStates; posState++)
|
|
||||||
{
|
|
||||||
m_LowCoder[posState].Init();
|
|
||||||
m_MidCoder[posState].Init();
|
|
||||||
}
|
|
||||||
m_Choice2.Init();
|
|
||||||
m_HighCoder.Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState)
|
|
||||||
{
|
|
||||||
if (m_Choice.Decode(rangeDecoder) == 0)
|
|
||||||
return m_LowCoder[posState].Decode(rangeDecoder);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint symbol = Base.kNumLowLenSymbols;
|
|
||||||
if (m_Choice2.Decode(rangeDecoder) == 0)
|
|
||||||
symbol += m_MidCoder[posState].Decode(rangeDecoder);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
symbol += Base.kNumMidLenSymbols;
|
|
||||||
symbol += m_HighCoder.Decode(rangeDecoder);
|
|
||||||
}
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class LiteralDecoder
|
|
||||||
{
|
|
||||||
struct Decoder2
|
|
||||||
{
|
|
||||||
BitDecoder[] m_Decoders;
|
|
||||||
public void Create() { m_Decoders = new BitDecoder[0x300]; }
|
|
||||||
public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); }
|
|
||||||
|
|
||||||
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder)
|
|
||||||
{
|
|
||||||
uint symbol = 1;
|
|
||||||
do
|
|
||||||
symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
|
|
||||||
while (symbol < 0x100);
|
|
||||||
return (byte)symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte)
|
|
||||||
{
|
|
||||||
uint symbol = 1;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
uint matchBit = (uint)(matchByte >> 7) & 1;
|
|
||||||
matchByte <<= 1;
|
|
||||||
uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder);
|
|
||||||
symbol = (symbol << 1) | bit;
|
|
||||||
if (matchBit != bit)
|
|
||||||
{
|
|
||||||
while (symbol < 0x100)
|
|
||||||
symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (symbol < 0x100);
|
|
||||||
return (byte)symbol;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Decoder2[] m_Coders;
|
|
||||||
int m_NumPrevBits;
|
|
||||||
int m_NumPosBits;
|
|
||||||
uint m_PosMask;
|
|
||||||
|
|
||||||
public void Create(int numPosBits, int numPrevBits)
|
|
||||||
{
|
|
||||||
if (m_Coders != null && m_NumPrevBits == numPrevBits &&
|
|
||||||
m_NumPosBits == numPosBits)
|
|
||||||
return;
|
|
||||||
m_NumPosBits = numPosBits;
|
|
||||||
m_PosMask = ((uint)1 << numPosBits) - 1;
|
|
||||||
m_NumPrevBits = numPrevBits;
|
|
||||||
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
|
|
||||||
m_Coders = new Decoder2[numStates];
|
|
||||||
for (uint i = 0; i < numStates; i++)
|
|
||||||
m_Coders[i].Create();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
|
|
||||||
for (uint i = 0; i < numStates; i++)
|
|
||||||
m_Coders[i].Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint GetState(uint pos, byte prevByte)
|
|
||||||
{ return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }
|
|
||||||
|
|
||||||
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)
|
|
||||||
{ return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
|
|
||||||
|
|
||||||
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)
|
|
||||||
{ return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
|
|
||||||
};
|
|
||||||
|
|
||||||
LZ.OutWindow m_OutWindow = new LZ.OutWindow();
|
|
||||||
RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder();
|
|
||||||
|
|
||||||
BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
|
|
||||||
BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates];
|
|
||||||
BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates];
|
|
||||||
BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates];
|
|
||||||
BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates];
|
|
||||||
BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
|
|
||||||
|
|
||||||
BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];
|
|
||||||
BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
|
|
||||||
|
|
||||||
BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits);
|
|
||||||
|
|
||||||
LenDecoder m_LenDecoder = new LenDecoder();
|
|
||||||
LenDecoder m_RepLenDecoder = new LenDecoder();
|
|
||||||
|
|
||||||
LiteralDecoder m_LiteralDecoder = new LiteralDecoder();
|
|
||||||
|
|
||||||
uint m_DictionarySize;
|
|
||||||
uint m_DictionarySizeCheck;
|
|
||||||
|
|
||||||
uint m_PosStateMask;
|
|
||||||
|
|
||||||
public Decoder()
|
|
||||||
{
|
|
||||||
m_DictionarySize = 0xFFFFFFFF;
|
|
||||||
for (int i = 0; i < Base.kNumLenToPosStates; i++)
|
|
||||||
m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetDictionarySize(uint dictionarySize)
|
|
||||||
{
|
|
||||||
if (m_DictionarySize != dictionarySize)
|
|
||||||
{
|
|
||||||
m_DictionarySize = dictionarySize;
|
|
||||||
m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1);
|
|
||||||
uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12));
|
|
||||||
m_OutWindow.Create(blockSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetLiteralProperties(int lp, int lc)
|
|
||||||
{
|
|
||||||
if (lp > 8)
|
|
||||||
throw new InvalidParamException();
|
|
||||||
if (lc > 8)
|
|
||||||
throw new InvalidParamException();
|
|
||||||
m_LiteralDecoder.Create(lp, lc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetPosBitsProperties(int pb)
|
|
||||||
{
|
|
||||||
if (pb > Base.kNumPosStatesBitsMax)
|
|
||||||
throw new InvalidParamException();
|
|
||||||
uint numPosStates = (uint)1 << pb;
|
|
||||||
m_LenDecoder.Create(numPosStates);
|
|
||||||
m_RepLenDecoder.Create(numPosStates);
|
|
||||||
m_PosStateMask = numPosStates - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _solid = false;
|
|
||||||
void Init(System.IO.Stream inStream, System.IO.Stream outStream)
|
|
||||||
{
|
|
||||||
m_RangeDecoder.Init(inStream);
|
|
||||||
m_OutWindow.Init(outStream, _solid);
|
|
||||||
|
|
||||||
uint i;
|
|
||||||
for (i = 0; i < Base.kNumStates; i++)
|
|
||||||
{
|
|
||||||
for (uint j = 0; j <= m_PosStateMask; j++)
|
|
||||||
{
|
|
||||||
uint index = (i << Base.kNumPosStatesBitsMax) + j;
|
|
||||||
m_IsMatchDecoders[index].Init();
|
|
||||||
m_IsRep0LongDecoders[index].Init();
|
|
||||||
}
|
|
||||||
m_IsRepDecoders[i].Init();
|
|
||||||
m_IsRepG0Decoders[i].Init();
|
|
||||||
m_IsRepG1Decoders[i].Init();
|
|
||||||
m_IsRepG2Decoders[i].Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_LiteralDecoder.Init();
|
|
||||||
for (i = 0; i < Base.kNumLenToPosStates; i++)
|
|
||||||
m_PosSlotDecoder[i].Init();
|
|
||||||
// m_PosSpecDecoder.Init();
|
|
||||||
for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
|
|
||||||
m_PosDecoders[i].Init();
|
|
||||||
|
|
||||||
m_LenDecoder.Init();
|
|
||||||
m_RepLenDecoder.Init();
|
|
||||||
m_PosAlignDecoder.Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
|
|
||||||
Int64 inSize, Int64 outSize, ICodeProgress progress)
|
|
||||||
{
|
|
||||||
Init(inStream, outStream);
|
|
||||||
|
|
||||||
Base.State state = new Base.State();
|
|
||||||
state.Init();
|
|
||||||
uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
|
|
||||||
|
|
||||||
UInt64 nowPos64 = 0;
|
|
||||||
UInt64 outSize64 = (UInt64)outSize;
|
|
||||||
if (nowPos64 < outSize64)
|
|
||||||
{
|
|
||||||
if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)
|
|
||||||
throw new DataErrorException();
|
|
||||||
state.UpdateChar();
|
|
||||||
byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);
|
|
||||||
m_OutWindow.PutByte(b);
|
|
||||||
nowPos64++;
|
|
||||||
}
|
|
||||||
while (nowPos64 < outSize64)
|
|
||||||
{
|
|
||||||
progress.SetProgress(inStream.Position, (long)nowPos64);
|
|
||||||
// UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);
|
|
||||||
// while(nowPos64 < next)
|
|
||||||
{
|
|
||||||
uint posState = (uint)nowPos64 & m_PosStateMask;
|
|
||||||
if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
byte prevByte = m_OutWindow.GetByte(0);
|
|
||||||
if (!state.IsCharState())
|
|
||||||
b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder,
|
|
||||||
(uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0));
|
|
||||||
else
|
|
||||||
b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte);
|
|
||||||
m_OutWindow.PutByte(b);
|
|
||||||
state.UpdateChar();
|
|
||||||
nowPos64++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint len;
|
|
||||||
if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1)
|
|
||||||
{
|
|
||||||
if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0)
|
|
||||||
{
|
|
||||||
if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
|
|
||||||
{
|
|
||||||
state.UpdateShortRep();
|
|
||||||
m_OutWindow.PutByte(m_OutWindow.GetByte(rep0));
|
|
||||||
nowPos64++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UInt32 distance;
|
|
||||||
if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0)
|
|
||||||
{
|
|
||||||
distance = rep1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0)
|
|
||||||
distance = rep2;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
distance = rep3;
|
|
||||||
rep3 = rep2;
|
|
||||||
}
|
|
||||||
rep2 = rep1;
|
|
||||||
}
|
|
||||||
rep1 = rep0;
|
|
||||||
rep0 = distance;
|
|
||||||
}
|
|
||||||
len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
|
|
||||||
state.UpdateRep();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rep3 = rep2;
|
|
||||||
rep2 = rep1;
|
|
||||||
rep1 = rep0;
|
|
||||||
len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
|
|
||||||
state.UpdateMatch();
|
|
||||||
uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
|
|
||||||
if (posSlot >= Base.kStartPosModelIndex)
|
|
||||||
{
|
|
||||||
int numDirectBits = (int)((posSlot >> 1) - 1);
|
|
||||||
rep0 = ((2 | (posSlot & 1)) << numDirectBits);
|
|
||||||
if (posSlot < Base.kEndPosModelIndex)
|
|
||||||
rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
|
|
||||||
rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rep0 += (m_RangeDecoder.DecodeDirectBits(
|
|
||||||
numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits);
|
|
||||||
rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rep0 = posSlot;
|
|
||||||
}
|
|
||||||
if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck)
|
|
||||||
{
|
|
||||||
if (rep0 == 0xFFFFFFFF)
|
|
||||||
break;
|
|
||||||
throw new DataErrorException();
|
|
||||||
}
|
|
||||||
m_OutWindow.CopyBlock(rep0, len);
|
|
||||||
nowPos64 += len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_OutWindow.Flush();
|
|
||||||
m_OutWindow.ReleaseStream();
|
|
||||||
m_RangeDecoder.ReleaseStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetDecoderProperties(byte[] properties)
|
|
||||||
{
|
|
||||||
if (properties.Length < 5)
|
|
||||||
throw new InvalidParamException();
|
|
||||||
int lc = properties[0] % 9;
|
|
||||||
int remainder = properties[0] / 9;
|
|
||||||
int lp = remainder % 5;
|
|
||||||
int pb = remainder / 5;
|
|
||||||
if (pb > Base.kNumPosStatesBitsMax)
|
|
||||||
throw new InvalidParamException();
|
|
||||||
UInt32 dictionarySize = 0;
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8);
|
|
||||||
SetDictionarySize(dictionarySize);
|
|
||||||
SetLiteralProperties(lp, lc);
|
|
||||||
SetPosBitsProperties(pb);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Train(System.IO.Stream stream)
|
|
||||||
{
|
|
||||||
_solid = true;
|
|
||||||
return m_OutWindow.Train(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
public override bool CanRead { get { return true; }}
|
|
||||||
public override bool CanWrite { get { return true; }}
|
|
||||||
public override bool CanSeek { get { return true; }}
|
|
||||||
public override long Length { get { return 0; }}
|
|
||||||
public override long Position
|
|
||||||
{
|
|
||||||
get { return 0; }
|
|
||||||
set { }
|
|
||||||
}
|
|
||||||
public override void Flush() { }
|
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public override long Seek(long offset, System.IO.SeekOrigin origin)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
public override void SetLength(long value) {}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,237 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.RangeCoder
|
|
||||||
{
|
|
||||||
class Encoder
|
|
||||||
{
|
|
||||||
public const uint kTopValue = (1 << 24);
|
|
||||||
|
|
||||||
System.IO.Stream Stream;
|
|
||||||
|
|
||||||
public UInt64 Low;
|
|
||||||
public uint Range;
|
|
||||||
uint _cacheSize;
|
|
||||||
byte _cache;
|
|
||||||
|
|
||||||
long StartPosition;
|
|
||||||
|
|
||||||
public void SetStream(System.IO.Stream stream)
|
|
||||||
{
|
|
||||||
Stream = stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReleaseStream()
|
|
||||||
{
|
|
||||||
Stream = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
StartPosition = Stream.Position;
|
|
||||||
|
|
||||||
Low = 0;
|
|
||||||
Range = 0xFFFFFFFF;
|
|
||||||
_cacheSize = 1;
|
|
||||||
_cache = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void FlushData()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 5; i++)
|
|
||||||
ShiftLow();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void FlushStream()
|
|
||||||
{
|
|
||||||
Stream.Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CloseStream()
|
|
||||||
{
|
|
||||||
Stream.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Encode(uint start, uint size, uint total)
|
|
||||||
{
|
|
||||||
Low += start * (Range /= total);
|
|
||||||
Range *= size;
|
|
||||||
while (Range < kTopValue)
|
|
||||||
{
|
|
||||||
Range <<= 8;
|
|
||||||
ShiftLow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ShiftLow()
|
|
||||||
{
|
|
||||||
if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1)
|
|
||||||
{
|
|
||||||
byte temp = _cache;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Stream.WriteByte((byte)(temp + (Low >> 32)));
|
|
||||||
temp = 0xFF;
|
|
||||||
}
|
|
||||||
while (--_cacheSize != 0);
|
|
||||||
_cache = (byte)(((uint)Low) >> 24);
|
|
||||||
}
|
|
||||||
_cacheSize++;
|
|
||||||
Low = ((uint)Low) << 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EncodeDirectBits(uint v, int numTotalBits)
|
|
||||||
{
|
|
||||||
for (int i = numTotalBits - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
Range >>= 1;
|
|
||||||
if (((v >> i) & 1) == 1)
|
|
||||||
Low += Range;
|
|
||||||
if (Range < kTopValue)
|
|
||||||
{
|
|
||||||
Range <<= 8;
|
|
||||||
ShiftLow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EncodeBit(uint size0, int numTotalBits, uint symbol)
|
|
||||||
{
|
|
||||||
uint newBound = (Range >> numTotalBits) * size0;
|
|
||||||
if (symbol == 0)
|
|
||||||
Range = newBound;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Low += newBound;
|
|
||||||
Range -= newBound;
|
|
||||||
}
|
|
||||||
while (Range < kTopValue)
|
|
||||||
{
|
|
||||||
Range <<= 8;
|
|
||||||
ShiftLow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public long GetProcessedSizeAdd()
|
|
||||||
{
|
|
||||||
return _cacheSize +
|
|
||||||
Stream.Position - StartPosition + 4;
|
|
||||||
// (long)Stream.GetProcessedSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Decoder
|
|
||||||
{
|
|
||||||
public const uint kTopValue = (1 << 24);
|
|
||||||
public uint Range;
|
|
||||||
public uint Code;
|
|
||||||
// public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
|
|
||||||
public System.IO.Stream Stream;
|
|
||||||
|
|
||||||
public void Init(System.IO.Stream stream)
|
|
||||||
{
|
|
||||||
// Stream.Init(stream);
|
|
||||||
Stream = stream;
|
|
||||||
|
|
||||||
Code = 0;
|
|
||||||
Range = 0xFFFFFFFF;
|
|
||||||
for (int i = 0; i < 5; i++)
|
|
||||||
Code = (Code << 8) | (byte)Stream.ReadByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReleaseStream()
|
|
||||||
{
|
|
||||||
// Stream.ReleaseStream();
|
|
||||||
Stream = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CloseStream()
|
|
||||||
{
|
|
||||||
Stream.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Normalize()
|
|
||||||
{
|
|
||||||
while (Range < kTopValue)
|
|
||||||
{
|
|
||||||
Code = (Code << 8) | (byte)Stream.ReadByte();
|
|
||||||
Range <<= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Normalize2()
|
|
||||||
{
|
|
||||||
if (Range < kTopValue)
|
|
||||||
{
|
|
||||||
Code = (Code << 8) | (byte)Stream.ReadByte();
|
|
||||||
Range <<= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint GetThreshold(uint total)
|
|
||||||
{
|
|
||||||
return Code / (Range /= total);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Decode(uint start, uint size, uint total)
|
|
||||||
{
|
|
||||||
Code -= start * Range;
|
|
||||||
Range *= size;
|
|
||||||
Normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint DecodeDirectBits(int numTotalBits)
|
|
||||||
{
|
|
||||||
uint range = Range;
|
|
||||||
uint code = Code;
|
|
||||||
uint result = 0;
|
|
||||||
for (int i = numTotalBits; i > 0; i--)
|
|
||||||
{
|
|
||||||
range >>= 1;
|
|
||||||
/*
|
|
||||||
result <<= 1;
|
|
||||||
if (code >= range)
|
|
||||||
{
|
|
||||||
code -= range;
|
|
||||||
result |= 1;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
uint t = (code - range) >> 31;
|
|
||||||
code -= range & (t - 1);
|
|
||||||
result = (result << 1) | (1 - t);
|
|
||||||
|
|
||||||
if (range < kTopValue)
|
|
||||||
{
|
|
||||||
code = (code << 8) | (byte)Stream.ReadByte();
|
|
||||||
range <<= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Range = range;
|
|
||||||
Code = code;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint DecodeBit(uint size0, int numTotalBits)
|
|
||||||
{
|
|
||||||
uint newBound = (Range >> numTotalBits) * size0;
|
|
||||||
uint symbol;
|
|
||||||
if (Code < newBound)
|
|
||||||
{
|
|
||||||
symbol = 0;
|
|
||||||
Range = newBound;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
symbol = 1;
|
|
||||||
Code -= newBound;
|
|
||||||
Range -= newBound;
|
|
||||||
}
|
|
||||||
Normalize();
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ulong GetProcessedSize() {return Stream.GetProcessedSize(); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.RangeCoder
|
|
||||||
{
|
|
||||||
struct BitEncoder
|
|
||||||
{
|
|
||||||
public const int kNumBitModelTotalBits = 11;
|
|
||||||
public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
|
|
||||||
const int kNumMoveBits = 5;
|
|
||||||
const int kNumMoveReducingBits = 2;
|
|
||||||
public const int kNumBitPriceShiftBits = 6;
|
|
||||||
|
|
||||||
uint Prob;
|
|
||||||
|
|
||||||
public void Init() { Prob = kBitModelTotal >> 1; }
|
|
||||||
|
|
||||||
public void UpdateModel(uint symbol)
|
|
||||||
{
|
|
||||||
if (symbol == 0)
|
|
||||||
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
|
|
||||||
else
|
|
||||||
Prob -= (Prob) >> kNumMoveBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Encode(Encoder encoder, uint symbol)
|
|
||||||
{
|
|
||||||
// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
|
|
||||||
// UpdateModel(symbol);
|
|
||||||
uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob;
|
|
||||||
if (symbol == 0)
|
|
||||||
{
|
|
||||||
encoder.Range = newBound;
|
|
||||||
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
encoder.Low += newBound;
|
|
||||||
encoder.Range -= newBound;
|
|
||||||
Prob -= (Prob) >> kNumMoveBits;
|
|
||||||
}
|
|
||||||
if (encoder.Range < Encoder.kTopValue)
|
|
||||||
{
|
|
||||||
encoder.Range <<= 8;
|
|
||||||
encoder.ShiftLow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits];
|
|
||||||
|
|
||||||
static BitEncoder()
|
|
||||||
{
|
|
||||||
const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);
|
|
||||||
for (int i = kNumBits - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
UInt32 start = (UInt32)1 << (kNumBits - i - 1);
|
|
||||||
UInt32 end = (UInt32)1 << (kNumBits - i);
|
|
||||||
for (UInt32 j = start; j < end; j++)
|
|
||||||
ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) +
|
|
||||||
(((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint GetPrice(uint symbol)
|
|
||||||
{
|
|
||||||
return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
|
|
||||||
}
|
|
||||||
public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; }
|
|
||||||
public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; }
|
|
||||||
}
|
|
||||||
|
|
||||||
struct BitDecoder
|
|
||||||
{
|
|
||||||
public const int kNumBitModelTotalBits = 11;
|
|
||||||
public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
|
|
||||||
const int kNumMoveBits = 5;
|
|
||||||
|
|
||||||
uint Prob;
|
|
||||||
|
|
||||||
public void UpdateModel(int numMoveBits, uint symbol)
|
|
||||||
{
|
|
||||||
if (symbol == 0)
|
|
||||||
Prob += (kBitModelTotal - Prob) >> numMoveBits;
|
|
||||||
else
|
|
||||||
Prob -= (Prob) >> numMoveBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init() { Prob = kBitModelTotal >> 1; }
|
|
||||||
|
|
||||||
public uint Decode(RangeCoder.Decoder rangeDecoder)
|
|
||||||
{
|
|
||||||
uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob;
|
|
||||||
if (rangeDecoder.Code < newBound)
|
|
||||||
{
|
|
||||||
rangeDecoder.Range = newBound;
|
|
||||||
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
|
|
||||||
if (rangeDecoder.Range < Decoder.kTopValue)
|
|
||||||
{
|
|
||||||
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
|
|
||||||
rangeDecoder.Range <<= 8;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rangeDecoder.Range -= newBound;
|
|
||||||
rangeDecoder.Code -= newBound;
|
|
||||||
Prob -= (Prob) >> kNumMoveBits;
|
|
||||||
if (rangeDecoder.Range < Decoder.kTopValue)
|
|
||||||
{
|
|
||||||
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
|
|
||||||
rangeDecoder.Range <<= 8;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,160 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.RangeCoder
|
|
||||||
{
|
|
||||||
struct BitTreeEncoder
|
|
||||||
{
|
|
||||||
BitEncoder[] Models;
|
|
||||||
int NumBitLevels;
|
|
||||||
|
|
||||||
public BitTreeEncoder(int numBitLevels)
|
|
||||||
{
|
|
||||||
NumBitLevels = numBitLevels;
|
|
||||||
Models = new BitEncoder[1 << numBitLevels];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
for (uint i = 1; i < (1 << NumBitLevels); i++)
|
|
||||||
Models[i].Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Encode(Encoder rangeEncoder, UInt32 symbol)
|
|
||||||
{
|
|
||||||
UInt32 m = 1;
|
|
||||||
for (int bitIndex = NumBitLevels; bitIndex > 0; )
|
|
||||||
{
|
|
||||||
bitIndex--;
|
|
||||||
UInt32 bit = (symbol >> bitIndex) & 1;
|
|
||||||
Models[m].Encode(rangeEncoder, bit);
|
|
||||||
m = (m << 1) | bit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
|
|
||||||
{
|
|
||||||
UInt32 m = 1;
|
|
||||||
for (UInt32 i = 0; i < NumBitLevels; i++)
|
|
||||||
{
|
|
||||||
UInt32 bit = symbol & 1;
|
|
||||||
Models[m].Encode(rangeEncoder, bit);
|
|
||||||
m = (m << 1) | bit;
|
|
||||||
symbol >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UInt32 GetPrice(UInt32 symbol)
|
|
||||||
{
|
|
||||||
UInt32 price = 0;
|
|
||||||
UInt32 m = 1;
|
|
||||||
for (int bitIndex = NumBitLevels; bitIndex > 0; )
|
|
||||||
{
|
|
||||||
bitIndex--;
|
|
||||||
UInt32 bit = (symbol >> bitIndex) & 1;
|
|
||||||
price += Models[m].GetPrice(bit);
|
|
||||||
m = (m << 1) + bit;
|
|
||||||
}
|
|
||||||
return price;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UInt32 ReverseGetPrice(UInt32 symbol)
|
|
||||||
{
|
|
||||||
UInt32 price = 0;
|
|
||||||
UInt32 m = 1;
|
|
||||||
for (int i = NumBitLevels; i > 0; i--)
|
|
||||||
{
|
|
||||||
UInt32 bit = symbol & 1;
|
|
||||||
symbol >>= 1;
|
|
||||||
price += Models[m].GetPrice(bit);
|
|
||||||
m = (m << 1) | bit;
|
|
||||||
}
|
|
||||||
return price;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,
|
|
||||||
int NumBitLevels, UInt32 symbol)
|
|
||||||
{
|
|
||||||
UInt32 price = 0;
|
|
||||||
UInt32 m = 1;
|
|
||||||
for (int i = NumBitLevels; i > 0; i--)
|
|
||||||
{
|
|
||||||
UInt32 bit = symbol & 1;
|
|
||||||
symbol >>= 1;
|
|
||||||
price += Models[startIndex + m].GetPrice(bit);
|
|
||||||
m = (m << 1) | bit;
|
|
||||||
}
|
|
||||||
return price;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,
|
|
||||||
Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)
|
|
||||||
{
|
|
||||||
UInt32 m = 1;
|
|
||||||
for (int i = 0; i < NumBitLevels; i++)
|
|
||||||
{
|
|
||||||
UInt32 bit = symbol & 1;
|
|
||||||
Models[startIndex + m].Encode(rangeEncoder, bit);
|
|
||||||
m = (m << 1) | bit;
|
|
||||||
symbol >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct BitTreeDecoder
|
|
||||||
{
|
|
||||||
BitDecoder[] Models;
|
|
||||||
int NumBitLevels;
|
|
||||||
|
|
||||||
public BitTreeDecoder(int numBitLevels)
|
|
||||||
{
|
|
||||||
NumBitLevels = numBitLevels;
|
|
||||||
Models = new BitDecoder[1 << numBitLevels];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
for (uint i = 1; i < (1 << NumBitLevels); i++)
|
|
||||||
Models[i].Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Decode(RangeCoder.Decoder rangeDecoder)
|
|
||||||
{
|
|
||||||
uint m = 1;
|
|
||||||
for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)
|
|
||||||
m = (m << 1) + Models[m].Decode(rangeDecoder);
|
|
||||||
return m - ((uint)1 << NumBitLevels);
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint ReverseDecode(RangeCoder.Decoder rangeDecoder)
|
|
||||||
{
|
|
||||||
uint m = 1;
|
|
||||||
uint symbol = 0;
|
|
||||||
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
|
|
||||||
{
|
|
||||||
uint bit = Models[m].Decode(rangeDecoder);
|
|
||||||
m <<= 1;
|
|
||||||
m += bit;
|
|
||||||
symbol |= (bit << bitIndex);
|
|
||||||
}
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,
|
|
||||||
RangeCoder.Decoder rangeDecoder, int NumBitLevels)
|
|
||||||
{
|
|
||||||
uint m = 1;
|
|
||||||
uint symbol = 0;
|
|
||||||
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
|
|
||||||
{
|
|
||||||
uint bit = Models[startIndex + m].Decode(rangeDecoder);
|
|
||||||
m <<= 1;
|
|
||||||
m += bit;
|
|
||||||
symbol |= (bit << bitIndex);
|
|
||||||
}
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,160 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
// ICoder.h
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The exception that is thrown when an error in input stream occurs during decoding.
|
|
||||||
/// </summary>
|
|
||||||
class DataErrorException : Exception
|
|
||||||
{
|
|
||||||
public DataErrorException(): base("Data Error") { }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The exception that is thrown when the value of an argument is outside the allowable range.
|
|
||||||
/// </summary>
|
|
||||||
class InvalidParamException : Exception
|
|
||||||
{
|
|
||||||
public InvalidParamException(): base("Invalid Parameter") { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ICodeProgress
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Callback progress.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="inSize">
|
|
||||||
/// input size. -1 if unknown.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="outSize">
|
|
||||||
/// output size. -1 if unknown.
|
|
||||||
/// </param>
|
|
||||||
void SetProgress(Int64 inSize, Int64 outSize);
|
|
||||||
};
|
|
||||||
|
|
||||||
public interface ICoder
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Codes streams.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="inStream">
|
|
||||||
/// input Stream.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="outStream">
|
|
||||||
/// output Stream.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="inSize">
|
|
||||||
/// input Size. -1 if unknown.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="outSize">
|
|
||||||
/// output Size. -1 if unknown.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="progress">
|
|
||||||
/// callback progress reference.
|
|
||||||
/// </param>
|
|
||||||
/// <exception cref="SevenZip.DataErrorException">
|
|
||||||
/// if input stream is not valid
|
|
||||||
/// </exception>
|
|
||||||
void Code(System.IO.Stream inStream, System.IO.Stream outStream,
|
|
||||||
Int64 inSize, Int64 outSize, ICodeProgress progress);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
public interface ICoder2
|
|
||||||
{
|
|
||||||
void Code(ISequentialInStream []inStreams,
|
|
||||||
const UInt64 []inSizes,
|
|
||||||
ISequentialOutStream []outStreams,
|
|
||||||
UInt64 []outSizes,
|
|
||||||
ICodeProgress progress);
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides the fields that represent properties idenitifiers for compressing.
|
|
||||||
/// </summary>
|
|
||||||
public enum CoderPropID
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies default property.
|
|
||||||
/// </summary>
|
|
||||||
DefaultProp = 0,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies size of dictionary.
|
|
||||||
/// </summary>
|
|
||||||
DictionarySize,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies size of memory for PPM*.
|
|
||||||
/// </summary>
|
|
||||||
UsedMemorySize,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies order for PPM methods.
|
|
||||||
/// </summary>
|
|
||||||
Order,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies Block Size.
|
|
||||||
/// </summary>
|
|
||||||
BlockSize,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies number of postion state bits for LZMA (0 <= x <= 4).
|
|
||||||
/// </summary>
|
|
||||||
PosStateBits,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies number of literal context bits for LZMA (0 <= x <= 8).
|
|
||||||
/// </summary>
|
|
||||||
LitContextBits,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies number of literal position bits for LZMA (0 <= x <= 4).
|
|
||||||
/// </summary>
|
|
||||||
LitPosBits,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies number of fast bytes for LZ*.
|
|
||||||
/// </summary>
|
|
||||||
NumFastBytes,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B".
|
|
||||||
/// </summary>
|
|
||||||
MatchFinder,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies the number of match finder cyckes.
|
|
||||||
/// </summary>
|
|
||||||
MatchFinderCycles,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies number of passes.
|
|
||||||
/// </summary>
|
|
||||||
NumPasses,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies number of algorithm.
|
|
||||||
/// </summary>
|
|
||||||
Algorithm,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies the number of threads.
|
|
||||||
/// </summary>
|
|
||||||
NumThreads,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies mode with end marker.
|
|
||||||
/// </summary>
|
|
||||||
EndMarker
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
public interface ISetCoderProperties
|
|
||||||
{
|
|
||||||
void SetCoderProperties(CoderPropID[] propIDs, object[] properties);
|
|
||||||
};
|
|
||||||
|
|
||||||
public interface IWriteCoderProperties
|
|
||||||
{
|
|
||||||
void WriteCoderProperties(System.IO.Stream outStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ISetDecoderProperties
|
|
||||||
{
|
|
||||||
void SetDecoderProperties(byte[] properties);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
## LZMA SDK
|
|
||||||
This source came from the C# implementation of LZMA from the LZMA SDK, version 16.02, from http://www.7-zip.org/sdk.html.
|
|
||||||
|
|
||||||
## License
|
|
||||||
LZMA SDK is placed in the public domain.
|
|
||||||
|
|
||||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute the original LZMA SDK code, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.
|
|
||||||
|
|
||||||
## Thanks!
|
|
||||||
Thanks goes to Igor Pavlov for making this available.
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<Import Project="..\..\build\common.props" />
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
|
||||||
<EnableApiCheck>false</EnableApiCheck>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Archive
|
|
||||||
{
|
|
||||||
public struct ProgressReport
|
|
||||||
{
|
|
||||||
public ProgressReport(string phase, long ticks, long total)
|
|
||||||
{
|
|
||||||
Phase = phase;
|
|
||||||
Ticks = ticks;
|
|
||||||
Total = total;
|
|
||||||
}
|
|
||||||
public string Phase { get; }
|
|
||||||
public long Ticks { get; }
|
|
||||||
public long Total { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ProgressReportExtensions
|
|
||||||
{
|
|
||||||
public static void Report(this IProgress<ProgressReport> progress, string phase, long ticks, long total)
|
|
||||||
{
|
|
||||||
progress.Report(new ProgressReport(phase, ticks, total));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
[assembly: AssemblyMetadataAttribute("Serviceable", "True")]
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.IO.Compression;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Archive
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Wraps ThreadLocal<ZipArchive> and exposes Dispose semantics that dispose all archives
|
|
||||||
/// </summary>
|
|
||||||
internal class ThreadLocalZipArchive : IDisposable
|
|
||||||
{
|
|
||||||
private ThreadLocal<ZipArchive> _archive;
|
|
||||||
private bool _disposed = false;
|
|
||||||
|
|
||||||
public ThreadLocalZipArchive(string archivePath, ZipArchive local = null)
|
|
||||||
{
|
|
||||||
_archive = new ThreadLocal<ZipArchive>(() =>
|
|
||||||
new ZipArchive(File.Open(archivePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete), ZipArchiveMode.Read),
|
|
||||||
trackAllValues:true);
|
|
||||||
|
|
||||||
if (local != null)
|
|
||||||
{
|
|
||||||
// reuse provided one for current thread
|
|
||||||
_archive.Value = local;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ZipArchive Archive { get { return _archive.Value; } }
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (!_disposed)
|
|
||||||
{
|
|
||||||
if (_archive != null)
|
|
||||||
{
|
|
||||||
// dispose all archives
|
|
||||||
if (_archive.Values != null)
|
|
||||||
{
|
|
||||||
foreach (var value in _archive.Values)
|
|
||||||
{
|
|
||||||
if (value != null)
|
|
||||||
{
|
|
||||||
value.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// dispose ThreadLocal
|
|
||||||
_archive.Dispose();
|
|
||||||
_archive = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Cli.CommandLine
|
|
||||||
{
|
|
||||||
internal class CommandArgument
|
|
||||||
{
|
|
||||||
public CommandArgument()
|
|
||||||
{
|
|
||||||
Values = new List<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public List<string> Values { get; private set; }
|
|
||||||
public bool MultipleValues { get; set; }
|
|
||||||
public string Value
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Values.FirstOrDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,693 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Cli.CommandLine
|
|
||||||
{
|
|
||||||
internal class CommandLineApplication
|
|
||||||
{
|
|
||||||
private enum ParseOptionResult
|
|
||||||
{
|
|
||||||
Succeeded,
|
|
||||||
ShowHelp,
|
|
||||||
ShowVersion,
|
|
||||||
UnexpectedArgs,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Indicates whether the parser should throw an exception when it runs into an unexpected argument.
|
|
||||||
// If this field is set to false, the parser will stop parsing when it sees an unexpected argument, and all
|
|
||||||
// remaining arguments, including the first unexpected argument, will be stored in RemainingArguments property.
|
|
||||||
private readonly bool _throwOnUnexpectedArg;
|
|
||||||
|
|
||||||
public CommandLineApplication(bool throwOnUnexpectedArg = true)
|
|
||||||
{
|
|
||||||
_throwOnUnexpectedArg = throwOnUnexpectedArg;
|
|
||||||
Options = new List<CommandOption>();
|
|
||||||
Arguments = new List<CommandArgument>();
|
|
||||||
Commands = new List<CommandLineApplication>();
|
|
||||||
RemainingArguments = new List<string>();
|
|
||||||
Invoke = () => 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandLineApplication Parent { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string FullName { get; set; }
|
|
||||||
public string Syntax { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public List<CommandOption> Options { get; private set; }
|
|
||||||
public CommandOption OptionHelp { get; private set; }
|
|
||||||
public CommandOption OptionVersion { get; private set; }
|
|
||||||
public List<CommandArgument> Arguments { get; private set; }
|
|
||||||
public List<string> RemainingArguments { get; private set; }
|
|
||||||
public bool IsShowingInformation { get; protected set; } // Is showing help or version?
|
|
||||||
public Func<int> Invoke { get; set; }
|
|
||||||
public Func<string> LongVersionGetter { get; set; }
|
|
||||||
public Func<string> ShortVersionGetter { get; set; }
|
|
||||||
public List<CommandLineApplication> Commands { get; private set; }
|
|
||||||
public bool HandleResponseFiles { get; set; }
|
|
||||||
public bool AllowArgumentSeparator { get; set; }
|
|
||||||
public bool HandleRemainingArguments { get; set; }
|
|
||||||
public string ArgumentSeparatorHelpText { get; set; }
|
|
||||||
|
|
||||||
public CommandLineApplication AddCommand(string name, bool throwOnUnexpectedArg = true)
|
|
||||||
{
|
|
||||||
return AddCommand(name, _ => { }, throwOnUnexpectedArg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandLineApplication AddCommand(string name, Action<CommandLineApplication> configuration,
|
|
||||||
bool throwOnUnexpectedArg = true)
|
|
||||||
{
|
|
||||||
var command = new CommandLineApplication(throwOnUnexpectedArg) { Name = name };
|
|
||||||
return AddCommand(command, configuration, throwOnUnexpectedArg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandLineApplication AddCommand(CommandLineApplication command, bool throwOnUnexpectedArg = true)
|
|
||||||
{
|
|
||||||
return AddCommand(command, _ => { }, throwOnUnexpectedArg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandLineApplication AddCommand(
|
|
||||||
CommandLineApplication command,
|
|
||||||
Action<CommandLineApplication> configuration,
|
|
||||||
bool throwOnUnexpectedArg = true)
|
|
||||||
{
|
|
||||||
if (command == null || configuration == null)
|
|
||||||
{
|
|
||||||
throw new NullReferenceException();
|
|
||||||
}
|
|
||||||
|
|
||||||
command.Parent = this;
|
|
||||||
Commands.Add(command);
|
|
||||||
configuration(command);
|
|
||||||
return command;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandOption Option(string template, string description, CommandOptionType optionType)
|
|
||||||
{
|
|
||||||
return Option(template, description, optionType, _ => { });
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandOption Option(string template, string description, CommandOptionType optionType, Action<CommandOption> configuration)
|
|
||||||
{
|
|
||||||
var option = new CommandOption(template, optionType) { Description = description };
|
|
||||||
Options.Add(option);
|
|
||||||
configuration(option);
|
|
||||||
return option;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandArgument Argument(string name, string description, bool multipleValues = false)
|
|
||||||
{
|
|
||||||
return Argument(name, description, _ => { }, multipleValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandArgument Argument(string name, string description, Action<CommandArgument> configuration, bool multipleValues = false)
|
|
||||||
{
|
|
||||||
var lastArg = Arguments.LastOrDefault();
|
|
||||||
if (lastArg != null && lastArg.MultipleValues)
|
|
||||||
{
|
|
||||||
var message = string.Format(LocalizableStrings.LastArgumentMultiValueError,
|
|
||||||
lastArg.Name);
|
|
||||||
throw new InvalidOperationException(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
var argument = new CommandArgument { Name = name, Description = description, MultipleValues = multipleValues };
|
|
||||||
Arguments.Add(argument);
|
|
||||||
configuration(argument);
|
|
||||||
return argument;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnExecute(Func<int> invoke)
|
|
||||||
{
|
|
||||||
Invoke = invoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnExecute(Func<Task<int>> invoke)
|
|
||||||
{
|
|
||||||
Invoke = () => invoke().Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Execute(params string[] args)
|
|
||||||
{
|
|
||||||
CommandLineApplication command = this;
|
|
||||||
CommandArgumentEnumerator arguments = null;
|
|
||||||
|
|
||||||
if (HandleResponseFiles)
|
|
||||||
{
|
|
||||||
args = ExpandResponseFiles(args).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var index = 0; index < args.Length; index++)
|
|
||||||
{
|
|
||||||
var arg = args[index];
|
|
||||||
|
|
||||||
bool isLongOption = arg.StartsWith("--");
|
|
||||||
if (arg == "-?" || arg == "/?")
|
|
||||||
{
|
|
||||||
command.ShowHelp();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (isLongOption || arg.StartsWith("-"))
|
|
||||||
{
|
|
||||||
CommandOption option;
|
|
||||||
|
|
||||||
var result = ParseOption(isLongOption, command, args, ref index, out option);
|
|
||||||
|
|
||||||
|
|
||||||
if (result == ParseOptionResult.ShowHelp)
|
|
||||||
{
|
|
||||||
command.ShowHelp();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (result == ParseOptionResult.ShowVersion)
|
|
||||||
{
|
|
||||||
command.ShowVersion();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (result == ParseOptionResult.UnexpectedArgs)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var subcommand = ParseSubCommand(arg, command);
|
|
||||||
if (subcommand != null)
|
|
||||||
{
|
|
||||||
command = subcommand;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (arguments == null || arguments.CommandName != command.Name)
|
|
||||||
{
|
|
||||||
arguments = new CommandArgumentEnumerator(command.Arguments.GetEnumerator(), command.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arguments.MoveNext())
|
|
||||||
{
|
|
||||||
arguments.Current.Values.Add(arg);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HandleUnexpectedArg(command, args, index, argTypeName: "command or argument");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Commands.Count > 0 && command == this)
|
|
||||||
{
|
|
||||||
throw new CommandParsingException(
|
|
||||||
command,
|
|
||||||
"Required command missing",
|
|
||||||
isRequiredSubCommandMissing: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return command.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ParseOptionResult ParseOption(
|
|
||||||
bool isLongOption,
|
|
||||||
CommandLineApplication command,
|
|
||||||
string[] args,
|
|
||||||
ref int index,
|
|
||||||
out CommandOption option)
|
|
||||||
{
|
|
||||||
option = null;
|
|
||||||
ParseOptionResult result = ParseOptionResult.Succeeded;
|
|
||||||
var arg = args[index];
|
|
||||||
|
|
||||||
int optionPrefixLength = isLongOption ? 2 : 1;
|
|
||||||
string[] optionComponents = arg.Substring(optionPrefixLength).Split(new[] { ':', '=' }, 2);
|
|
||||||
string optionName = optionComponents[0];
|
|
||||||
|
|
||||||
if (isLongOption)
|
|
||||||
{
|
|
||||||
option = command.Options.SingleOrDefault(
|
|
||||||
opt => string.Equals(opt.LongName, optionName, StringComparison.Ordinal));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
option = command.Options.SingleOrDefault(
|
|
||||||
opt => string.Equals(opt.ShortName, optionName, StringComparison.Ordinal));
|
|
||||||
|
|
||||||
if (option == null)
|
|
||||||
{
|
|
||||||
option = command.Options.SingleOrDefault(
|
|
||||||
opt => string.Equals(opt.SymbolName, optionName, StringComparison.Ordinal));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (option == null)
|
|
||||||
{
|
|
||||||
if (isLongOption && string.IsNullOrEmpty(optionName) &&
|
|
||||||
!command._throwOnUnexpectedArg && AllowArgumentSeparator)
|
|
||||||
{
|
|
||||||
// a stand-alone "--" is the argument separator, so skip it and
|
|
||||||
// handle the rest of the args as unexpected args
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
HandleUnexpectedArg(command, args, index, argTypeName: "option");
|
|
||||||
result = ParseOptionResult.UnexpectedArgs;
|
|
||||||
}
|
|
||||||
else if (command.OptionHelp == option)
|
|
||||||
{
|
|
||||||
result = ParseOptionResult.ShowHelp;
|
|
||||||
}
|
|
||||||
else if (command.OptionVersion == option)
|
|
||||||
{
|
|
||||||
result = ParseOptionResult.ShowVersion;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (optionComponents.Length == 2)
|
|
||||||
{
|
|
||||||
if (!option.TryParse(optionComponents[1]))
|
|
||||||
{
|
|
||||||
command.ShowHint();
|
|
||||||
throw new CommandParsingException(command,
|
|
||||||
String.Format(LocalizableStrings.UnexpectedValueForOptionError, optionComponents[1], optionName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (option.OptionType == CommandOptionType.NoValue ||
|
|
||||||
option.OptionType == CommandOptionType.BoolValue)
|
|
||||||
{
|
|
||||||
// No value is needed for this option
|
|
||||||
option.TryParse(null);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index++;
|
|
||||||
|
|
||||||
if (index < args.Length)
|
|
||||||
{
|
|
||||||
arg = args[index];
|
|
||||||
if (!option.TryParse(arg))
|
|
||||||
{
|
|
||||||
command.ShowHint();
|
|
||||||
throw new CommandParsingException(
|
|
||||||
command,
|
|
||||||
String.Format(LocalizableStrings.UnexpectedValueForOptionError, arg, optionName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
command.ShowHint();
|
|
||||||
throw new CommandParsingException(
|
|
||||||
command,
|
|
||||||
String.Format(LocalizableStrings.OptionRequiresSingleValueWhichIsMissing, arg, optionName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private CommandLineApplication ParseSubCommand(string arg, CommandLineApplication command)
|
|
||||||
{
|
|
||||||
foreach (var subcommand in command.Commands)
|
|
||||||
{
|
|
||||||
if (string.Equals(subcommand.Name, arg, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return subcommand;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper method that adds a help option
|
|
||||||
public CommandOption HelpOption(string template)
|
|
||||||
{
|
|
||||||
// Help option is special because we stop parsing once we see it
|
|
||||||
// So we store it separately for further use
|
|
||||||
OptionHelp = Option(template, LocalizableStrings.ShowHelpInfo, CommandOptionType.NoValue);
|
|
||||||
|
|
||||||
return OptionHelp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandOption VersionOption(string template,
|
|
||||||
string shortFormVersion,
|
|
||||||
string longFormVersion = null)
|
|
||||||
{
|
|
||||||
if (longFormVersion == null)
|
|
||||||
{
|
|
||||||
return VersionOption(template, () => shortFormVersion);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return VersionOption(template, () => shortFormVersion, () => longFormVersion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper method that adds a version option
|
|
||||||
public CommandOption VersionOption(string template,
|
|
||||||
Func<string> shortFormVersionGetter,
|
|
||||||
Func<string> longFormVersionGetter = null)
|
|
||||||
{
|
|
||||||
// Version option is special because we stop parsing once we see it
|
|
||||||
// So we store it separately for further use
|
|
||||||
OptionVersion = Option(template, LocalizableStrings.ShowVersionInfo, CommandOptionType.NoValue);
|
|
||||||
ShortVersionGetter = shortFormVersionGetter;
|
|
||||||
LongVersionGetter = longFormVersionGetter ?? shortFormVersionGetter;
|
|
||||||
|
|
||||||
return OptionVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show short hint that reminds users to use help option
|
|
||||||
public void ShowHint()
|
|
||||||
{
|
|
||||||
if (OptionHelp != null)
|
|
||||||
{
|
|
||||||
Console.WriteLine(string.Format(LocalizableStrings.ShowHintInfo, OptionHelp.LongName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show full help
|
|
||||||
public void ShowHelp(string commandName = null)
|
|
||||||
{
|
|
||||||
var headerBuilder = new StringBuilder(LocalizableStrings.UsageHeader);
|
|
||||||
var usagePrefixLength = headerBuilder.Length;
|
|
||||||
for (var cmd = this; cmd != null; cmd = cmd.Parent)
|
|
||||||
{
|
|
||||||
cmd.IsShowingInformation = true;
|
|
||||||
if (cmd != this && cmd.Arguments.Any())
|
|
||||||
{
|
|
||||||
var args = string.Join(" ", cmd.Arguments.Select(arg => arg.Name));
|
|
||||||
headerBuilder.Insert(usagePrefixLength, string.Format(" {0} {1}", cmd.Name, args));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
headerBuilder.Insert(usagePrefixLength, string.Format(" {0}", cmd.Name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandLineApplication target;
|
|
||||||
|
|
||||||
if (commandName == null || string.Equals(Name, commandName, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
target = this;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
target = Commands.SingleOrDefault(cmd => string.Equals(cmd.Name, commandName, StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
if (target != null)
|
|
||||||
{
|
|
||||||
headerBuilder.AppendFormat(" {0}", commandName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// The command name is invalid so don't try to show help for something that doesn't exist
|
|
||||||
target = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var optionsBuilder = new StringBuilder();
|
|
||||||
var commandsBuilder = new StringBuilder();
|
|
||||||
var argumentsBuilder = new StringBuilder();
|
|
||||||
var argumentSeparatorBuilder = new StringBuilder();
|
|
||||||
|
|
||||||
int maxArgLen = 0;
|
|
||||||
for (var cmd = target; cmd != null; cmd = cmd.Parent)
|
|
||||||
{
|
|
||||||
if (cmd.Arguments.Any())
|
|
||||||
{
|
|
||||||
if (cmd == target)
|
|
||||||
{
|
|
||||||
headerBuilder.Append(LocalizableStrings.UsageArgumentsToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argumentsBuilder.Length == 0)
|
|
||||||
{
|
|
||||||
argumentsBuilder.AppendLine();
|
|
||||||
argumentsBuilder.AppendLine(LocalizableStrings.UsageArgumentsHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
maxArgLen = Math.Max(maxArgLen, MaxArgumentLength(cmd.Arguments));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var cmd = target; cmd != null; cmd = cmd.Parent)
|
|
||||||
{
|
|
||||||
if (cmd.Arguments.Any())
|
|
||||||
{
|
|
||||||
foreach (var arg in cmd.Arguments)
|
|
||||||
{
|
|
||||||
argumentsBuilder.AppendFormat(
|
|
||||||
" {0}{1}",
|
|
||||||
arg.Name.PadRight(maxArgLen + 2),
|
|
||||||
arg.Description);
|
|
||||||
argumentsBuilder.AppendLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target.Options.Any())
|
|
||||||
{
|
|
||||||
headerBuilder.Append(LocalizableStrings.UsageOptionsToken);
|
|
||||||
|
|
||||||
optionsBuilder.AppendLine();
|
|
||||||
optionsBuilder.AppendLine(LocalizableStrings.UsageOptionsHeader);
|
|
||||||
var maxOptLen = MaxOptionTemplateLength(target.Options);
|
|
||||||
var outputFormat = string.Format(" {{0, -{0}}}{{1}}", maxOptLen + 2);
|
|
||||||
foreach (var opt in target.Options)
|
|
||||||
{
|
|
||||||
optionsBuilder.AppendFormat(outputFormat, opt.Template, opt.Description);
|
|
||||||
optionsBuilder.AppendLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target.Commands.Any())
|
|
||||||
{
|
|
||||||
headerBuilder.Append(LocalizableStrings.UsageCommandToken);
|
|
||||||
|
|
||||||
commandsBuilder.AppendLine();
|
|
||||||
commandsBuilder.AppendLine(LocalizableStrings.UsageCommandsHeader);
|
|
||||||
var maxCmdLen = MaxCommandLength(target.Commands);
|
|
||||||
var outputFormat = string.Format(" {{0, -{0}}}{{1}}", maxCmdLen + 2);
|
|
||||||
foreach (var cmd in target.Commands.OrderBy(c => c.Name))
|
|
||||||
{
|
|
||||||
commandsBuilder.AppendFormat(outputFormat, cmd.Name, cmd.Description);
|
|
||||||
commandsBuilder.AppendLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OptionHelp != null)
|
|
||||||
{
|
|
||||||
commandsBuilder.AppendLine();
|
|
||||||
commandsBuilder.AppendFormat(LocalizableStrings.UsageCommandsDetailHelp, Name);
|
|
||||||
commandsBuilder.AppendLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target.AllowArgumentSeparator || target.HandleRemainingArguments)
|
|
||||||
{
|
|
||||||
if (target.AllowArgumentSeparator)
|
|
||||||
{
|
|
||||||
headerBuilder.Append(LocalizableStrings.UsageCommandAdditionalArgs);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
headerBuilder.Append(LocalizableStrings.UsageCommandArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(target.ArgumentSeparatorHelpText))
|
|
||||||
{
|
|
||||||
argumentSeparatorBuilder.AppendLine();
|
|
||||||
argumentSeparatorBuilder.AppendLine(LocalizableStrings.UsageCommandsAdditionalArgsHeader);
|
|
||||||
argumentSeparatorBuilder.AppendLine(String.Format(" {0}", target.ArgumentSeparatorHelpText));
|
|
||||||
argumentSeparatorBuilder.AppendLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
headerBuilder.AppendLine();
|
|
||||||
|
|
||||||
var nameAndVersion = new StringBuilder();
|
|
||||||
nameAndVersion.AppendLine(GetFullNameAndVersion());
|
|
||||||
nameAndVersion.AppendLine();
|
|
||||||
|
|
||||||
Console.Write("{0}{1}{2}{3}{4}{5}", nameAndVersion, headerBuilder, argumentsBuilder, optionsBuilder, commandsBuilder, argumentSeparatorBuilder);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ShowVersion()
|
|
||||||
{
|
|
||||||
for (var cmd = this; cmd != null; cmd = cmd.Parent)
|
|
||||||
{
|
|
||||||
cmd.IsShowingInformation = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine(FullName);
|
|
||||||
Console.WriteLine(LongVersionGetter());
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetFullNameAndVersion()
|
|
||||||
{
|
|
||||||
return ShortVersionGetter == null ? FullName : string.Format("{0} {1}", FullName, ShortVersionGetter());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ShowRootCommandFullNameAndVersion()
|
|
||||||
{
|
|
||||||
var rootCmd = this;
|
|
||||||
while (rootCmd.Parent != null)
|
|
||||||
{
|
|
||||||
rootCmd = rootCmd.Parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine(rootCmd.GetFullNameAndVersion());
|
|
||||||
Console.WriteLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int MaxOptionTemplateLength(IEnumerable<CommandOption> options)
|
|
||||||
{
|
|
||||||
var maxLen = 0;
|
|
||||||
foreach (var opt in options)
|
|
||||||
{
|
|
||||||
maxLen = opt.Template.Length > maxLen ? opt.Template.Length : maxLen;
|
|
||||||
}
|
|
||||||
return maxLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int MaxCommandLength(IEnumerable<CommandLineApplication> commands)
|
|
||||||
{
|
|
||||||
var maxLen = 0;
|
|
||||||
foreach (var cmd in commands)
|
|
||||||
{
|
|
||||||
maxLen = cmd.Name.Length > maxLen ? cmd.Name.Length : maxLen;
|
|
||||||
}
|
|
||||||
return maxLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int MaxArgumentLength(IEnumerable<CommandArgument> arguments)
|
|
||||||
{
|
|
||||||
var maxLen = 0;
|
|
||||||
foreach (var arg in arguments)
|
|
||||||
{
|
|
||||||
maxLen = arg.Name.Length > maxLen ? arg.Name.Length : maxLen;
|
|
||||||
}
|
|
||||||
return maxLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleUnexpectedArg(CommandLineApplication command, string[] args, int index, string argTypeName)
|
|
||||||
{
|
|
||||||
if (command._throwOnUnexpectedArg)
|
|
||||||
{
|
|
||||||
command.ShowHint();
|
|
||||||
throw new CommandParsingException(command, String.Format(LocalizableStrings.UnexpectedArgumentError, argTypeName, args[index]));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// All remaining arguments are stored for further use
|
|
||||||
command.RemainingArguments.AddRange(new ArraySegment<string>(args, index, args.Length - index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<string> ExpandResponseFiles(IEnumerable<string> args)
|
|
||||||
{
|
|
||||||
foreach (var arg in args)
|
|
||||||
{
|
|
||||||
if (!arg.StartsWith("@", StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
yield return arg;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var fileName = arg.Substring(1);
|
|
||||||
|
|
||||||
var responseFileArguments = ParseResponseFile(fileName);
|
|
||||||
|
|
||||||
// ParseResponseFile can suppress expanding this response file by
|
|
||||||
// returning null. In that case, we'll treat the response
|
|
||||||
// file token as a regular argument.
|
|
||||||
|
|
||||||
if (responseFileArguments == null)
|
|
||||||
{
|
|
||||||
yield return arg;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var responseFileArgument in responseFileArguments)
|
|
||||||
yield return responseFileArgument.Trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<string> ParseResponseFile(string fileName)
|
|
||||||
{
|
|
||||||
if (!HandleResponseFiles)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (!File.Exists(fileName))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException(String.Format(LocalizableStrings.ResponseFileNotFoundError, fileName));
|
|
||||||
}
|
|
||||||
|
|
||||||
return File.ReadLines(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CommandArgumentEnumerator : IEnumerator<CommandArgument>
|
|
||||||
{
|
|
||||||
private readonly IEnumerator<CommandArgument> _enumerator;
|
|
||||||
|
|
||||||
public CommandArgumentEnumerator(
|
|
||||||
IEnumerator<CommandArgument> enumerator,
|
|
||||||
string commandName)
|
|
||||||
{
|
|
||||||
CommandName = commandName;
|
|
||||||
_enumerator = enumerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string CommandName { get; }
|
|
||||||
|
|
||||||
public CommandArgument Current
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _enumerator.Current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object IEnumerator.Current
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_enumerator.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool MoveNext()
|
|
||||||
{
|
|
||||||
if (Current == null || !Current.MultipleValues)
|
|
||||||
{
|
|
||||||
return _enumerator.MoveNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If current argument allows multiple values, we don't move forward and
|
|
||||||
// all later values will be added to current CommandArgument.Values
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
_enumerator.Reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Cli.CommandLine
|
|
||||||
{
|
|
||||||
internal class CommandOption
|
|
||||||
{
|
|
||||||
public CommandOption(string template, CommandOptionType optionType)
|
|
||||||
{
|
|
||||||
Template = template;
|
|
||||||
OptionType = optionType;
|
|
||||||
Values = new List<string>();
|
|
||||||
|
|
||||||
foreach (var part in Template.Split(new[] { ' ', '|' }, StringSplitOptions.RemoveEmptyEntries))
|
|
||||||
{
|
|
||||||
if (part.StartsWith("--"))
|
|
||||||
{
|
|
||||||
LongName = part.Substring(2);
|
|
||||||
}
|
|
||||||
else if (part.StartsWith("-"))
|
|
||||||
{
|
|
||||||
var optName = part.Substring(1);
|
|
||||||
|
|
||||||
// If there is only one char and it is not an English letter, it is a symbol option (e.g. "-?")
|
|
||||||
if (optName.Length == 1 && !IsEnglishLetter(optName[0]))
|
|
||||||
{
|
|
||||||
SymbolName = optName;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ShortName = optName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (part.StartsWith("<") && part.EndsWith(">"))
|
|
||||||
{
|
|
||||||
ValueName = part.Substring(1, part.Length - 2);
|
|
||||||
}
|
|
||||||
else if (optionType == CommandOptionType.MultipleValue && part.StartsWith("<") && part.EndsWith(">..."))
|
|
||||||
{
|
|
||||||
ValueName = part.Substring(1, part.Length - 5);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new ArgumentException(String.Format(LocalizableStrings.InvalidTemplateError, nameof(template)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(LongName) && string.IsNullOrEmpty(ShortName) && string.IsNullOrEmpty(SymbolName))
|
|
||||||
{
|
|
||||||
throw new ArgumentException(LocalizableStrings.InvalidTemplateError, nameof(template));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Template { get; set; }
|
|
||||||
public string ShortName { get; set; }
|
|
||||||
public string LongName { get; set; }
|
|
||||||
public string SymbolName { get; set; }
|
|
||||||
public string ValueName { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public List<string> Values { get; private set; }
|
|
||||||
public bool? BoolValue { get; private set; }
|
|
||||||
public CommandOptionType OptionType { get; private set; }
|
|
||||||
|
|
||||||
public bool TryParse(string value)
|
|
||||||
{
|
|
||||||
switch (OptionType)
|
|
||||||
{
|
|
||||||
case CommandOptionType.MultipleValue:
|
|
||||||
Values.Add(value);
|
|
||||||
break;
|
|
||||||
case CommandOptionType.SingleValue:
|
|
||||||
if (Values.Any())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Values.Add(value);
|
|
||||||
break;
|
|
||||||
case CommandOptionType.BoolValue:
|
|
||||||
if (Values.Any())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value == null)
|
|
||||||
{
|
|
||||||
// add null to indicate that the option was present, but had no value
|
|
||||||
Values.Add(null);
|
|
||||||
BoolValue = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool boolValue;
|
|
||||||
if (!bool.TryParse(value, out boolValue))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Values.Add(value);
|
|
||||||
BoolValue = boolValue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CommandOptionType.NoValue:
|
|
||||||
if (value != null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Add a value to indicate that this option was specified
|
|
||||||
Values.Add("on");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HasValue()
|
|
||||||
{
|
|
||||||
return Values.Any();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Value()
|
|
||||||
{
|
|
||||||
return HasValue() ? Values[0] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsEnglishLetter(char c)
|
|
||||||
{
|
|
||||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Cli.CommandLine
|
|
||||||
{
|
|
||||||
internal enum CommandOptionType
|
|
||||||
{
|
|
||||||
MultipleValue,
|
|
||||||
SingleValue,
|
|
||||||
BoolValue,
|
|
||||||
NoValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using Microsoft.DotNet.Tools;
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Cli.CommandLine
|
|
||||||
{
|
|
||||||
internal class CommandParsingException : Exception
|
|
||||||
{
|
|
||||||
private readonly bool _isRequiredSubCommandMissing;
|
|
||||||
|
|
||||||
public CommandParsingException(
|
|
||||||
string message,
|
|
||||||
string helpText = null) : base(message)
|
|
||||||
{
|
|
||||||
HelpText = helpText ?? "";
|
|
||||||
Data.Add("CLI_User_Displayed_Exception", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandParsingException(
|
|
||||||
CommandLineApplication command,
|
|
||||||
string message,
|
|
||||||
bool isRequiredSubCommandMissing = false)
|
|
||||||
: this(message)
|
|
||||||
{
|
|
||||||
Command = command;
|
|
||||||
_isRequiredSubCommandMissing = isRequiredSubCommandMissing;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandLineApplication Command { get; }
|
|
||||||
|
|
||||||
public string HelpText { get; } = "";
|
|
||||||
|
|
||||||
public override string Message
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _isRequiredSubCommandMissing
|
|
||||||
? CommonLocalizableStrings.RequiredCommandNotPassed
|
|
||||||
: base.Message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Cli.CommandLine
|
|
||||||
{
|
|
||||||
internal class HelpMessageStrings
|
|
||||||
{
|
|
||||||
internal const string MSBuildAdditionalArgsHelpText = LocalizableStrings.MSBuildAdditionalArgsHelpText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Cli.CommandLine
|
|
||||||
{
|
|
||||||
internal class LocalizableStrings
|
|
||||||
{
|
|
||||||
public const string LastArgumentMultiValueError = "The last argument '{0}' accepts multiple values. No more argument can be added.";
|
|
||||||
|
|
||||||
public const string OptionRequiresSingleValueWhichIsMissing = "Required value for option '{0}' was not provided.";
|
|
||||||
|
|
||||||
public const string UnexpectedValueForOptionError = "Unexpected value '{0}' for option '{1}'";
|
|
||||||
|
|
||||||
public const string UnexpectedArgumentError = "Unrecognized {0} '{1}'";
|
|
||||||
|
|
||||||
public const string ResponseFileNotFoundError = "Response file '{0}' doesn't exist.";
|
|
||||||
|
|
||||||
public const string ShowHelpInfo = "Show help information";
|
|
||||||
|
|
||||||
public const string ShowVersionInfo = "Show version information";
|
|
||||||
|
|
||||||
public const string ShowHintInfo = "Specify --{0} for a list of available options and commands.";
|
|
||||||
|
|
||||||
public const string UsageHeader = "Usage:";
|
|
||||||
|
|
||||||
public const string UsageArgumentsToken = " [arguments]";
|
|
||||||
|
|
||||||
public const string UsageArgumentsHeader = "Arguments:";
|
|
||||||
|
|
||||||
public const string UsageOptionsToken = " [options]";
|
|
||||||
|
|
||||||
public const string UsageOptionsHeader = "Options:";
|
|
||||||
|
|
||||||
public const string UsageCommandToken = " [command]";
|
|
||||||
|
|
||||||
public const string UsageCommandsHeader = "Commands:";
|
|
||||||
|
|
||||||
public const string UsageCommandsDetailHelp = "Use \"{0} [command] --help\" for more information about a command.";
|
|
||||||
|
|
||||||
public const string UsageCommandArgs = " [args]";
|
|
||||||
|
|
||||||
public const string UsageCommandAdditionalArgs = " [[--] <additional arguments>...]]";
|
|
||||||
|
|
||||||
public const string UsageCommandsAdditionalArgsHeader = "Additional Arguments:";
|
|
||||||
|
|
||||||
public const string InvalidTemplateError = "Invalid template pattern '{0}'";
|
|
||||||
|
|
||||||
public const string MSBuildAdditionalArgsHelpText = "Any extra options that should be passed to MSBuild. See 'dotnet msbuild -h' for available options.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,189 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Tools
|
|
||||||
{
|
|
||||||
internal class CommonLocalizableStrings
|
|
||||||
{
|
|
||||||
public const string UnsupportedProjectType = "Unsupported project type. Please check with your sdk provider.";
|
|
||||||
public const string ProjectAlreadyHasAreference = "Project already has a reference to `{0}`.";
|
|
||||||
public const string ProjectReferenceCouldNotBeFound = "Project reference `{0}` could not be found.";
|
|
||||||
public const string ProjectReferenceRemoved = "Project reference `{0}` removed.";
|
|
||||||
|
|
||||||
// Project related
|
|
||||||
public const string Project = "Project";
|
|
||||||
public const string ProjectFile = "Project file";
|
|
||||||
public const string Reference = "Reference";
|
|
||||||
public const string ProjectReference = "Project reference";
|
|
||||||
public const string ProjectReferenceOneOrMore = "Project reference(s)";
|
|
||||||
public const string PackageReference = "Package reference";
|
|
||||||
public const string P2P = "Project to Project";
|
|
||||||
public const string P2PReference = "Project to Project reference";
|
|
||||||
public const string Package = "Package";
|
|
||||||
public const string Solution = "Solution";
|
|
||||||
public const string SolutionFile = "Solution file";
|
|
||||||
public const string Executable = "Executable";
|
|
||||||
public const string Library = "Library";
|
|
||||||
public const string Program = "Program";
|
|
||||||
public const string Application = "Application";
|
|
||||||
public const string ReferenceAddedToTheProject = "Reference `{0}` added to the project.";
|
|
||||||
|
|
||||||
// Verbs
|
|
||||||
public const string Add = "Add";
|
|
||||||
public const string Remove = "Remove";
|
|
||||||
public const string Delete = "Delete";
|
|
||||||
public const string Update = "Update";
|
|
||||||
public const string New = "New";
|
|
||||||
public const string List = "List";
|
|
||||||
public const string Load = "Load";
|
|
||||||
public const string Save = "Save";
|
|
||||||
public const string Find = "Find";
|
|
||||||
|
|
||||||
// Other
|
|
||||||
public const string Error = "Error";
|
|
||||||
public const string Warning = "Warning";
|
|
||||||
|
|
||||||
public const string File = "File";
|
|
||||||
public const string Directory = "Directory";
|
|
||||||
|
|
||||||
public const string Type = "Type";
|
|
||||||
public const string Value = "Value";
|
|
||||||
public const string Group = "Group";
|
|
||||||
|
|
||||||
// General sentences";
|
|
||||||
public const string XAddedToY = "{0} added to {1}.";
|
|
||||||
public const string XRemovedFromY = "{0} removed from {1}.";
|
|
||||||
public const string XDeletedFromY = "{0} deleted from {1}.";
|
|
||||||
public const string XSuccessfullyUpdated = "{0} successfully updated.";
|
|
||||||
|
|
||||||
// General errors
|
|
||||||
/// Invalid
|
|
||||||
public const string XIsInvalid = "{0} is invalid.";
|
|
||||||
public const string XYFoundButInvalid = "{0} `{1}` found but is invalid.";
|
|
||||||
public const string XFoundButInvalid = "`{0}` found but is invalid.";
|
|
||||||
public const string OperationInvalid = "Operation is invalid.";
|
|
||||||
public const string OperationXInvalid = "Operation {0} is invalid.";
|
|
||||||
|
|
||||||
/// Not Found
|
|
||||||
public const string XNotFound = "{0} not found.";
|
|
||||||
public const string XOrYNotFound = "{0} or {1} not found.";
|
|
||||||
public const string XOrYNotFoundInZ = "{0} or {1} not found in `{2}`.";
|
|
||||||
public const string FileNotFound = "File `{0}` not found.";
|
|
||||||
|
|
||||||
/// Does not exist
|
|
||||||
public const string XDoesNotExist = "{0} does not exist.";
|
|
||||||
public const string XYDoesNotExist = "{0} `{1}` does not exist.";
|
|
||||||
|
|
||||||
/// Duplicate
|
|
||||||
public const string MoreThanOneXFound = "More than one {0} found.";
|
|
||||||
public const string XAlreadyContainsY = "{0} already contains {1}.";
|
|
||||||
public const string XAlreadyContainsYZ = "{0} already contains {1} `{2}`.";
|
|
||||||
public const string XAlreadyHasY = "{0} already has {1}.";
|
|
||||||
public const string XAlreadyHasYZ = "{0} already has {1} `{2}`.";
|
|
||||||
|
|
||||||
/// Other
|
|
||||||
public const string XWasNotExpected = "{0} was not expected.";
|
|
||||||
public const string XNotProvided = "{0} not provided.";
|
|
||||||
public const string SpecifyAtLeastOne = "Please specify at least one {0}.";
|
|
||||||
public const string CouldNotConnectWithTheServer = "Could not connect with the server.";
|
|
||||||
|
|
||||||
// Command Line Parsing
|
|
||||||
public const string RequiredArgumentIsInvalid = "Required argument {0} is invalid.";
|
|
||||||
public const string OptionIsInvalid = "Option {0} is invalid.";
|
|
||||||
public const string ArgumentIsInvalid = "Argument {0} is invalid.";
|
|
||||||
public const string RequiredArgumentNotPassed = "Required argument {0} was not provided.";
|
|
||||||
public const string RequiredCommandNotPassed = "Required command was not provided.";
|
|
||||||
|
|
||||||
// dotnet <verb>
|
|
||||||
/// Project
|
|
||||||
public const string CouldNotFindAnyProjectInDirectory = "Could not find any project in `{0}`.";
|
|
||||||
public const string CouldNotFindProjectOrDirectory = "Could not find project or directory `{0}`.";
|
|
||||||
public const string MoreThanOneProjectInDirectory = "Found more than one project in `{0}`. Please specify which one to use.";
|
|
||||||
public const string FoundInvalidProject = "Found a project `{0}` but it is invalid.";
|
|
||||||
public const string InvalidProject = "Invalid project `{0}`.";
|
|
||||||
|
|
||||||
/// Solution
|
|
||||||
public const string CouldNotFindSolutionIn = "Specified solution file {0} does not exist, or there is no solution file in the directory.";
|
|
||||||
public const string CouldNotFindSolutionOrDirectory = "Could not find solution or directory `{0}`.";
|
|
||||||
public const string MoreThanOneSolutionInDirectory = "Found more than one solution file in {0}. Please specify which one to use.";
|
|
||||||
public const string InvalidSolutionFormatString = "Invalid solution `{0}`. {1}"; // {0} is the solution path, {1} is already localized details on the failure
|
|
||||||
public const string SolutionDoesNotExist = "Specified solution file {0} does not exist, or there is no solution file in the directory.";
|
|
||||||
|
|
||||||
/// add p2p
|
|
||||||
public const string ReferenceDoesNotExist = "Reference {0} does not exist.";
|
|
||||||
public const string ReferenceIsInvalid = "Reference `{0}` is invalid.";
|
|
||||||
public const string SpecifyAtLeastOneReferenceToAdd = "You must specify at least one reference to add.";
|
|
||||||
public const string ProjectAlreadyHasAReference = "Project {0} already has a reference `{1}`.";
|
|
||||||
|
|
||||||
/// add package
|
|
||||||
public const string PackageReferenceDoesNotExist = "Package reference `{0}` does not exist.";
|
|
||||||
public const string PackageReferenceIsInvalid = "Package reference `{0}` is invalid.";
|
|
||||||
public const string SpecifyAtLeastOnePackageReferenceToAdd = "You must specify at least one package to add.";
|
|
||||||
public const string PackageReferenceAddedToTheProject = "Package reference `{0}` added to the project.";
|
|
||||||
public const string ProjectAlreadyHasAPackageReference = "Project {0} already has a reference `{1}`.";
|
|
||||||
public const string PleaseSpecifyVersion = "Please specify a version of the package.";
|
|
||||||
|
|
||||||
/// add sln
|
|
||||||
public const string ProjectDoesNotExist = "Project `{0}` does not exist.";
|
|
||||||
public const string ProjectIsInvalid = "Project `{0}` is invalid.";
|
|
||||||
public const string SpecifyAtLeastOneProjectToAdd = "You must specify at least one project to add.";
|
|
||||||
public const string ProjectAddedToTheSolution = "Project `{0}` added to the solution.";
|
|
||||||
public const string SolutionAlreadyContainsProject = "Solution {0} already contains project {1}.";
|
|
||||||
|
|
||||||
/// del p2p
|
|
||||||
public const string ReferenceNotFoundInTheProject = "Specified reference {0} does not exist in project {1}.";
|
|
||||||
public const string ReferenceRemoved = "Reference `{0}` deleted from the project.";
|
|
||||||
public const string SpecifyAtLeastOneReferenceToRemove = "You must specify at least one reference to remove.";
|
|
||||||
public const string ReferenceDeleted = "Reference `{0}` deleted.";
|
|
||||||
|
|
||||||
/// del pkg
|
|
||||||
public const string PackageReferenceNotFoundInTheProject = "Package reference `{0}` could not be found in the project.";
|
|
||||||
public const string PackageReferenceRemoved = "Reference `{0}` deleted from the project.";
|
|
||||||
public const string SpecifyAtLeastOnePackageReferenceToRemove = "You must specify at least one package reference to remove.";
|
|
||||||
public const string PackageReferenceDeleted = "Package reference `{0}` deleted.";
|
|
||||||
|
|
||||||
/// del sln
|
|
||||||
public const string ProjectNotFoundInTheSolution = "Project `{0}` could not be found in the solution.";
|
|
||||||
public const string ProjectRemoved = "Project `{0}` removed from solution.";
|
|
||||||
public const string SpecifyAtLeastOneProjectToRemove = "You must specify at least one project to remove.";
|
|
||||||
public const string ProjectDeleted = "Project `{0}` deleted from solution.";
|
|
||||||
|
|
||||||
/// list
|
|
||||||
public const string NoReferencesFound = "There are no {0} references in project {1}. ;; {0} is the type of the item being requested (project, package, p2p) and {1} is the object operated on (a project file or a solution file). ";
|
|
||||||
public const string NoProjectsFound = "No projects found in the solution.";
|
|
||||||
|
|
||||||
/// arguments
|
|
||||||
public const string ArgumentsProjectOrSolutionDescription = "The project or solution to operation on. If a file is not specified, the current directory is searched.";
|
|
||||||
|
|
||||||
/// sln
|
|
||||||
public const string ArgumentsProjectDescription = "The project file to operate on. If a file is not specified, the command will search the current directory for one.";
|
|
||||||
public const string ArgumentsSolutionDescription = "Solution file to operate on. If not specified, the command will search the current directory for one.";
|
|
||||||
public const string CmdSlnFile = "SLN_FILE";
|
|
||||||
public const string CmdProjectFile = "PROJECT";
|
|
||||||
|
|
||||||
/// commands
|
|
||||||
public const string CmdFramework = "FRAMEWORK";
|
|
||||||
|
|
||||||
/// update pkg
|
|
||||||
public const string PleaseSpecifyNewVersion = "Please specify new version of the package.";
|
|
||||||
public const string PleaseSpecifyWhichPackageToUpdate = "Please specify which package to update.";
|
|
||||||
public const string NothingToUpdate = "Nothing to update.";
|
|
||||||
public const string EverythingUpToDate = "Everything is already up-to-date.";
|
|
||||||
public const string PackageVersionUpdatedTo = "Version of package `{0}` updated to `{1}`.";
|
|
||||||
public const string PackageVersionUpdated = "Version of package `{0}` updated.";
|
|
||||||
public const string CouldNotUpdateTheVersion = "Could not update the version of the package `{0}`.";
|
|
||||||
|
|
||||||
/// new
|
|
||||||
public const string TemplateCreatedSuccessfully = "The template {0} created successfully. Please run \"dotnet restore\" to get started!";
|
|
||||||
public const string TemplateInstalledSuccesfully = "The template {0} installed successfully. You can use \"dotnet new {0}\" to get started with the new template.";
|
|
||||||
public const string TemplateCreateError = "Template {0} could not be created. Error returned was: {1}.";
|
|
||||||
public const string TemplateInstallError = "Template {0} could not be installed. Error returned was: {1}.";
|
|
||||||
public const string SpecifiedNameExists = "Specified name {0} already exists. Please specify a different name.";
|
|
||||||
public const string SpecifiedAliasExists = "Specified alias {0} already exists. Please specify a different alias.";
|
|
||||||
public const string MandatoryParameterMissing = "Mandatory parameter {0} missing for template {1}. ";
|
|
||||||
|
|
||||||
public const string ProjectNotCompatibleWithFrameworks = "Project `{0}` cannot be added due to incompatible targeted frameworks between the two projects. Please review the project you are trying to add and verify that is compatible with the following targets:";
|
|
||||||
public const string ProjectDoesNotTargetFramework = "Project `{0}` does not target framework `{1}`.";
|
|
||||||
public const string ProjectCouldNotBeEvaluated = "Project `{0}` could not be evaluated. Evaluation failed with following error:\n{1}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
using Microsoft.DotNet.Cli.CommandLine;
|
|
||||||
//using Microsoft.DotNet.Cli.Utils;
|
|
||||||
using Microsoft.DotNet.Archive;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Tools.Archive
|
|
||||||
{
|
|
||||||
|
|
||||||
public partial class ArchiveCommand
|
|
||||||
{
|
|
||||||
public static int Main(string[] args)
|
|
||||||
{
|
|
||||||
//DebugHelper.HandleDebugSwitch(ref args);
|
|
||||||
|
|
||||||
var app = new CommandLineApplication();
|
|
||||||
app.Name = "archive";
|
|
||||||
app.FullName = ".NET archiver";
|
|
||||||
app.Description = "Archives and expands sets of files";
|
|
||||||
app.HelpOption("-h|--help");
|
|
||||||
|
|
||||||
var extract = app.Option("-x|--extract <outputDirectory>", "Directory to extract to", CommandOptionType.SingleValue);
|
|
||||||
var archiveFile = app.Option("-a|--archive <file>", "Archive to operate on", CommandOptionType.SingleValue);
|
|
||||||
var externals = app.Option("--external <external>...", "External files and directories to consider for extraction", CommandOptionType.MultipleValue);
|
|
||||||
var sources = app.Argument("<sources>...", "Files & directory to include in the archive", multipleValues: true);
|
|
||||||
|
|
||||||
app.OnExecute(() =>
|
|
||||||
{
|
|
||||||
|
|
||||||
if (extract.HasValue() && sources.Values.Any())
|
|
||||||
{
|
|
||||||
Console.WriteLine("Extract '-x' can only be specified when no '<sources>' are specified to add to the archive.");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (!extract.HasValue() && !sources.Values.Any())
|
|
||||||
{
|
|
||||||
Console.WriteLine("Either extract '-x' or '<sources>' must be specified.");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!archiveFile.HasValue())
|
|
||||||
{
|
|
||||||
Console.WriteLine("Archive '-a' must be specified.");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var progress = new ConsoleProgressReport();
|
|
||||||
|
|
||||||
var archive = new IndexedArchive();
|
|
||||||
foreach (var external in externals.Values)
|
|
||||||
{
|
|
||||||
if (Directory.Exists(external))
|
|
||||||
{
|
|
||||||
archive.AddExternalDirectory(external);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
archive.AddExternalFile(external);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sources.Values.Any())
|
|
||||||
{
|
|
||||||
foreach (var source in sources.Values)
|
|
||||||
{
|
|
||||||
if (Directory.Exists(source))
|
|
||||||
{
|
|
||||||
archive.AddDirectory(source, progress);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
archive.AddFile(source, Path.GetFileName(source));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
archive.Save(archiveFile.Value(), progress);
|
|
||||||
}
|
|
||||||
else // sources not specified, extract must have been specified
|
|
||||||
{
|
|
||||||
archive.Extract(archiveFile.Value(), extract.Value(), progress);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
return app.Execute(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
|
|
||||||
<Import Project="..\..\build\common.props" />
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<EnableApiCheck>false</EnableApiCheck>
|
|
||||||
<RuntimeIdentifiers>win7-x64;linux-x64</RuntimeIdentifiers>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Microsoft.DotNet.Archive\Microsoft.DotNet.Archive.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
Loading…
Reference in New Issue