Compare commits

...

4 Commits

Author SHA1 Message Date
Adrian 2643cd3509 Simplify UnsafeBitmap and always lock it 2016-04-26 00:39:50 +02:00
Adrian c7a4eb49b5 Add boolean size in binary reader/writer 2016-04-25 16:54:33 +02:00
Adrian fbeb667c4d Small fix in ExtendedBinaryReader 2016-04-23 02:15:35 +02:00
Adrian 16b864e0de Rewrite CmdApp 2016-04-22 18:46:48 +02:00
7 changed files with 171 additions and 122 deletions

View File

@ -5,53 +5,162 @@ namespace AdrianKousz.Util
{
public class CmdApp
{
IApp<string, string[]> app;
string[] args;
private string header;
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;
this.args = args;
}
Console.WriteLine(header);
Console.WriteLine();
public void Run()
{
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();
if (args.Length == 0) {
noArgCommand.Run(new string[0]);
return;
}
var cmd = commands[requestedcmd];
var requireargcount = cmd.GetArgumentCount();
var cmdname = args[0];
var cmd = GetCommand(cmdname);
if (cmd == null) {
defaultCommand.Run(new string[] { cmdname });
return;
}
var requireargcount = cmd.MinArgumentCount;
if (args.Length - 1 < requireargcount) {
Console.Out.WriteLine("Provide at least {0} arguments for \"{1}\". See help:", requireargcount, requestedcmd);
Console.Out.WriteLine();
Console.Out.WriteLine(cmd.GetHelp());
Console.Out.WriteLine();
var hint = string.Format(SR.Error_ArgCount, cmdname, requireargcount);
defaultCommand.Run(new string[] { cmdname, hint });
return;
}
var cmdargs = new string[args.Length - 1];
Array.Copy(args, 1, cmdargs, 0, cmdargs.Length);
cmd.SetArguments(cmdargs);
cmd.Run();
cmd.Run(cmdargs);
}
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 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 ErrorHasNoNull = "String does not contain trailing null";
@ -20,17 +20,14 @@ namespace AdrianKousz.Util
Strict = strict;
}
public override string ReadString()
{
throw new NotSupportedException(ErrorChooseMethod);
}
public override string ReadString() { throw new NotSupportedException(ErrorChooseMethod); }
public override bool ReadBoolean() { throw new NotSupportedException(ErrorChooseMethod); }
public override bool ReadBoolean()
{
return ReadInt32() != 0;
}
public bool ReadBooleanByte() { return ReadByte() != 0; }
public bool ReadBooleanInt16() { return ReadInt16() != 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 ReadStringInt16() { return ReadStringInternal(ReadInt16(), false); }
public string ReadStringInt32() { return ReadStringInternal(ReadInt32(), false); }

View File

@ -8,7 +8,7 @@ namespace AdrianKousz.Util
{
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";
public ExtendedBinaryWriter(Stream stream, Encoding enc)
@ -17,16 +17,12 @@ namespace AdrianKousz.Util
Encoding = enc;
}
public override void Write(string value)
{
throw new NotSupportedException(ErrorChooseMethod);
}
public override void Write(string value) { throw new NotSupportedException(ErrorChooseMethod); }
public override void Write(bool value) { throw new NotSupportedException(ErrorChooseMethod); }
public override void Write(bool value)
{
if (value) Write((Int32)1);
else Write((Int32)0);
}
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); }
public void WriteBooleanInt32(bool value) { if (value) Write((Int32)1); else Write((Int32)0); }
public void WriteString(string value, int len) { WriteStringInternal(value, len, TypeCode.Empty); }
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 WriteZStringRaw(string value) { WriteStringInternal(value + "\0", 0, TypeCode.Empty); }
public int GetByteCount(string value)
{
return Encoding.GetByteCount(value);
}
public int GetZByteCount(string value)
{
return Encoding.GetByteCount(value + "\0");
}
public int GetByteCount(string value) { return Encoding.GetByteCount(value); }
public int GetZByteCount(string value) { return Encoding.GetByteCount(value + "\0"); }
private void WriteStringInternal(string value, int len, TypeCode typecode)
{

View File

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

View File

@ -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();
}
}

View File

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

View File

@ -37,8 +37,6 @@
<Compile Include="AdrianKousz.Util\ExtendedBinaryReader.cs" />
<Compile Include="AdrianKousz.Util\ExtendedBinaryWriter.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\NonDisposingStreamWrapper.cs" />
<Compile Include="AdrianKousz.Util\UnsafeBitmap.cs" />