1 // =================================
  2 // Copyright (c) 2024 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System.Collections;
  7 using System.Threading;
  8 
  9 namespace System
 10 {
 11     public List<string> SplitMessageIntoLines(const string& text)
 12     {
 13         string line;
 14         List<string> lines;
 15         for (char c : text)
 16         {
 17             if (c == '\n')
 18             {
 19                 lines.Add(line);
 20                 line.Clear();
 21             }
 22             else if (c != '\r')
 23             {
 24                 line.Append(c);
 25             }
 26         }
 27         if (!line.IsEmpty() || text.IsEmpty())
 28         {
 29             lines.Add(line);
 30         }
 31         return lines;
 32     }
 33 
 34     public enum LogMode
 35     {
 36         consolequeue
 37     }
 38 
 39     public class Log
 40     {
 41         static Log() : instance(new Log())
 42         {
 43         }
 44         public static Log& Instance()
 45         {
 46             return *instance;
 47         }
 48         public inline void SetMode(LogMode mode_)
 49         {
 50             mode = mode_;
 51         }
 52         public inline LogMode Mode() const
 53         {
 54             return mode;
 55         }
 56         private Log() : mtx()mode(LogMode.console)
 57         {
 58         }
 59         [nodiscard]
 60         public Result<bool> LogMessage(int logStreamIdconst string& message)
 61         {
 62             if (mode == LogMode.queue)
 63             {
 64                 return PutMessageToQueue(logStreamIdmessage);
 65             }
 66             else if (mode == LogMode.console)
 67             {
 68                 LockGuard<Mutex> lock(mtx);
 69                 if (logStreamId == -1)
 70                 {
 71                     Console.Out() << message << endl();
 72                 }
 73                 else
 74                 {
 75                     Console.Out() << Format(ToString(logStreamId)2FormatWidth.minFormatJustify.right'0') << ">" << message << endl();
 76                 }
 77             }
 78             return Result<bool>(true);
 79         }
 80         [nodiscard]
 81         public Result<string> GetMessageFromQueue()
 82         {
 83             return queue.Get();
 84         }
 85         public inline bool Exiting() const
 86         {
 87             return queue.Exiting();
 88         }
 89         [nodiscard]
 90         public Result<bool> Exit()
 91         {
 92             return queue.Exit();
 93         }
 94         [nodiscard]
 95         private Result<bool> PutMessageToQueue(int logStreamIdconst string& message)
 96         {
 97             if (logStreamId == -1)
 98             {
 99                 Result<bool> result = queue.Put(message);
100                 if (result.Error()) return result;
101             }
102             else
103             {
104                 string s = Format(ToString(logStreamId)2FormatWidth.minFormatJustify.right'0');
105                 s.Append(">").Append(message);
106                 Result<bool> result = queue.Put(s);
107                 if (result.Error()) return result;
108             }
109             return Result<bool>(true);
110         }
111         private static UniquePtr<Log> instance;
112         private Mutex mtx;
113         private LogMode mode;
114         private System.Threading.SynchronizedQueue<string> queue;
115     }
116 
117     [nodiscard]
118     public Result<bool> LogMessage(int logStreamIdconst string& message)
119     {
120         List<string> lines = SplitMessageIntoLines(message);
121         for (const string& line : lines)
122         {
123             Result<bool> result = Log.Instance().LogMessage(logStreamIdline);
124             if (result.Error()) return result;
125         }
126         return Result<bool>(true);
127     }
128 }