Compare commits

..

No commits in common. "2643cd350956acbb038cf44fad7284978f84622b" and "34b3ff87222a224b8fbb872e9f998b54c1624597" have entirely different histories.

7 changed files with 122 additions and 171 deletions

View File

@ -5,162 +5,53 @@ namespace AdrianKousz.Util
{ {
public class CmdApp public class CmdApp
{ {
private string header; IApp<string, string[]> app;
private IDictionary<string, Command> cmds; string[] args;
private Command noArgCommand;
private Command defaultCommand;
private CmdApp() { } public CmdApp(IApp<string, string[]> app, string[] args)
public void Run(string[] args)
{ {
Console.WriteLine(header); this.app = app;
Console.WriteLine(); this.args = args;
}
if (args.Length == 0) { public void Run()
noArgCommand.Run(new string[0]); {
Console.Out.WriteLine(app.GetHeader());
Console.Out.WriteLine();
var commands = app.GetCommands();
var showhelp = true;
var requestedcmd = "";
if (args.Length != 0) {
requestedcmd = args[0].Trim().ToLower();
showhelp = !commands.ContainsKey(requestedcmd);
}
if (showhelp) {
Console.Out.WriteLine("Available commands are:");
foreach (var icommand in commands) {
Console.Out.WriteLine(" {0,-12} {1}", icommand.Key, icommand.Value.GetDescription());
}
Console.Out.WriteLine();
return; return;
} }
var cmdname = args[0]; var cmd = commands[requestedcmd];
var cmd = GetCommand(cmdname); var requireargcount = cmd.GetArgumentCount();
if (cmd == null) {
defaultCommand.Run(new string[] { cmdname });
return;
}
var requireargcount = cmd.MinArgumentCount;
if (args.Length - 1 < requireargcount) { if (args.Length - 1 < requireargcount) {
var hint = string.Format(SR.Error_ArgCount, cmdname, requireargcount); Console.Out.WriteLine("Provide at least {0} arguments for \"{1}\". See help:", requireargcount, requestedcmd);
defaultCommand.Run(new string[] { cmdname, hint }); Console.Out.WriteLine();
Console.Out.WriteLine(cmd.GetHelp());
Console.Out.WriteLine();
return; return;
} }
var cmdargs = new string[args.Length - 1]; var cmdargs = new string[args.Length - 1];
Array.Copy(args, 1, cmdargs, 0, cmdargs.Length); Array.Copy(args, 1, cmdargs, 0, cmdargs.Length);
cmd.Run(cmdargs); cmd.SetArguments(cmdargs);
} cmd.Run();
private Command GetCommand(string k)
{
k = k.ToLower();
if (cmds.ContainsKey(k)) return cmds[k];
return null;
}
public abstract class Command
{
public int MinArgumentCount { get; protected set; }
public string Description { get; protected set; } = SR.NoDesc;
public string Help { get; protected set; } = SR.NoHelp;
public abstract void Run(string[] args);
}
public sealed class HelpCommand : Command
{
private CmdApp app;
public HelpCommand(CmdApp app)
{
Description = SR.HelpCmdDesc;
Help = SR.HelpCmdHelp;
this.app = app;
}
public override void Run(string[] args)
{
var sb = new System.Text.StringBuilder();
var showlist = true;
var cmdname = args.Length > 0 ? args[0].ToLower() : "";
if (args.Length > 1)
Console.WriteLine(args[1]);
if (!cmdname.Equals("")) {
var cmd = app.GetCommand(cmdname);
if (cmd == null) {
sb.AppendFormat(SR.Error_NoCmd, cmdname);
sb.AppendLine();
} else {
sb.AppendFormat(SR.HelpFor, cmdname);
sb.AppendLine();
sb.AppendLine();
sb.AppendLine(cmd.Help);
showlist = false;
}
}
if (showlist) {
sb.AppendLine(SR.AvailCmds);
foreach (var cmd in app.cmds) {
sb.AppendFormat(" {0,-12} {1}", cmd.Key, cmd.Value.Description);
sb.AppendLine();
}
}
Console.WriteLine(sb);
if (args.Length == 0) {
Console.WriteLine(SR.PressEnter);
Console.ReadLine();
}
}
}
public sealed class Builder
{
private CmdApp result = new CmdApp();
private Command helpCommand;
public Builder()
{
result.cmds = new Dictionary<string, Command>();
result.header = SR.DefaultAppHeader;
helpCommand = new HelpCommand(result);
result.noArgCommand = helpCommand;
result.defaultCommand = helpCommand;
}
public Builder NoArg(Command value) { result.noArgCommand = value; return this; }
public Builder Default(Command value) { result.defaultCommand = value; return this; }
public Builder Header(string value) { result.header = value; return this; }
public Builder Add(string name, Command command)
{
name = name.ToLower();
if (name == null || name.Equals("") || name.Equals(SR.HelpCmdName))
throw new ArgumentException(SR.Error_CmdNameForbidden);
result.cmds.Add(name, command);
return this;
}
public CmdApp Build()
{
result.cmds.Add(SR.HelpCmdName, helpCommand);
var r = result;
result = null;
return r;
}
}
private static class SR
{
public const string DefaultAppHeader = "Unnamed console application";
public const string HelpCmdName = "help";
public const string HelpCmdDesc = "Get help";
public const string HelpCmdHelp = "List available commands or display help of a command\n\nParameters:\n[<command>]";
public const string NoDesc = "(No short description available)";
public const string NoHelp = "(No help available)";
public const string PressEnter = "Press enter to continue ...";
public const string HelpFor = "Help for {0}:";
public const string AvailCmds = "Available commands are:";
public const string Error_CmdNameForbidden = "Forbidden name";
public const string Error_NoCmd = "\x1b[31mCommand \"{0}\" does not exist!\x1b[0m";
public const string Error_ArgCount = "\x1b[31mCommand \"{0}\" requires at least {1} arguments!\x1b[0m";
} }
} }
} }

