You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

365 lines
10 KiB

using System;
using System.IO;
namespace SevenZip
{
using CommandLineParser;
public class CDoubleStream: Stream
{
public System.IO.Stream s1;
public System.IO.Stream s2;
public int fileIndex;
public long skipSize;
public override bool CanRead { get { return true; }}
public override bool CanWrite { get { return false; }}
public override bool CanSeek { get { return false; }}
public override long Length { get { return s1.Length + s2.Length - skipSize; } }
public override long Position
{
get { return 0; }
set { }
}
public override void Flush() { }
public override int Read(byte[] buffer, int offset, int count)
{
int numTotal = 0;
while (count > 0)
{
if (fileIndex == 0)
{
int num = s1.Read(buffer, offset, count);
offset += num;
count -= num;
numTotal += num;
if (num == 0)
fileIndex++;
}
if (fileIndex == 1)
{
numTotal += s2.Read(buffer, offset, count);
return numTotal;
}
}
return numTotal;
}
public override void Write(byte[] buffer, int offset, int count)
{
throw (new Exception("can't Write"));
}
public override long Seek(long offset, System.IO.SeekOrigin origin)
{
throw (new Exception("can't Seek"));
}
public override void SetLength(long value)
{
throw (new Exception("can't SetLength"));
}
}
class LzmaAlone
{
enum Key
{
Help1 = 0,
Help2,
Mode,
Dictionary,
FastBytes,
LitContext,
LitPos,
PosBits,
MatchFinder,
EOS,
StdIn,
StdOut,
Train
};
static void PrintHelp()
{
System.Console.WriteLine("\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" +
" e: encode file\n" +
" d: decode file\n" +
" b: Benchmark\n" +
"<Switches>\n" +
// " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" +
" -d{N}: set dictionary - [0, 29], default: 23 (8MB)\n" +
" -fb{N}: set number of fast bytes - [5, 273], default: 128\n" +
" -lc{N}: set number of literal context bits - [0, 8], default: 3\n" +
" -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" +
" -pb{N}: set number of pos bits - [0, 4], default: 2\n" +
" -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" +
" -eos: write End Of Stream marker\n"
// + " -si: read data from stdin\n"
// + " -so: write data to stdout\n"
);
}
static bool GetNumber(string s, out Int32 v)
{
v = 0;
for (int i = 0; i < s.Length; i++)
{
char c = s[i];
if (c < '0' || c > '9')
return false;
v *= 10;
v += (Int32)(c - '0');
}
return true;
}
static int IncorrectCommand()
{
throw (new Exception("Command line error"));
// System.Console.WriteLine("\nCommand line error\n");
// return 1;
}
static int Main2(string[] args)
{
System.Console.WriteLine("\nLZMA# 4.61 2008-11-23\n");
if (args.Length == 0)
{
PrintHelp();
return 0;
}
SwitchForm[] kSwitchForms = new SwitchForm[13];
int sw = 0;
kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false);
kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false);
kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1);
kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1);
kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1);
kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1);
kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1);
kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1);
kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1);
kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false);
kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false);
kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false);
kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1);
Parser parser = new Parser(sw);
try
{
parser.ParseStrings(kSwitchForms, args);
}
catch
{
return IncorrectCommand();
}
if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs)
{
PrintHelp();
return 0;
}
System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings;
int paramIndex = 0;
if (paramIndex >= nonSwitchStrings.Count)
return IncorrectCommand();
string command = (string)nonSwitchStrings[paramIndex++];
command = command.ToLower();
bool dictionaryIsDefined = false;
Int32 dictionary = 1 << 21;
if (parser[(int)Key.Dictionary].ThereIs)
{
Int32 dicLog;
if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog))
IncorrectCommand();
dictionary = (Int32)1 << dicLog;
dictionaryIsDefined = true;
}
string mf = "bt4";
if (parser[(int)Key.MatchFinder].ThereIs)
mf = (string)parser[(int)Key.MatchFinder].PostStrings[0];
mf = mf.ToLower();
if (command == "b")
{
const Int32 kNumDefaultItereations = 10;
Int32 numIterations = kNumDefaultItereations;
if (paramIndex < nonSwitchStrings.Count)
if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations))
numIterations = kNumDefaultItereations;
return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary);
}
string train = "";
if (parser[(int)Key.Train].ThereIs)
train = (string)parser[(int)Key.Train].PostStrings[0];
bool encodeMode = false;
if (command == "e")
encodeMode = true;
else if (command == "d")
encodeMode = false;
else
IncorrectCommand();
bool stdInMode = parser[(int)Key.StdIn].ThereIs;
bool stdOutMode = parser[(int)Key.StdOut].ThereIs;
Stream inStream = null;
if (stdInMode)
{
throw (new Exception("Not implemeted"));
}
else
{
if (paramIndex >= nonSwitchStrings.Count)
IncorrectCommand();
string inputName = (string)nonSwitchStrings[paramIndex++];
inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read);
}
FileStream outStream = null;
if (stdOutMode)
{
throw (new Exception("Not implemeted"));
}
else
{
if (paramIndex >= nonSwitchStrings.Count)
IncorrectCommand();
string outputName = (string)nonSwitchStrings[paramIndex++];
outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write);
}
FileStream trainStream = null;
if (train.Length != 0)
trainStream = new FileStream(train, FileMode.Open, FileAccess.Read);
if (encodeMode)
{
if (!dictionaryIsDefined)
dictionary = 1 << 23;
Int32 posStateBits = 2;
Int32 litContextBits = 3; // for normal files
// UInt32 litContextBits = 0; // for 32-bit data
Int32 litPosBits = 0;
// UInt32 litPosBits = 2; // for 32-bit data
Int32 algorithm = 2;
Int32 numFastBytes = 128;
bool eos = parser[(int)Key.EOS].ThereIs || stdInMode;
if (parser[(int)Key.Mode].ThereIs)
if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm))
IncorrectCommand();
if (parser[(int)Key.FastBytes].ThereIs)
if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes))
IncorrectCommand();
if (parser[(int)Key.LitContext].ThereIs)
if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits))
IncorrectCommand();
if (parser[(int)Key.LitPos].ThereIs)
if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits))
IncorrectCommand();
if (parser[(int)Key.PosBits].ThereIs)
if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits))
IncorrectCommand();
CoderPropID[] propIDs =
{
CoderPropID.DictionarySize,
CoderPropID.PosStateBits,
CoderPropID.LitContextBits,
CoderPropID.LitPosBits,
CoderPropID.Algorithm,
CoderPropID.NumFastBytes,
CoderPropID.MatchFinder,
CoderPropID.EndMarker
};
object[] properties =
{
(Int32)(dictionary),
(Int32)(posStateBits),
(Int32)(litContextBits),
(Int32)(litPosBits),
(Int32)(algorithm),
(Int32)(numFastBytes),
mf,
eos
};
Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder();
encoder.SetCoderProperties(propIDs, properties);
encoder.WriteCoderProperties(outStream);
Int64 fileSize;
if (eos || stdInMode)
fileSize = -1;
else
fileSize = inStream.Length;
for (int i = 0; i < 8; i++)
outStream.WriteByte((Byte)(fileSize >> (8 * i)));
if (trainStream != null)
{
CDoubleStream doubleStream = new CDoubleStream();
doubleStream.s1 = trainStream;
doubleStream.s2 = inStream;
doubleStream.fileIndex = 0;
inStream = doubleStream;
long trainFileSize = trainStream.Length;
doubleStream.skipSize = 0;
if (trainFileSize > dictionary)
doubleStream.skipSize = trainFileSize - dictionary;
trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin);
encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize));
}
encoder.Code(inStream, outStream, -1, -1, null);
}
else if (command == "d")
{
byte[] properties = new byte[5];
if (inStream.Read(properties, 0, 5) != 5)
throw (new Exception("input .lzma is too short"));
Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder();
decoder.SetDecoderProperties(properties);
if (trainStream != null)
{
if (!decoder.Train(trainStream))
throw (new Exception("can't train"));
}
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;
decoder.Code(inStream, outStream, compressedSize, outSize, null);
}
else
throw (new Exception("Command Error"));
return 0;
}
[STAThread]
static int Main(string[] args)
{
try
{
return Main2(args);
}
catch (Exception e)
{
Console.WriteLine("{0} Caught exception #1.", e);
// throw e;
return 1;
}
}
}
}