TextFile.pas
资源名称:CAST2SDK.rar [点击查看]
上传用户:yj_qiu
上传日期:2022-08-08
资源大小:23636k
文件大小:9k
源码类别:
游戏引擎
开发平台:
Delphi
- (*
- @Abstract(Text file unit)
- (C) 2004-2007 George "Mirage" Bakhtadze. <a href="http://www.casteng.com">www.casteng.com</a> <br>
- The source code may be used under either MPL 1.1 or LGPL 2.1 license. See included license.txt file <br>
- Unit contains some text file related utilities and logging class
- *)
- {$Include GDefines.inc}
- unit TextFile;
- interface
- {$IFDEF LOGGING}
- uses
- // {$IFDEF USEFASTMM} FastMM4, {$ENDIF}
- SysUtils, OSUtils
- {$IFDEF MULTITHREADLOG}
- // {$IFDEF FPC} , FPCWindows {$ENDIF}
- , Windows
- {$ENDIF};
- {$ENDIF}
- type
- // Levels of importance of log messages
- TLogLevel = (lkDebug, lkInfo, lkNotice, lkWarning, lkError, lkFatalError);
- // Log level setting type
- TLogLevels = set of TLogLevel;
- const
- // lkDebug = 0; lkInfo = 1; lkNotice = 2; lkWarning = 3; lkError = 4; lkFatalError = 5; lkTitle = lkNotice;
- lkPrefix: array[TLogLevel] of string = (' (D) ', ' (i) ', ' (I) ', '(WW) ', '(EE) ', '(!!) ');
- // lfLogDebug = 1 shl 8; lfLogInfo = 1 shl 9; lfLogNotices = 1 shl 10; lfLogTitles = lfLogNotices;
- // lfLogWarnings = 1 shl 11; lfLogErrors = 1 shl 12; LogFatalErrors = 1 shl 13;
- llMax: TLogLevels = [lkDebug, lkInfo, lkNotice, lkWarning, lkError, lkFatalError];
- llMedium: TLogLevels = [lkNotice, lkWarning, lkError, lkFatalError];
- llMin: TLogLevels = [lkError, lkFatalError];
- // lmMask: array[0..lkFatalError] of Integer = (lfLogDebug, lfLogInfo, lfLogNotices, lfLogWarnings, lfLogErrors, LogFatalErrors);
- type
- // Log date and time setting type
- TLogTimeFormat = (// doesn't output any time information
- lfNone,
- // include date in the log
- lfDate,
- // include time in the log
- lfTime,
- // include date and time in the log
- lfDateTime,
- // include time elapsed since startup in the log
- lfElapsed);
- // Class reference to log session class
- CLogSession = class of TLogSession;
- { @Abstract(Logger class) }
- TLogSession = class
- private
- LogFile: Text;
- FLogLevels: TLogLevels;
- {$IFDEF MULTITHREADLOG}
- CriticalSection: _RTL_CRITICAL_SECTION; // ToDo: Replace with a user-mode sync
- {$ENDIF}
- LogKindCount: array[TLogLevel] of Integer;
- procedure SetMode(NewMode: TLogLevels);
- protected
- // Log mode titles
- ModeTitles: array[TLogLevel] of string;
- // Determines which date or time to include in the log
- TimeFormat: TLogTimeFormat;
- // Startup timestamp in milliseconds
- StartedMs: Cardinal;
- // Appends a string to log. Thread-safe if <b>MULTITHREADLOG</b> defined
- procedure AppendLog(const Desc: string; Level: TLogLevel = lkInfo); virtual;
- public
- { Initializes a log session with the specified log file name, time and level settings }
- constructor Init(const FileName: string; ATimeFormat: TLogTimeFormat; ALevels: TLogLevels); virtual;
- // Destructor
- destructor Shutdown; virtual;
- // Logs a string <b>Desc</b> if <b>Level</b> matches current logging level (see @Link(LogLevels))
- procedure Log(const Desc: string; Level: TLogLevel = lkInfo);
- // Set of levels which to include in the log
- property LogLevels: TLogLevels read FLogLevels write SetMode;
- end;
- //function SetLength(S : string; DLength : word):string;
- function SkipBeforeSTR(var TextFile : text; SkipSTR : string):boolean;
- function ReadLine(var TextFile : text):string;
- // Replaces logger with a new one of the specified class
- procedure ChangeLoggerClass(NewClass: CLogSession);
- var
- // Current logger
- Log: TLogSession;
- implementation
- function SkipBeforeSTR(var TextFile : text; SkipSTR : string):boolean;
- var s: string;
- begin
- repeat
- readln(TextFile, s);
- if s = SkipSTR then begin
- Result := True; Exit;
- end;
- until False;
- Result := False;
- end;
- function ReadLine(var TextFile : Text):string;
- var i: Word; var s: string;
- begin
- if EOF(TextFile) then exit;
- i:=1;
- repeat
- ReadLn(TextFile,s);
- until (s<>'') and (s[1]<>'#') or EOF(TextFile);
- if s<>'' then begin
- while s[i]=' ' do inc(i);
- if i=Length(s) then s:='' else s:=Copy(s, i, Length(s)-i+1);
- end;
- Result:=s;
- end;
- procedure ChangeLoggerClass(NewClass: CLogSession);
- var NewLog: TLogSession;
- begin
- if not Assigned(Log) or (NewClass = nil) then Exit;
- NewLog := NewClass.Create;
- NewLog.LogKindCount := Log.LogKindCount;
- NewLog.TimeFormat := Log.TimeFormat;
- NewLog.LogLevels := Log.LogLevels;
- NewLog.StartedMs := Log.StartedMs;
- AssignFile(NewLog.LogFile, TTextRec(Log.LogFile).Name);
- {$IFDEF MULTITHREADLOG}
- NewLog.CriticalSection := Log.CriticalSection;
- {$ENDIF}
- {$IFDEF MULTITHREADLOG}
- EnterCriticalSection(NewLog.CriticalSection);
- {$ENDIF}
- Log.Free;
- Log := NewLog;
- {$IFDEF MULTITHREADLOG}
- LeaveCriticalSection(NewLog.CriticalSection);
- {$ENDIF}
- Log.Log('Logger class changed to "' + NewClass.ClassName + '"', lkNotice);
- end;
- { TLogSession }
- procedure TLogSession.SetMode(NewMode: TLogLevels);
- var ModeStr: string; i: Integer;
- begin
- {$IFDEF LOGGING}
- ModeStr := '[';
- for i := Ord(Low(TLogLevel)) to Ord(High(TLogLevel)) do if TLogLevel(i) in NewMode then begin
- if ModeStr <> '[' then ModeStr := ModeStr + ', ';
- ModeStr := ModeStr + ModeTitles[TLogLevel(i)] + ' ' + Trim(lkPrefix[TLogLevel(i)]);
- end;
- ModeStr := ModeStr + ']';
- if NewMode = [] then ModeStr := 'nothing';
- Log('Logging ' + ModeStr, lkNotice);
- FLogLevels := NewMode;
- {$ENDIF}
- end;
- constructor TLogSession.Init(const FileName: string; ATimeFormat: TLogTimeFormat; ALevels: TLogLevels);
- var i: Integer; ModeStr: string;
- begin
- {$IFDEF LOGGING}
- TextFile.Log := Self;
- {$IFDEF MULTITHREADLOG}
- InitializeCriticalSection(CriticalSection);
- {$ENDIF}
- ModeTitles[lkDebug] := 'debug info';
- ModeTitles[lkInfo] := 'info';
- ModeTitles[lkNotice] := 'notices';
- ModeTitles[lkWarning] := 'warnings';
- ModeTitles[lkError] := 'errors';
- ModeTitles[lkFatalError] := 'fatal errors';
- if Pos(':', FileName) > 0 then AssignFile(LogFile, Filename) else AssignFile(LogFile, GetCurrentDir+''+Filename);
- {$I-}
- Rewrite(LogFile); CloseFile(LogFile);
- if IOResult <> 0 then ALevels := [];
- StartedMs := GetCurrentMs;
- case TimeFormat of
- lfNone: ModeStr := 'no timestamp mode.';
- lfDate: ModeStr := 'date only mode.';
- lfTime: ModeStr := 'time only mode.';
- lfDateTime: ModeStr := 'date and time mode.';
- lfElapsed: ModeStr := 'elapsed time mode.';
- end;
- TimeFormat := ATimeFormat;
- LogLevels := ALevels;
- Log('Log subsystem started in ' + ModeStr, lkNotice);
- for i := Ord(Low(TLogLevel)) to Ord(High(TLogLevel)) do LogKindCount[TLogLevel(i)] := 0;
- {$ENDIF}
- end;
- destructor TLogSession.Shutdown;
- begin
- {$IFDEF LOGGING}
- Log('Logged fatal errors: ' + IntToStr(LogKindCount[lkFatalError]) +
- ', errors: ' + IntToStr(LogKindCount[lkError]) +
- ', warnings: ' + IntToStr(LogKindCount[lkWarning]) +
- ', titles: ' + IntToStr(LogKindCount[lkNotice]) +
- ', infos: ' + IntToStr(LogKindCount[lkInfo]) +
- ', debug info: ' + IntToStr(LogKindCount[lkDebug]) );
- Log('Log session shutdown');
- TextFile.Log := nil;
- {$IFDEF MULTITHREADLOG}
- DeleteCriticalSection(CriticalSection);
- {$ENDIF}
- {$ENDIF}
- end;
- procedure TLogSession.Log(const Desc: string; Level: TLogLevel = lkInfo);
- begin
- {$IFDEF LOGGING}
- if not (Level in LogLevels) then Exit;
- {$IFDEF MULTITHREADLOG}
- EnterCriticalSection(CriticalSection);
- {$ENDIF}
- AppendLog(Desc, Level);
- {$IFDEF MULTITHREADLOG}
- LeaveCriticalSection(CriticalSection);
- {$ENDIF}
- {$ENDIF}
- end;
- procedure TLogSession.AppendLog(const Desc: string; Level: TLogLevel = lkInfo);
- begin
- {$IFDEF LOGGING}
- {$I-}
- Append(LogFile);
- if IOResult <> 0 then Exit;
- case TimeFormat of
- lfNone: WriteLn(LogFile, lkPrefix[Level] + Desc);
- lfDate: WriteLn(LogFile, DateToStr(Now) + #9 + lkPrefix[Level] + Desc);
- lfTime: WriteLn(LogFile, TimeToStr(Now) + #9 + lkPrefix[Level] + Desc);
- lfDateTime: WriteLn(LogFile, DateTimeToStr(Now) + #9 + lkPrefix[Level] + Desc);
- lfElapsed: WriteLn(LogFile, IntToStr(GetCurrentMs-StartedMs) + #9 + lkPrefix[Level] + Desc);
- end;
- CloseFile(LogFile);
- Inc(LogKindCount[Level]);
- {$ENDIF}
- end;
- initialization
- {$IFDEF LOGGING}
- Log := TLogSession.Init(Copy(ExtractFileName(ParamStr(0)), 1, Length(ExtractFileName(ParamStr(0))) - Length(ExtractFileExt(ParamStr(0)))) + '.log', lfElapsed, llMax);
- {$ELSE}
- Log := TLogSession.Init('', lfNone, llMin);
- {$ENDIF}
- finalization
- Log.Shutdown;
- end.