View File

@ -9,7 +9,7 @@ namespace AdrianKousz.Util
public bool Strict; public bool Strict;
public Encoding Encoding { get; private set; } public Encoding Encoding { get; private set; }
private const string ErrorChooseMethod = "Choose method with correct integer size"; private const string ErrorChooseMethod = "Choose string writing method";
private const string ErrorHasNull = "String contains trailing null"; private const string ErrorHasNull = "String contains trailing null";
private const string ErrorHasNoNull = "String does not contain trailing null"; private const string ErrorHasNoNull = "String does not contain trailing null";
@ -20,14 +20,17 @@ namespace AdrianKousz.Util
Strict = strict; Strict = strict;
} }
public override string ReadString() { throw new NotSupportedException(ErrorChooseMethod); } public override string ReadString()
public override bool ReadBoolean() { throw new NotSupportedException(ErrorChooseMethod); } {
throw new NotSupportedException(ErrorChooseMethod);
}
public bool ReadBooleanByte() { return ReadByte() != 0; } public override bool ReadBoolean()
public bool ReadBooleanInt16() { return ReadInt16() != 0; } {
public bool ReadBooleanInt32() { return ReadInt32() != 0; } return ReadInt32() != 0;
}
public string ReadString(int len) { return ReadStringInternal(len, false); } public string ReadStringInternal(int len) { return ReadStringInternal(len, false); }
public string ReadStringByte() { return ReadStringInternal(ReadByte(), false); } public string ReadStringByte() { return ReadStringInternal(ReadByte(), false); }
public string ReadStringInt16() { return ReadStringInternal(ReadInt16(), false); } public string ReadStringInt16() { return ReadStringInternal(ReadInt16(), false); }
public string ReadStringInt32() { return ReadStringInternal(ReadInt32(), false); } public string ReadStringInt32() { return ReadStringInternal(ReadInt32(), false); }

View File

