Compare commits
4 Commits
34b3ff8722
...
2643cd3509
Author | SHA1 | Date |
---|---|---|
Adrian | 2643cd3509 | |
Adrian | c7a4eb49b5 | |
Adrian | fbeb667c4d | |
Adrian | 16b864e0de |
|
@ -5,53 +5,162 @@ namespace AdrianKousz.Util
|
||||||
{
|
{
|
||||||
public class CmdApp
|
public class CmdApp
|
||||||
{
|
{
|
||||||
IApp<string, string[]> app;
|
private string header;
|
||||||
string[] args;
|
private IDictionary<string, Command> cmds;
|
||||||
|
private Command noArgCommand;
|
||||||
|
private Command defaultCommand;
|
||||||
|
|
||||||
public CmdApp(IApp<string, string[]> app, string[] args)
|
private CmdApp() { }
|
||||||
|
|
||||||
|
public void Run(string[] args)
|
||||||
{
|
{
|
||||||
this.app = app;
|
Console.WriteLine(header);
|
||||||
this.args = args;
|
Console.WriteLine();
|
||||||
}
|
|
||||||
|
|
||||||
public void Run()
|
if (args.Length == 0) {
|
||||||
{
|
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 cmd = commands[requestedcmd];
|
var cmdname = args[0];
|
||||||
var requireargcount = cmd.GetArgumentCount();
|
var cmd = GetCommand(cmdname);
|
||||||
|
|
||||||
|
if (cmd == null) {
|
||||||
|
defaultCommand.Run(new string[] { cmdname });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var requireargcount = cmd.MinArgumentCount;
|
||||||
|
|
||||||
if (args.Length - 1 < requireargcount) {
|
if (args.Length - 1 < requireargcount) {
|
||||||
Console.Out.WriteLine("Provide at least {0} arguments for \"{1}\". See help:", requireargcount, requestedcmd);
|
var hint = string.Format(SR.Error_ArgCount, cmdname, requireargcount);
|
||||||
Console.Out.WriteLine();
|
defaultCommand.Run(new string[] { cmdname, hint });
|
||||||
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.SetArguments(cmdargs);
|
cmd.Run(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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 string writing method";
|
private const string ErrorChooseMethod = "Choose method with correct integer size";
|
||||||
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,17 +20,14 @@ namespace AdrianKousz.Util
|
||||||
Strict = strict;
|
Strict = strict;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ReadString()
|
public override string ReadString() { throw new NotSupportedException(ErrorChooseMethod); }
|
||||||
{
|
public override bool ReadBoolean() { throw new NotSupportedException(ErrorChooseMethod); }
|
||||||
throw new NotSupportedException(ErrorChooseMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool ReadBoolean()
|
public bool ReadBooleanByte() { return ReadByte() != 0; }
|
||||||
{
|
public bool ReadBooleanInt16() { return ReadInt16() != 0; }
|
||||||
return ReadInt32() != 0;
|
public bool ReadBooleanInt32() { return ReadInt32() != 0; }
|
||||||
}
|
|
||||||
|
|
||||||
public string ReadStringInternal(int len) { return ReadStringInternal(len, false); }
|
public string ReadString(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); }
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace AdrianKousz.Util
|
||||||
{
|
{
|
||||||
public Encoding Encoding { get; private set; }
|
public Encoding Encoding { get; private set; }
|
||||||
|
|
||||||
private const string ErrorChooseMethod = "Choose string writing method";
|
private const string ErrorChooseMethod = "Choose method with correct integer size";
|
||||||
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,16 +17,12 @@ namespace AdrianKousz.Util
|
||||||
Encoding = enc;
|
Encoding = enc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Write(string value)
|
public override void Write(string value) { throw new NotSupportedException(ErrorChooseMethod); }
|
||||||
{
|
public override void Write(bool value) { throw new NotSupportedException(ErrorChooseMethod); }
|
||||||
throw new NotSupportedException(ErrorChooseMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Write(bool value)
|
public void WriteBooleanByte(bool value) { if (value) Write((Byte)1); else Write((Byte)0); }
|
||||||
{
|
public void WriteBooleanInt16(bool value) { if (value) Write((Int16)1); else Write((Int16)0); }
|
||||||
if (value) Write((Int32)1);
|
public void WriteBooleanInt32(bool value) { if (value) Write((Int32)1); else Write((Int32)0); }
|
||||||
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); }
|
||||||
|
@ -40,15 +36,8 @@ 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)
|
public int GetByteCount(string value) { return Encoding.GetByteCount(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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace AdrianKousz.Util
|
|
||||||
{
|
|
||||||
public interface IApp<TName, TCmd>
|
|
||||||
{
|
|
||||||
string GetHeader();
|
|
||||||
IDictionary<TName, ICommand<TCmd>> GetCommands();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace AdrianKousz.Util
|
|
||||||
{
|
|
||||||
public interface ICommand<T>
|
|
||||||
{
|
|
||||||
string GetDescription();
|
|
||||||
string GetHelp();
|
|
||||||
int GetArgumentCount();
|
|
||||||
void SetArguments(T args);
|
|
||||||
void Run();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,59 +6,38 @@ 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, true) { }
|
: this(bmp, false) { }
|
||||||
|
|
||||||
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;
|
||||||
this.bmpdat = null;
|
var mode = write ? ImageLockMode.ReadWrite : ImageLockMode.ReadOnly;
|
||||||
if (locknow)
|
var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
|
||||||
Lock(write ? ImageLockMode.ReadWrite : ImageLockMode.ReadOnly);
|
bmpdat = bmp.LockBits(rect, mode, bmp.PixelFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (bmp == null) return;
|
if (bmp == null) return;
|
||||||
Unlock();
|
bmp.UnlockBits(bmpdat);
|
||||||
|
bmpdat = null;
|
||||||
bmp = null;
|
bmp = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Lock(ImageLockMode mode)
|
public int Height { get { EnsureValid(); return bmpdat.Height; } }
|
||||||
{
|
public PixelFormat PixelFormat { get { EnsureValid(); return bmpdat.PixelFormat; } }
|
||||||
if (bmpdat != null)
|
public byte* Scan0 { get { EnsureValid(); return (byte*)bmpdat.Scan0.ToPointer(); } }
|
||||||
throw new InvalidOperationException(ErrorAlreadyLocked);
|
public int Stride { get { EnsureValid(); return bmpdat.Stride; } }
|
||||||
if (bmp == null)
|
public int Width { get { EnsureValid(); return bmpdat.Width; } }
|
||||||
throw new ObjectDisposedException(null);
|
|
||||||
var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
|
|
||||||
bmpdat = bmp.LockBits(rect, mode, bmp.PixelFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Unlock()
|
private void EnsureValid()
|
||||||
{
|
|
||||||
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 InvalidOperationException(ErrorNotLocked);
|
throw new ObjectDisposedException(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,6 @@
|
||||||
<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" />
|
||||||
|
|
Loading…
Reference in New Issue