diff --git a/BeefSpace.toml b/BeefSpace.toml index 835301a..4246be3 100644 --- a/BeefSpace.toml +++ b/BeefSpace.toml @@ -1,11 +1,5 @@ FileVersion = 1 -Projects = {Sandbox = {Path = "Sandbox"}, GlitchyEngine = {Path = "GlitchyEngine"}} +Projects = {Sandbox = {Path = "Sandbox"}, GlitchyEngine = {Path = "GlitchyEngine"}, GlitchLog = {Path = "GlitchLog"}} [Workspace] StartupProject = "Sandbox" - -[Configs.Test.Win32] -ConfigSelections = {corlib = {Config = "Debug"}} - -[Configs.Test.Win64] -ConfigSelections = {corlib = {Config = "Debug"}} diff --git a/GlitchLog/BeefProj.toml b/GlitchLog/BeefProj.toml new file mode 100644 index 0000000..cbe34f5 --- /dev/null +++ b/GlitchLog/BeefProj.toml @@ -0,0 +1,4 @@ +FileVersion = 1 + +[Project] +Name = "GlitchLog" diff --git a/GlitchLog/src/DebugLogger.bf b/GlitchLog/src/DebugLogger.bf new file mode 100644 index 0000000..433a760 --- /dev/null +++ b/GlitchLog/src/DebugLogger.bf @@ -0,0 +1,123 @@ +using System; +using System.Diagnostics; + +using internal GlitchLog; + +namespace GlitchLog +{ + public abstract class Logger + { + protected LogLevel _logLevel; + + public LogLevel Level + { + get => _logLevel; + set => _logLevel = value; + } + + public abstract String Name {get; set;} + + public abstract void Trace(StringView format, params Object[] args); + public abstract void Info(StringView format, params Object[] args); + public abstract void Warning(StringView format, params Object[] args); + public abstract void Error(StringView format, params Object[] args); + public abstract void Critical(StringView format, params Object[] args); + + public abstract void Log(LogLevel level, StringView format, params Object[] args); + } + + public class DebugLogger : Logger + { + // {l} = log level (first parameter) + // {t} = current date time (second parameter) + // {n} = logger name (third parameter) + // {m} = message + + private String _name; + + public override String Name + { + get => _name; + set => _name = value; + } + + public this() + { + Runtime.Assert(Debug.IsDebuggerPresent, "The DebugLogger requires a debugger to be present."); + } + + +#if GL_NOLOG || GL_NOTRACE + [SkipCall] +#endif + [Inline] + public override void Trace(StringView format, params Object[] args) + { + InternalLog(.Trace, format, params args); + } + +#if GL_NOLOG || GL_NOINFO + [SkipCall] +#endif + [Inline] + public override void Info(StringView format, params Object[] args) + { + InternalLog(.Info, format, params args); + } + +#if GL_NOLOG || GL_NOWARNING + [SkipCall] +#endif + [Inline] + public override void Warning(StringView format, params Object[] args) + { + InternalLog(.Warning, format, params args); + } + +#if GL_NOLOG || GL_NOERROR + [SkipCall] +#endif + [Inline] + public override void Error(StringView format, params Object[] args) + { + InternalLog(.Error, format, params args); + } + +#if GL_NOLOG || GL_NOCRITICAL + [SkipCall] +#endif + [Inline] + public override void Critical(StringView format, params Object[] args) + { + InternalLog(.Critical, format, params args); + } + +#if GL_NOLOG + [SkipCall] +#endif + [Inline] + public override void Log(LogLevel level, StringView format, params Object[] args) + { + InternalLog(level, format, params args); + } + + private void InternalLog(LogLevel level, StringView format, params Object[] args) + { + if(_logLevel > level) + return; + + String msg = scope String(4096); + if(GlitchLog._preMsgFormat.Ptr != null) + msg.AppendF(GlitchLog._preMsgFormat, level.UpperString, DateTime.Now, _name); + + msg.AppendF(format, params args); + + if(GlitchLog._postMsgFormat.Ptr != null) + msg.AppendF(GlitchLog._postMsgFormat, level.UpperString, DateTime.Now, _name); + + msg.Append('\n'); + + Debug.[Friend]Write(msg.Ptr, msg.Length); + } + } +} diff --git a/GlitchLog/src/FileLogger.bf b/GlitchLog/src/FileLogger.bf new file mode 100644 index 0000000..c76fd40 --- /dev/null +++ b/GlitchLog/src/FileLogger.bf @@ -0,0 +1,43 @@ +using System; +using System.IO; +using System.Text; + +namespace GlitchLog +{ + public class FileLogger : ILogger + { + StreamWriter _sw ~ delete _; + + [AllowAppend] + public this(String fileName) + { + var sw = append StreamWriter(); + _sw = sw; + _sw.Create(fileName); + } + + public void Trace(StringView format, params Object[] args) + { + _sw.Write("TRACE: "); + _sw.WriteLine(format, params args); + } + + public void Info(StringView format, params Object[] args) + { + _sw.Write("INFO: "); + _sw.WriteLine(format, params args); + } + + public void Warning(StringView format, params Object[] args) + { + _sw.Write("WARNING: "); + _sw.WriteLine(format, params args); + } + + public void Error(StringView format, params Object[] args) + { + _sw.Write("ERROR: "); + _sw.WriteLine(format, params args); + } + } +} diff --git a/GlitchLog/src/GlitchLog.bf b/GlitchLog/src/GlitchLog.bf new file mode 100644 index 0000000..1eee6c0 --- /dev/null +++ b/GlitchLog/src/GlitchLog.bf @@ -0,0 +1,65 @@ +using System; +using System.Text; +using System.Diagnostics; + +namespace GlitchLog +{ + public static class GlitchLog + { + private static String _format; + internal static String _preparedFormat ~ delete _; + internal static StringView _preMsgFormat; + internal static StringView _postMsgFormat; + + public static String Format + { + get => _format; + set + { + _format = value; + + PrepareFormat(); + } + } + + static void PrepareFormat() + { + delete _preparedFormat; + + // Length = 0 -> no format -> only print msg + if(_format.Length == 0) + { + _preMsgFormat.Ptr = null; + _postMsgFormat.Ptr = null; + } + + _preparedFormat = new .(_format); + + // Todo: this is utter garbage + _preparedFormat.Replace("{l", "{0"); + _preparedFormat.Replace("{t", "{1"); + _preparedFormat.Replace("{n", "{2"); + + int index = _preparedFormat.IndexOf("{m}"); + + // {m} not in format-string -> format is pre msg + if(index == -1) + { + _preMsgFormat = _preparedFormat; + _postMsgFormat.Ptr = null; + } + else + { + if(index == 0) + _preMsgFormat.Ptr = null; + else + _preMsgFormat = .(_preparedFormat, 0, index); + + if(index == _preparedFormat.Length - 3) + _postMsgFormat.Ptr = null; + else + _postMsgFormat = .(_preparedFormat, index + 3, _preparedFormat.Length - index - 3); + } + } + } +} diff --git a/GlitchLog/src/ILogger.bf b/GlitchLog/src/ILogger.bf new file mode 100644 index 0000000..5fa0ccd --- /dev/null +++ b/GlitchLog/src/ILogger.bf @@ -0,0 +1,12 @@ +using System; + +namespace GlitchLog +{ + public interface ILogger + { + void Trace(StringView format, params Object[] args); + void Info(StringView format, params Object[] args); + void Warning(StringView format, params Object[] args); + void Error(StringView format, params Object[] args); + } +} diff --git a/GlitchLog/src/LogLevel.bf b/GlitchLog/src/LogLevel.bf new file mode 100644 index 0000000..309f7ae --- /dev/null +++ b/GlitchLog/src/LogLevel.bf @@ -0,0 +1,24 @@ +using System; + +namespace GlitchLog +{ + /** + * Defines the severity level of a log message. + * @remarks also used to determine which levels will be logged. + */ + public enum LogLevel + { + case Trace = 0; + case Debug; + case Info; + case Warning; + case Error; + case Critical; + case Off; + + public static readonly StringView[?] UpperStringViews = .("TRACE", "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "OFF"); + + [Inline] + public StringView UpperString => UpperStringViews[this.Underlying]; + } +} diff --git a/GlitchyEngine/BeefProj.toml b/GlitchyEngine/BeefProj.toml index 7d832a2..bc35522 100644 --- a/GlitchyEngine/BeefProj.toml +++ b/GlitchyEngine/BeefProj.toml @@ -1,4 +1,5 @@ FileVersion = 1 +Dependencies = {GlitchLog = "*", corlib = "*"} [Project] Name = "GlitchyEngine" diff --git a/GlitchyEngine/src/Log.bf b/GlitchyEngine/src/Log.bf new file mode 100644 index 0000000..3b100a8 --- /dev/null +++ b/GlitchyEngine/src/Log.bf @@ -0,0 +1,29 @@ +using System; +using GlitchLog; + +namespace GlitchyEngine +{ + public class Log + { + static Logger _engineLogger ~ delete _; + static Logger _clientLogger ~ delete _; + + [Inline] + public static Logger EngineLogger => _engineLogger; + [Inline] + public static Logger ClientLogger => _clientLogger; + + static this() + { + GlitchLog.Format = "[{t:HH:mm:ss.fff}] ({n})|{l}: {m}"; + + _engineLogger = new DebugLogger(); + _engineLogger.Name = "ENGINE"; + _engineLogger.Level = .Trace; + + _clientLogger = new DebugLogger(); + _clientLogger.Name = "APP"; + _clientLogger.Level = .Trace; + } + } +} diff --git a/GlitchyEngine/src/Program.bf b/GlitchyEngine/src/Program.bf index 5577034..10ca6f2 100644 --- a/GlitchyEngine/src/Program.bf +++ b/GlitchyEngine/src/Program.bf @@ -1,4 +1,6 @@ using System; +using GlitchLog; +using System.Diagnostics; namespace GlitchyEngine { @@ -9,12 +11,24 @@ namespace GlitchyEngine public static int Main(String[] args) { + Log.EngineLogger.Info("Initializing Application..."); + + Stopwatch initWatch = .StartNew(); + var app = CreateApplication(); + initWatch.Stop(); + + Log.EngineLogger.Info("Application initialized ({}ms).", initWatch.ElapsedMilliseconds); + app.Run(); + + Log.EngineLogger.Info("Uninitializing Application..."); delete app; + Log.EngineLogger.Info("Application uninitialized."); + return 0; } } diff --git a/Sandbox/BeefProj.toml b/Sandbox/BeefProj.toml index 42602b4..fe09da5 100644 --- a/Sandbox/BeefProj.toml +++ b/Sandbox/BeefProj.toml @@ -1,5 +1,5 @@ FileVersion = 1 -Dependencies = {corlib = "*", GlitchyEngine = "*"} +Dependencies = {GlitchyEngine = "*", corlib = "*"} [Project] Name = "Sandbox" diff --git a/Sandbox/src/SandboxApp.bf b/Sandbox/src/SandboxApp.bf index c00287f..851821c 100644 --- a/Sandbox/src/SandboxApp.bf +++ b/Sandbox/src/SandboxApp.bf @@ -1,5 +1,7 @@ using System; using GlitchyEngine; +using System.Diagnostics; +using GlitchLog; namespace Sandbox { @@ -8,6 +10,8 @@ namespace Sandbox [Export, LinkName("CreateApplication")] public static Application CreateApplication() { + + return new SandboxApp(); } }