@ -8,7 +8,7 @@ namespace AdrianKousz.Util
{ {
public Encoding Encoding { get; private set; } public Encoding Encoding { get; private set; }
private const string ErrorChooseMethod = "Choose method with correct integer size"; private const string ErrorChooseMethod = "Choose string writing method";
private const string ErrorStringTooLong = "String too long"; private const string ErrorStringTooLong = "String too long";
public ExtendedBinaryWriter(Stream stream, Encoding enc) public ExtendedBinaryWriter(Stream stream, Encoding enc)
@ -17,12 +17,16 @@ namespace AdrianKousz.Util
Encoding = enc; Encoding = enc;
} }
public override void Write(string value) { throw new NotSupportedException(ErrorChooseMethod); } public override void Write(string value)
public override void Write(bool value) { throw new NotSupportedException(ErrorChooseMethod); } {
throw new NotSupportedException(ErrorChooseMethod);
}
public void WriteBooleanByte(bool value) { if (value) Write((Byte)1); else Write((Byte)0); } public override void Write(bool value)
public void WriteBooleanInt16(bool value) { if (value) Write((Int16)1); else Write((Int16)0); } {
public void WriteBooleanInt32(bool value) { if (value) Write((Int32)1); else Write((Int32)0); } if (value) Write((Int32)1);
else Write((Int32)0);
}
public void WriteString(string value, int len) { WriteStringInternal(value, len, TypeCode.Empty); } public void WriteString(string value, int len) { WriteStringInternal(value, len, TypeCode.Empty); }
public void WriteStringByte(string value) { WriteStringInternal(value, 0, TypeCode.Byte); } public void WriteStringByte(string value) { WriteStringInternal(value, 0, TypeCode.Byte); }
@ -36,8 +40,15 @@ namespace AdrianKousz.Util
public void WriteZStringInt32(string value) { WriteStringInternal(value + "\0", 0, TypeCode.Int32); } public void WriteZStringInt32(string value) { WriteStringInternal(value + "\0", 0, TypeCode.Int32); }
public void WriteZStringRaw(string value) { WriteStringInternal(value + "\0", 0, TypeCode.Empty); } public void WriteZStringRaw(string value) { WriteStringInternal(value + "\0", 0, TypeCode.Empty); }
public int GetByteCount(string value) { return Encoding.GetByteCount(value); } public int GetByteCount(string value)
public int GetZByteCount(string value) { return Encoding.GetByteCount(value + "\0"); } {
return Encoding.GetByteCount(value);
}
public int GetZByteCount(string value)
{
return Encoding.GetByteCount(value + "\0");
}
private void WriteStringInternal(string value, int len, TypeCode typecode) private void WriteStringInternal(string value, int len, TypeCode typecode)
{ {

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace AdrianKousz.Util
{
public interface IApp<TName, TCmd>
{
string GetHeader();
IDictionary<TName, ICommand<TCmd>> GetCommands();
}
}

View File

@ -0,0 +1,13 @@
using System.Collections.Generic;
namespace AdrianKousz.Util
{
public interface ICommand<T>
{
string GetDescription();
string GetHelp();
int GetArgumentCount();
void SetArguments(T args);
void Run();
}
}

View File

@ -6,38 +6,59 @@ namespace AdrianKousz.Util
{ {
public unsafe class UnsafeBitmap : IDisposable public unsafe class UnsafeBitmap : IDisposable
{ {
private const string ErrorNotLocked = "Bitmap not locked";
private const string ErrorAlreadyLocked = "Bitmap already locked";
private Bitmap bmp; private Bitmap bmp;
private BitmapData bmpdat; private BitmapData bmpdat;
public UnsafeBitmap(Bitmap bmp) public UnsafeBitmap(Bitmap bmp)
: this(bmp, false) { } : this(bmp, false, true) { }
public UnsafeBitmap(Bitmap bmp, bool write) public UnsafeBitmap(Bitmap bmp, bool write)
: this(bmp, write, true) { }
public UnsafeBitmap(Bitmap bmp, bool write, bool locknow)
{ {
this.bmp = bmp; this.bmp = bmp;
var mode = write ? ImageLockMode.ReadWrite : ImageLockMode.ReadOnly; this.bmpdat = null;
var rect = new Rectangle(0, 0, bmp.Width, bmp.Height); if (locknow)
bmpdat = bmp.LockBits(rect, mode, bmp.PixelFormat); Lock(write ? ImageLockMode.ReadWrite : ImageLockMode.ReadOnly);
} }
public void Dispose() public void Dispose()
{ {
if (bmp == null) return; if (bmp == null) return;
bmp.UnlockBits(bmpdat); Unlock();
bmpdat = null;
bmp = null; bmp = null;
} }
public int Height { get { EnsureValid(); return bmpdat.Height; } } public void Lock(ImageLockMode mode)
public PixelFormat PixelFormat { get { EnsureValid(); return bmpdat.PixelFormat; } } {
public byte* Scan0 { get { EnsureValid(); return (byte*)bmpdat.Scan0.ToPointer(); } } if (bmpdat != null)
public int Stride { get { EnsureValid(); return bmpdat.Stride; } } throw new InvalidOperationException(ErrorAlreadyLocked);
public int Width { get { EnsureValid(); return bmpdat.Width; } } if (bmp == null)
throw new ObjectDisposedException(null);
var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
bmpdat = bmp.LockBits(rect, mode, bmp.PixelFormat);
}
private void EnsureValid() public void Unlock()
{
bmp.UnlockBits(bmpdat);
bmpdat = null;
}
public int Height { get { CheckLocked(); return bmpdat.Height; } }
public PixelFormat PixelFormat { get { CheckLocked(); return bmpdat.PixelFormat; } }
public byte* Scan0 { get { CheckLocked(); return (byte*)bmpdat.Scan0.ToPointer(); } }
public int Stride { get { CheckLocked(); return bmpdat.Stride; } }
public int Width { get { CheckLocked(); return bmpdat.Width; } }
private void CheckLocked()
{ {
if (bmpdat == null) if (bmpdat == null)
throw new ObjectDisposedException(null); throw new InvalidOperationException(ErrorNotLocked);
} }
} }
} }

View File

@ -37,6 +37,8 @@
<Compile Include="AdrianKousz.Util\ExtendedBinaryReader.cs" /> <Compile Include="AdrianKousz.Util\ExtendedBinaryReader.cs" />
<Compile Include="AdrianKousz.Util\ExtendedBinaryWriter.cs" /> <Compile Include="AdrianKousz.Util\ExtendedBinaryWriter.cs" />
<Compile Include="AdrianKousz.Util\UncompressedDeflateStream.cs" /> <Compile Include="AdrianKousz.Util\UncompressedDeflateStream.cs" />
<Compile Include="AdrianKousz.Util\ICommand.cs" />
<Compile Include="AdrianKousz.Util\IApp.cs" />
<Compile Include="AdrianKousz.Util\CmdApp.cs" /> <Compile Include="AdrianKousz.Util\CmdApp.cs" />
<Compile Include="AdrianKousz.Util\NonDisposingStreamWrapper.cs" /> <Compile Include="AdrianKousz.Util\NonDisposingStreamWrapper.cs" />
<Compile Include="AdrianKousz.Util\UnsafeBitmap.cs" /> <Compile Include="AdrianKousz.Util\UnsafeBitmap.cs" />