[Tools/] Last round of untabify

This commit is contained in:
Matt Nadareski
2019-02-08 21:03:28 -08:00
parent 7c79d3ea45
commit 84f3ce4d4e
4 changed files with 636 additions and 636 deletions

View File

@@ -12,191 +12,191 @@ using Alphaleonis.Win32.Filesystem;
namespace SabreTools.Library.Tools namespace SabreTools.Library.Tools
{ {
/// <summary> /// <summary>
/// All general database operations /// All general database operations
/// </summary> /// </summary>
public static class DatabaseTools public static class DatabaseTools
{ {
/// <summary> /// <summary>
/// Add a header to the database /// Add a header to the database
/// </summary> /// </summary>
/// <param name="header">String representing the header bytes</param> /// <param name="header">String representing the header bytes</param>
/// <param name="SHA1">SHA-1 of the deheadered file</param> /// <param name="SHA1">SHA-1 of the deheadered file</param>
/// <param name="type">Name of the source skipper file</param> /// <param name="type">Name of the source skipper file</param>
public static void AddHeaderToDatabase(string header, string SHA1, string source) public static void AddHeaderToDatabase(string header, string SHA1, string source)
{ {
bool exists = false; bool exists = false;
// Ensure the database exists // Ensure the database exists
EnsureDatabase(Constants.HeadererDbSchema, Constants.HeadererFileName, Constants.HeadererConnectionString); EnsureDatabase(Constants.HeadererDbSchema, Constants.HeadererFileName, Constants.HeadererConnectionString);
// Open the database connection // Open the database connection
SqliteConnection dbc = new SqliteConnection(Constants.HeadererConnectionString); SqliteConnection dbc = new SqliteConnection(Constants.HeadererConnectionString);
dbc.Open(); dbc.Open();
string query = @"SELECT * FROM data WHERE sha1='" + SHA1 + "' AND header='" + header + "'"; string query = @"SELECT * FROM data WHERE sha1='" + SHA1 + "' AND header='" + header + "'";
SqliteCommand slc = new SqliteCommand(query, dbc); SqliteCommand slc = new SqliteCommand(query, dbc);
SqliteDataReader sldr = slc.ExecuteReader(); SqliteDataReader sldr = slc.ExecuteReader();
exists = sldr.HasRows; exists = sldr.HasRows;
if (!exists) if (!exists)
{ {
query = @"INSERT INTO data (sha1, header, type) VALUES ('" + query = @"INSERT INTO data (sha1, header, type) VALUES ('" +
SHA1 + "', " + SHA1 + "', " +
"'" + header + "', " + "'" + header + "', " +
"'" + source + "')"; "'" + source + "')";
slc = new SqliteCommand(query, dbc); slc = new SqliteCommand(query, dbc);
Globals.Logger.Verbose("Result of inserting header: {0}", slc.ExecuteNonQuery()); Globals.Logger.Verbose("Result of inserting header: {0}", slc.ExecuteNonQuery());
} }
// Dispose of database objects // Dispose of database objects
slc.Dispose(); slc.Dispose();
sldr.Dispose(); sldr.Dispose();
dbc.Dispose(); dbc.Dispose();
} }
/// <summary> /// <summary>
/// Ensure that the databse exists and has the proper schema /// Ensure that the databse exists and has the proper schema
/// </summary> /// </summary>
/// <param name="type">Schema type to use</param> /// <param name="type">Schema type to use</param>
/// <param name="db">Name of the databse</param> /// <param name="db">Name of the databse</param>
/// <param name="connectionString">Connection string for SQLite</param> /// <param name="connectionString">Connection string for SQLite</param>
public static void EnsureDatabase(string type, string db, string connectionString) public static void EnsureDatabase(string type, string db, string connectionString)
{ {
// Set the type to lowercase // Set the type to lowercase
type = type.ToLowerInvariant(); type = type.ToLowerInvariant();
// Make sure the file exists // Make sure the file exists
if (!File.Exists(db)) if (!File.Exists(db))
{ {
SqliteConnection.CreateFile(db); SqliteConnection.CreateFile(db);
} }
// Open the database connection // Open the database connection
SqliteConnection dbc = new SqliteConnection(connectionString); SqliteConnection dbc = new SqliteConnection(connectionString);
dbc.Open(); dbc.Open();
// Make sure the database has the correct schema // Make sure the database has the correct schema
try try
{ {
if (type == "rombasharp") if (type == "rombasharp")
{ {
string query = @" string query = @"
CREATE TABLE IF NOT EXISTS crc ( CREATE TABLE IF NOT EXISTS crc (
'crc' TEXT NOT NULL, 'crc' TEXT NOT NULL,
PRIMARY KEY (crc) PRIMARY KEY (crc)
)"; )";
SqliteCommand slc = new SqliteCommand(query, dbc); SqliteCommand slc = new SqliteCommand(query, dbc);
slc.ExecuteNonQuery(); slc.ExecuteNonQuery();
query = @" query = @"
CREATE TABLE IF NOT EXISTS md5 ( CREATE TABLE IF NOT EXISTS md5 (
'md5' TEXT NOT NULL, 'md5' TEXT NOT NULL,
PRIMARY KEY (md5) PRIMARY KEY (md5)
)"; )";
slc = new SqliteCommand(query, dbc); slc = new SqliteCommand(query, dbc);
slc.ExecuteNonQuery(); slc.ExecuteNonQuery();
query = @" query = @"
CREATE TABLE IF NOT EXISTS sha1 ( CREATE TABLE IF NOT EXISTS sha1 (
'sha1' TEXT NOT NULL, 'sha1' TEXT NOT NULL,
'depot' TEXT, 'depot' TEXT,
PRIMARY KEY (sha1) PRIMARY KEY (sha1)
)"; )";
slc = new SqliteCommand(query, dbc); slc = new SqliteCommand(query, dbc);
slc.ExecuteNonQuery(); slc.ExecuteNonQuery();
query = @" query = @"
CREATE TABLE IF NOT EXISTS crcsha1 ( CREATE TABLE IF NOT EXISTS crcsha1 (
'crc' TEXT NOT NULL, 'crc' TEXT NOT NULL,
'sha1' TEXT NOT NULL, 'sha1' TEXT NOT NULL,
PRIMARY KEY (crc, sha1) PRIMARY KEY (crc, sha1)
)"; )";
slc = new SqliteCommand(query, dbc); slc = new SqliteCommand(query, dbc);
slc.ExecuteNonQuery(); slc.ExecuteNonQuery();
query = @" query = @"
CREATE TABLE IF NOT EXISTS md5sha1 ( CREATE TABLE IF NOT EXISTS md5sha1 (
'md5' TEXT NOT NULL, 'md5' TEXT NOT NULL,
'sha1' TEXT NOT NULL, 'sha1' TEXT NOT NULL,
PRIMARY KEY (md5, sha1) PRIMARY KEY (md5, sha1)
)"; )";
slc = new SqliteCommand(query, dbc); slc = new SqliteCommand(query, dbc);
slc.ExecuteNonQuery(); slc.ExecuteNonQuery();
query = @" query = @"
CREATE TABLE IF NOT EXISTS dat ( CREATE TABLE IF NOT EXISTS dat (
'hash' TEXT NOT NULL, 'hash' TEXT NOT NULL,
PRIMARY KEY (hash) PRIMARY KEY (hash)
)"; )";
slc = new SqliteCommand(query, dbc); slc = new SqliteCommand(query, dbc);
slc.ExecuteNonQuery(); slc.ExecuteNonQuery();
slc.Dispose(); slc.Dispose();
} }
else if (type == "headerer") else if (type == "headerer")
{ {
string query = @" string query = @"
CREATE TABLE IF NOT EXISTS data ( CREATE TABLE IF NOT EXISTS data (
'sha1' TEXT NOT NULL, 'sha1' TEXT NOT NULL,
'header' TEXT NOT NULL, 'header' TEXT NOT NULL,
'type' TEXT NOT NULL, 'type' TEXT NOT NULL,
PRIMARY KEY (sha1, header, type) PRIMARY KEY (sha1, header, type)
)"; )";
SqliteCommand slc = new SqliteCommand(query, dbc); SqliteCommand slc = new SqliteCommand(query, dbc);
slc.ExecuteNonQuery(); slc.ExecuteNonQuery();
slc.Dispose(); slc.Dispose();
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine(ex); Console.WriteLine(ex);
} }
finally finally
{ {
dbc.Dispose(); dbc.Dispose();
} }
} }
/// <summary> /// <summary>
/// Retrieve headers from the database /// Retrieve headers from the database
/// </summary> /// </summary>
/// <param name="SHA1">SHA-1 of the deheadered file</param> /// <param name="SHA1">SHA-1 of the deheadered file</param>
/// <returns>List of strings representing the headers to add</returns> /// <returns>List of strings representing the headers to add</returns>
public static List<string> RetrieveHeadersFromDatabase(string SHA1) public static List<string> RetrieveHeadersFromDatabase(string SHA1)
{ {
// Ensure the database exists // Ensure the database exists
EnsureDatabase(Constants.HeadererDbSchema, Constants.HeadererFileName, Constants.HeadererConnectionString); EnsureDatabase(Constants.HeadererDbSchema, Constants.HeadererFileName, Constants.HeadererConnectionString);
// Open the database connection // Open the database connection
SqliteConnection dbc = new SqliteConnection(Constants.HeadererConnectionString); SqliteConnection dbc = new SqliteConnection(Constants.HeadererConnectionString);
dbc.Open(); dbc.Open();
// Create the output list of headers // Create the output list of headers
List<string> headers = new List<string>(); List<string> headers = new List<string>();
string query = @"SELECT header, type FROM data WHERE sha1='" + SHA1 + "'"; string query = @"SELECT header, type FROM data WHERE sha1='" + SHA1 + "'";
SqliteCommand slc = new SqliteCommand(query, dbc); SqliteCommand slc = new SqliteCommand(query, dbc);
SqliteDataReader sldr = slc.ExecuteReader(); SqliteDataReader sldr = slc.ExecuteReader();
if (sldr.HasRows) if (sldr.HasRows)
{ {
while (sldr.Read()) while (sldr.Read())
{ {
Globals.Logger.Verbose("Found match with rom type '{0}'", sldr.GetString(1)); Globals.Logger.Verbose("Found match with rom type '{0}'", sldr.GetString(1));
headers.Add(sldr.GetString(0)); headers.Add(sldr.GetString(0));
} }
} }
else else
{ {
Globals.Logger.Warning("No matching header could be found!"); Globals.Logger.Warning("No matching header could be found!");
} }
// Dispose of database objects // Dispose of database objects
slc.Dispose(); slc.Dispose();
sldr.Dispose(); sldr.Dispose();
dbc.Dispose(); dbc.Dispose();
return headers; return headers;
} }
} }
} }

View File

@@ -4,79 +4,79 @@ using SabreTools.Library.Data;
namespace SabreTools.Library.Tools namespace SabreTools.Library.Tools
{ {
/// <summary> /// <summary>
/// Stopwatch class for keeping track of duration in the code /// Stopwatch class for keeping track of duration in the code
/// </summary> /// </summary>
public class InternalStopwatch public class InternalStopwatch
{ {
private string _subject; private string _subject;
private DateTime _startTime; private DateTime _startTime;
/// <summary> /// <summary>
/// Constructor that initalizes the stopwatch /// Constructor that initalizes the stopwatch
/// </summary> /// </summary>
public InternalStopwatch() public InternalStopwatch()
{ {
_subject = ""; _subject = "";
} }
/// <summary> /// <summary>
/// Constructor that initalizes the stopwatch with a subject and starts immediately /// Constructor that initalizes the stopwatch with a subject and starts immediately
/// </summary> /// </summary>
/// <param name="subject">Subject of the stopwatch</param> /// <param name="subject">Subject of the stopwatch</param>
public InternalStopwatch(string subject) public InternalStopwatch(string subject)
{ {
_subject = subject; _subject = subject;
Start(); Start();
} }
/// <summary> /// <summary>
/// Constructor that initalizes the stopwatch with a subject and starts immediately /// Constructor that initalizes the stopwatch with a subject and starts immediately
/// </summary> /// </summary>
/// <param name="subject">Subject of the stopwatch</param> /// <param name="subject">Subject of the stopwatch</param>
/// <param name="more">Parameters to format the string</param> /// <param name="more">Parameters to format the string</param>
public InternalStopwatch(string subject, params object[] more) public InternalStopwatch(string subject, params object[] more)
{ {
_subject = string.Format(subject, more); _subject = string.Format(subject, more);
Start(); Start();
} }
/// <summary> /// <summary>
/// Start the stopwatch and display subject text /// Start the stopwatch and display subject text
/// </summary> /// </summary>
public void Start() public void Start()
{ {
_startTime = DateTime.Now; _startTime = DateTime.Now;
Globals.Logger.User("{0}...", _subject); Globals.Logger.User("{0}...", _subject);
} }
/// <summary> /// <summary>
/// Start the stopwatch and display subject text /// Start the stopwatch and display subject text
/// </summary> /// </summary>
/// <param name="subject">Text to show on stopwatch start</param> /// <param name="subject">Text to show on stopwatch start</param>
public void Start(string subject) public void Start(string subject)
{ {
_subject = subject; _subject = subject;
Start(); Start();
} }
/// <summary> /// <summary>
/// Start the stopwatch and display subject text /// Start the stopwatch and display subject text
/// </summary> /// </summary>
/// <param name="subject">Text to show on stopwatch start</param> /// <param name="subject">Text to show on stopwatch start</param>
/// <param name="more">Parameters to format the string</param> /// <param name="more">Parameters to format the string</param>
public void Start(string subject, params object[] more) public void Start(string subject, params object[] more)
{ {
_subject = string.Format(subject, more); _subject = string.Format(subject, more);
Start(); Start();
} }
/// <summary> /// <summary>
/// End the stopwatch and display subject text /// End the stopwatch and display subject text
/// </summary> /// </summary>
public void Stop() public void Stop()
{ {
Globals.Logger.User("{0} completed in {1}", _subject, DateTime.Now.Subtract(_startTime).ToString(@"hh\:mm\:ss\.fffff")); Globals.Logger.User("{0} completed in {1}", _subject, DateTime.Now.Subtract(_startTime).ToString(@"hh\:mm\:ss\.fffff"));
} }
} }
} }

View File

@@ -15,348 +15,348 @@ using StreamWriter = System.IO.StreamWriter;
namespace SabreTools.Library.Tools namespace SabreTools.Library.Tools
{ {
/// <summary> /// <summary>
/// Log either to file or to the console /// Log either to file or to the console
/// </summary> /// </summary>
public class Logger public class Logger
{ {
// Private instance variables // Private instance variables
private bool _tofile; private bool _tofile;
private bool _warnings; private bool _warnings;
private bool _errors; private bool _errors;
private string _filename; private string _filename;
private LogLevel _filter; private LogLevel _filter;
private DateTime _start; private DateTime _start;
private StreamWriter _log; private StreamWriter _log;
private object _lock = new object(); // This is used during multithreaded logging private object _lock = new object(); // This is used during multithreaded logging
// Private required variables // Private required variables
private string _basepath = Path.Combine(Globals.ExeDir, "logs") + Path.DirectorySeparatorChar; private string _basepath = Path.Combine(Globals.ExeDir, "logs") + Path.DirectorySeparatorChar;
/// <summary> /// <summary>
/// Initialize a console-only logger object /// Initialize a console-only logger object
/// </summary> /// </summary>
public Logger() public Logger()
{ {
_tofile = false; _tofile = false;
_warnings = false; _warnings = false;
_errors = false; _errors = false;
_filename = null; _filename = null;
_filter = LogLevel.VERBOSE; _filter = LogLevel.VERBOSE;
Start(); Start();
} }
/// <summary> /// <summary>
/// Initialize a Logger object with the given information /// Initialize a Logger object with the given information
/// </summary> /// </summary>
/// <param name="tofile">True if file should be written to instead of console</param> /// <param name="tofile">True if file should be written to instead of console</param>
/// <param name="filename">Filename representing log location</param> /// <param name="filename">Filename representing log location</param>
/// <param name="filter">Highest filtering level to be kept, default VERBOSE</param> /// <param name="filter">Highest filtering level to be kept, default VERBOSE</param>
public Logger(bool tofile, string filename, LogLevel filter = LogLevel.VERBOSE) public Logger(bool tofile, string filename, LogLevel filter = LogLevel.VERBOSE)
{ {
_tofile = tofile; _tofile = tofile;
_warnings = false; _warnings = false;
_errors = false; _errors = false;
_filename = Path.GetFileNameWithoutExtension(filename) + " (" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ")." + Utilities.GetExtension(filename); _filename = Path.GetFileNameWithoutExtension(filename) + " (" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ")." + Utilities.GetExtension(filename);
_filter = filter; _filter = filter;
if (!Directory.Exists(_basepath)) if (!Directory.Exists(_basepath))
{ {
Directory.CreateDirectory(_basepath); Directory.CreateDirectory(_basepath);
} }
Start(); Start();
} }
/// <summary> /// <summary>
/// Start logging by opening output file (if necessary) /// Start logging by opening output file (if necessary)
/// </summary> /// </summary>
/// <returns>True if the logging was started correctly, false otherwise</returns> /// <returns>True if the logging was started correctly, false otherwise</returns>
public bool Start() public bool Start()
{ {
_start = DateTime.Now; _start = DateTime.Now;
if (!_tofile) if (!_tofile)
{ {
return true; return true;
} }
try try
{ {
FileStream logfile = Utilities.TryCreate(Path.Combine(_basepath, _filename)); FileStream logfile = Utilities.TryCreate(Path.Combine(_basepath, _filename));
_log = new StreamWriter(logfile, Encoding.UTF8, (int)(4 * Constants.KibiByte), true); _log = new StreamWriter(logfile, Encoding.UTF8, (int)(4 * Constants.KibiByte), true);
_log.AutoFlush = true; _log.AutoFlush = true;
_log.WriteLine("Logging started " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); _log.WriteLine("Logging started " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
_log.WriteLine(string.Format("Command run: {0}", Globals.CommandLineArgs)); _log.WriteLine(string.Format("Command run: {0}", Globals.CommandLineArgs));
} }
catch catch
{ {
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// End logging by closing output file (if necessary) /// End logging by closing output file (if necessary)
/// </summary> /// </summary>
/// <param name="suppress">True if all ending output is to be suppressed, false otherwise (default)</param> /// <param name="suppress">True if all ending output is to be suppressed, false otherwise (default)</param>
/// <returns>True if the logging was ended correctly, false otherwise</returns> /// <returns>True if the logging was ended correctly, false otherwise</returns>
public bool Close(bool suppress = false) public bool Close(bool suppress = false)
{ {
if (!suppress) if (!suppress)
{ {
if (_warnings) if (_warnings)
{ {
Console.WriteLine("There were warnings in the last run! Check the log for more details"); Console.WriteLine("There were warnings in the last run! Check the log for more details");
} }
if (_errors) if (_errors)
{ {
Console.WriteLine("There were errors in the last run! Check the log for more details"); Console.WriteLine("There were errors in the last run! Check the log for more details");
} }
TimeSpan span = DateTime.Now.Subtract(_start); TimeSpan span = DateTime.Now.Subtract(_start);
// Special case for multi-day runs // Special case for multi-day runs
string total = ""; string total = "";
if (span >= TimeSpan.FromDays(1)) if (span >= TimeSpan.FromDays(1))
{ {
total = span.ToString(@"d\:hh\:mm\:ss"); total = span.ToString(@"d\:hh\:mm\:ss");
} }
else else
{ {
total = span.ToString(@"hh\:mm\:ss"); total = span.ToString(@"hh\:mm\:ss");
} }
if (!_tofile) if (!_tofile)
{ {
Console.WriteLine("Total runtime: " + total); Console.WriteLine("Total runtime: " + total);
return true; return true;
} }
try try
{ {
_log.WriteLine("Logging ended " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); _log.WriteLine("Logging ended " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
_log.WriteLine("Total runtime: " + total); _log.WriteLine("Total runtime: " + total);
Console.WriteLine("Total runtime: " + total); Console.WriteLine("Total runtime: " + total);
_log.Close(); _log.Close();
} }
catch catch
{ {
return false; return false;
} }
} }
else else
{ {
try try
{ {
_log.Close(); _log.Close();
} }
catch catch
{ {
return false; return false;
} }
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write the given string to the log output /// Write the given string to the log output
/// </summary> /// </summary>
/// <param name="output">String to be written log</param> /// <param name="output">String to be written log</param>
/// <param name="loglevel">Severity of the information being logged</param> /// <param name="loglevel">Severity of the information being logged</param>
/// <param name="appendPrefix">True if the level and datetime should be prepended to each statement, false otherwise</param> /// <param name="appendPrefix">True if the level and datetime should be prepended to each statement, false otherwise</param>
/// <returns>True if the output could be written, false otherwise</returns> /// <returns>True if the output could be written, false otherwise</returns>
private bool Log(string output, LogLevel loglevel, bool appendPrefix) private bool Log(string output, LogLevel loglevel, bool appendPrefix)
{ {
// If the log level is less than the filter level, we skip it but claim we didn't // If the log level is less than the filter level, we skip it but claim we didn't
if (loglevel < _filter) if (loglevel < _filter)
{ {
return true; return true;
} }
// USER and ERROR writes to console // USER and ERROR writes to console
if (loglevel == LogLevel.USER || loglevel == LogLevel.ERROR) if (loglevel == LogLevel.USER || loglevel == LogLevel.ERROR)
{ {
Console.WriteLine((loglevel == LogLevel.ERROR && appendPrefix ? loglevel.ToString() + " " : "") + output); Console.WriteLine((loglevel == LogLevel.ERROR && appendPrefix ? loglevel.ToString() + " " : "") + output);
} }
// If we're writing to file, use the existing stream // If we're writing to file, use the existing stream
if (_tofile) if (_tofile)
{ {
try try
{ {
lock(_lock) lock(_lock)
{ {
_log.WriteLine((appendPrefix ? loglevel.ToString() + " - " + DateTime.Now + " - " : "") + output); _log.WriteLine((appendPrefix ? loglevel.ToString() + " - " + DateTime.Now + " - " : "") + output);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine(ex); Console.WriteLine(ex);
Console.WriteLine("Could not write to log file!"); Console.WriteLine("Could not write to log file!");
return false; return false;
} }
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write the given exact string to the log output /// Write the given exact string to the log output
/// </summary> /// </summary>
/// <param name="output">String to be written log</param> /// <param name="output">String to be written log</param>
/// <param name="line">Line number to write out to</param> /// <param name="line">Line number to write out to</param>
/// <param name="column">Column number to write out to</param> /// <param name="column">Column number to write out to</param>
/// <returns>True if the output could be written, false otherwise</returns> /// <returns>True if the output could be written, false otherwise</returns>
public bool WriteExact(string output, int line, int column) public bool WriteExact(string output, int line, int column)
{ {
// Set the cursor position (if not being redirected) // Set the cursor position (if not being redirected)
if (!Console.IsOutputRedirected) if (!Console.IsOutputRedirected)
{ {
Console.CursorTop = line; Console.CursorTop = line;
Console.CursorLeft = column; Console.CursorLeft = column;
} }
// Write out to the console // Write out to the console
Console.Write(output); Console.Write(output);
// If we're writing to file, use the existing stream // If we're writing to file, use the existing stream
if (_tofile) if (_tofile)
{ {
try try
{ {
lock (_lock) lock (_lock)
{ {
_log.Write(DateTime.Now + " - " + output); _log.Write(DateTime.Now + " - " + output);
} }
} }
catch catch
{ {
Console.WriteLine("Could not write to log file!"); Console.WriteLine("Could not write to log file!");
return false; return false;
} }
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write the given string as a verbose message to the log output /// Write the given string as a verbose message to the log output
/// </summary> /// </summary>
/// <param name="output">String to be written log</param> /// <param name="output">String to be written log</param>
/// <param name="args">Optional arguments for string formatting</param> /// <param name="args">Optional arguments for string formatting</param>
/// <returns>True if the output could be written, false otherwise</returns>s /// <returns>True if the output could be written, false otherwise</returns>s
public bool Verbose(string output, params object[] args) public bool Verbose(string output, params object[] args)
{ {
return Log(args.Length == 0 ? output: string.Format(output, args), LogLevel.VERBOSE, true); return Log(args.Length == 0 ? output: string.Format(output, args), LogLevel.VERBOSE, true);
} }
/// <summary> /// <summary>
/// Write the given string as a verbose message to the log output /// Write the given string as a verbose message to the log output
/// </summary> /// </summary>
/// <param name="output">String to be written log</param> /// <param name="output">String to be written log</param>
/// <param name="appendPrefix">True if the level and datetime should be prepended to each statement (default), false otherwise</param> /// <param name="appendPrefix">True if the level and datetime should be prepended to each statement (default), false otherwise</param>
/// <param name="args">Optional arguments for string formatting</param> /// <param name="args">Optional arguments for string formatting</param>
/// <returns>True if the output could be written, false otherwise</returns> /// <returns>True if the output could be written, false otherwise</returns>
public bool Verbose(string output, bool appendPrefix = true, params object[] args) public bool Verbose(string output, bool appendPrefix = true, params object[] args)
{ {
return Log(args.Length == 0 ? output : string.Format(output, args), LogLevel.VERBOSE, appendPrefix); return Log(args.Length == 0 ? output : string.Format(output, args), LogLevel.VERBOSE, appendPrefix);
} }
/// <summary> /// <summary>
/// Write the given string as a user message to the log output /// Write the given string as a user message to the log output
/// </summary> /// </summary>
/// <param name="output">String to be written log</param> /// <param name="output">String to be written log</param>
/// <param name="args">Optional arguments for string formatting</param> /// <param name="args">Optional arguments for string formatting</param>
/// <returns>True if the output could be written, false otherwise</returns> /// <returns>True if the output could be written, false otherwise</returns>
public bool User(string output, params object[] args) public bool User(string output, params object[] args)
{ {
return Log(args.Length == 0 ? output : string.Format(output, args), LogLevel.USER, true); return Log(args.Length == 0 ? output : string.Format(output, args), LogLevel.USER, true);
} }
/// <summary> /// <summary>
/// Write the given string as a user message to the log output /// Write the given string as a user message to the log output
/// </summary> /// </summary>
/// <param name="output">String to be written log</param> /// <param name="output">String to be written log</param>
/// <param name="appendPrefix">True if the level and datetime should be prepended to each statement (default), false otherwise</param> /// <param name="appendPrefix">True if the level and datetime should be prepended to each statement (default), false otherwise</param>
/// <param name="args">Optional arguments for string formatting</param> /// <param name="args">Optional arguments for string formatting</param>
/// <returns>True if the output could be written, false otherwise</returns> /// <returns>True if the output could be written, false otherwise</returns>
public bool User(string output, bool appendPrefix = true, params object[] args) public bool User(string output, bool appendPrefix = true, params object[] args)
{ {
return Log(args.Length == 0 ? output : string.Format(output, args), LogLevel.USER, appendPrefix); return Log(args.Length == 0 ? output : string.Format(output, args), LogLevel.USER, appendPrefix);
} }
/// <summary> /// <summary>
/// Write the given string as a warning to the log output /// Write the given string as a warning to the log output
/// </summary> /// </summary>
/// <param name="output">String to be written log</param> /// <param name="output">String to be written log</param>
/// <param name="args">Optional arguments for string formatting</param> /// <param name="args">Optional arguments for string formatting</param>
/// <returns>True if the output could be written, false otherwise</returns> /// <returns>True if the output could be written, false otherwise</returns>
public bool Warning(string output, params object[] args) public bool Warning(string output, params object[] args)
{ {
_warnings = true; _warnings = true;
return Log(args.Length == 0 ? output : string.Format(output, args), LogLevel.WARNING, true); return Log(args.Length == 0 ? output : string.Format(output, args), LogLevel.WARNING, true);
} }
/// <summary> /// <summary>
/// Write the given string as a warning to the log output /// Write the given string as a warning to the log output
/// </summary> /// </summary>
/// <param name="output">String to be written log</param> /// <param name="output">String to be written log</param>
/// <param name="appendPrefix">True if the level and datetime should be prepended to each statement (default), false otherwise</param> /// <param name="appendPrefix">True if the level and datetime should be prepended to each statement (default), false otherwise</param>
/// <param name="args">Optional arguments for string formatting</param> /// <param name="args">Optional arguments for string formatting</param>
/// <returns>True if the output could be written, false otherwise</returns> /// <returns>True if the output could be written, false otherwise</returns>
public bool Warning(string output, bool appendPrefix = true, params object[] args) public bool Warning(string output, bool appendPrefix = true, params object[] args)
{ {
_warnings = true; _warnings = true;
return Log(args.Length == 0 ? output : string.Format(output, args), LogLevel.WARNING, appendPrefix); return Log(args.Length == 0 ? output : string.Format(output, args), LogLevel.WARNING, appendPrefix);
} }
/// <summary> /// <summary>
/// Writes the given string as an error in the log /// Writes the given string as an error in the log
/// </summary> /// </summary>
/// <param name="output">String to be written log</param> /// <param name="output">String to be written log</param>
/// <param name="args">Optional arguments for string formatting</param> /// <param name="args">Optional arguments for string formatting</param>
/// <returns>True if the output could be written, false otherwise</returns> /// <returns>True if the output could be written, false otherwise</returns>
public bool Error(string output, params object[] args) public bool Error(string output, params object[] args)
{ {
_errors = true; _errors = true;
return Log(args.Length == 0 ? output : string.Format(output, args), LogLevel.ERROR, true); return Log(args.Length == 0 ? output : string.Format(output, args), LogLevel.ERROR, true);
} }
/// <summary> /// <summary>
/// Writes the given string as an error in the log /// Writes the given string as an error in the log
/// </summary> /// </summary>
/// <param name="output">String to be written log</param> /// <param name="output">String to be written log</param>
/// <param name="appendPrefix">True if the level and datetime should be prepended to each statement (default), false otherwise</param> /// <param name="appendPrefix">True if the level and datetime should be prepended to each statement (default), false otherwise</param>
/// <param name="args">Optional arguments for string formatting</param> /// <param name="args">Optional arguments for string formatting</param>
/// <returns>True if the output could be written, false otherwise</returns> /// <returns>True if the output could be written, false otherwise</returns>
public bool Error(string output, bool appendPrefix = true, params object[] args) public bool Error(string output, bool appendPrefix = true, params object[] args)
{ {
_errors = true; _errors = true;
return Log(args.Length == 0 ? output : string.Format(output, args), LogLevel.ERROR, appendPrefix); return Log(args.Length == 0 ? output : string.Format(output, args), LogLevel.ERROR, appendPrefix);
} }
/// <summary> /// <summary>
/// Clear lines beneath the given line in the console /// Clear lines beneath the given line in the console
/// </summary> /// </summary>
/// <param name="line">Line number to clear beneath</param> /// <param name="line">Line number to clear beneath</param>
/// <returns>True</returns> /// <returns>True</returns>
public bool ClearBeneath(int line) public bool ClearBeneath(int line)
{ {
if (!Console.IsOutputRedirected) if (!Console.IsOutputRedirected)
{ {
for (int i = line; i < Console.WindowHeight; i++) for (int i = line; i < Console.WindowHeight; i++)
{ {
// http://stackoverflow.com/questions/8946808/can-console-clear-be-used-to-only-clear-a-line-instead-of-whole-console // http://stackoverflow.com/questions/8946808/can-console-clear-be-used-to-only-clear-a-line-instead-of-whole-console
Console.SetCursorPosition(0, Console.CursorTop); Console.SetCursorPosition(0, Console.CursorTop);
Console.Write(new string(' ', Console.WindowWidth)); Console.Write(new string(' ', Console.WindowWidth));
Console.SetCursorPosition(0, i); Console.SetCursorPosition(0, i);
} }
} }
return true; return true;
} }
} }
} }

View File

@@ -26,128 +26,128 @@ using System;
namespace SabreTools.Library.Tools namespace SabreTools.Library.Tools
{ {
public class OptimizedCRC : IDisposable public class OptimizedCRC : IDisposable
{ {
private const uint kCrcPoly = 0xEDB88320; private const uint kCrcPoly = 0xEDB88320;
private const uint kInitial = 0xFFFFFFFF; private const uint kInitial = 0xFFFFFFFF;
private const int CRC_NUM_TABLES = 8; private const int CRC_NUM_TABLES = 8;
private static readonly uint[] Table; private static readonly uint[] Table;
static OptimizedCRC() static OptimizedCRC()
{ {
unchecked unchecked
{ {
Table = new uint[256 * CRC_NUM_TABLES]; Table = new uint[256 * CRC_NUM_TABLES];
int i; int i;
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
uint r = (uint)i; uint r = (uint)i;
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
{ {
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
} }
Table[i] = r; Table[i] = r;
} }
for (; i < 256 * CRC_NUM_TABLES; i++) for (; i < 256 * CRC_NUM_TABLES; i++)
{ {
uint r = Table[i - 256]; uint r = Table[i - 256];
Table[i] = Table[r & 0xFF] ^ (r >> 8); Table[i] = Table[r & 0xFF] ^ (r >> 8);
} }
} }
} }
public uint UnsignedValue; public uint UnsignedValue;
public OptimizedCRC() public OptimizedCRC()
{ {
Init(); Init();
} }
/// <summary> /// <summary>
/// Reset CRC /// Reset CRC
/// </summary> /// </summary>
public void Init() public void Init()
{ {
UnsignedValue = kInitial; UnsignedValue = kInitial;
} }
public int Value public int Value
{ {
get { return (int)~UnsignedValue; } get { return (int)~UnsignedValue; }
} }
public void Update(byte[] data, int offset, int count) public void Update(byte[] data, int offset, int count)
{ {
new ArraySegment<byte>(data, offset, count); // check arguments new ArraySegment<byte>(data, offset, count); // check arguments
if (count == 0) if (count == 0)
{ {
return; return;
} }
var table = OptimizedCRC.Table; var table = OptimizedCRC.Table;
uint crc = UnsignedValue; uint crc = UnsignedValue;
for (; (offset & 7) != 0 && count != 0; count--) for (; (offset & 7) != 0 && count != 0; count--)
{ {
crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]]; crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]];
} }
if (count >= 8) if (count >= 8)
{ {
/* /*
* Idea from 7-zip project sources (http://7-zip.org/sdk.html) * Idea from 7-zip project sources (http://7-zip.org/sdk.html)
*/ */
int end = (count - 8) & ~7; int end = (count - 8) & ~7;
count -= end; count -= end;
end += offset; end += offset;
while (offset != end) while (offset != end)
{ {
crc ^= (uint)(data[offset] + (data[offset + 1] << 8) + (data[offset + 2] << 16) + (data[offset + 3] << 24)); crc ^= (uint)(data[offset] + (data[offset + 1] << 8) + (data[offset + 2] << 16) + (data[offset + 3] << 24));
uint high = (uint)(data[offset + 4] + (data[offset + 5] << 8) + (data[offset + 6] << 16) + (data[offset + 7] << 24)); uint high = (uint)(data[offset + 4] + (data[offset + 5] << 8) + (data[offset + 6] << 16) + (data[offset + 7] << 24));
offset += 8; offset += 8;
crc = table[(byte)crc + 0x700] crc = table[(byte)crc + 0x700]
^ table[(byte)(crc >>= 8) + 0x600] ^ table[(byte)(crc >>= 8) + 0x600]
^ table[(byte)(crc >>= 8) + 0x500] ^ table[(byte)(crc >>= 8) + 0x500]
^ table[/*(byte)*/(crc >> 8) + 0x400] ^ table[/*(byte)*/(crc >> 8) + 0x400]
^ table[(byte)(high) + 0x300] ^ table[(byte)(high) + 0x300]
^ table[(byte)(high >>= 8) + 0x200] ^ table[(byte)(high >>= 8) + 0x200]
^ table[(byte)(high >>= 8) + 0x100] ^ table[(byte)(high >>= 8) + 0x100]
^ table[/*(byte)*/(high >> 8) + 0x000]; ^ table[/*(byte)*/(high >> 8) + 0x000];
} }
} }
while (count-- != 0) while (count-- != 0)
{ {
crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]]; crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]];
} }
UnsignedValue = crc; UnsignedValue = crc;
} }
static public int Compute(byte[] data, int offset, int count) static public int Compute(byte[] data, int offset, int count)
{ {
var crc = new OptimizedCRC(); var crc = new OptimizedCRC();
crc.Update(data, offset, count); crc.Update(data, offset, count);
return crc.Value; return crc.Value;
} }
static public int Compute(byte[] data) static public int Compute(byte[] data)
{ {
return Compute(data, 0, data.Length); return Compute(data, 0, data.Length);
} }
static public int Compute(ArraySegment<byte> block) static public int Compute(ArraySegment<byte> block)
{ {
return Compute(block.Array, block.Offset, block.Count); return Compute(block.Array, block.Offset, block.Count);
} }
public void Dispose() public void Dispose()
{ {
UnsignedValue = 0; UnsignedValue = 0;
} }
} }
} }