diff options
Diffstat (limited to 'tests/examplefiles/example.pas')
| -rw-r--r-- | tests/examplefiles/example.pas | 2708 | 
1 files changed, 2708 insertions, 0 deletions
diff --git a/tests/examplefiles/example.pas b/tests/examplefiles/example.pas new file mode 100644 index 00000000..ab11ee67 --- /dev/null +++ b/tests/examplefiles/example.pas @@ -0,0 +1,2708 @@ +// vim:ft=pascal + +unit YTools; + +{=============================================================================== + +   cYcnus.YTools 1.0.3 Beta for Delphi 4+ +   by licenser and Murphy + +   ©2000-2003 by cYcnus +   visit www.cYcnus.de + +   licenser@cYcnus.de (Heinz N. Gies) +   murphy@cYcnus.de (Kornelius Kalnbach) +    +   this unit is published under the terms of the GPL + +===============================================================================} + +interface + +uses +  Windows, SysUtils, Classes, YTypes; + +const +  BackSpace = #8; +  Tab = #9; +  LF = #10; //Line Feed +  CR = #13; //Carriage Return +  Space = #32; +  EOLChars = [CR, LF]; +{$IFNDEF VER140} +  sLineBreak = #13#10; +  SwitchChars = ['/', '-']; +{$ENDIF} +  EOL = sLineBreak; +  MaxCard = High(Cardinal); +  AllChars = [#0..#255]; +  Alphabetical = ['A'..'Z', 'a'..'z']; +  DecimalChars = ['0'..'9']; +  AlphaNumerical = Alphabetical + DecimalChars; +  StrangeChars = [#0..#31, #127, #129, #141..#144, #157, #158]; + +  HexadecimalChars = DecimalChars + ['A'..'F', 'a'..'f']; +  OctalChars = ['0'..'7']; +  BinaryChars = ['0', '1']; + +  QuoteChars = ['''', '"']; +  WildCards = ['*', '?']; +  FileNameEnemies = WildCards + ['\', '/', ':', '<', '>', '|']; + +  HexChar: array[THex] of Char = ( +    '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); +  LowerHexChar: array[THex] of Char = ( +    '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'); +  BaseNChar: array[TBaseN] of Char = ( +    '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H', +    'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'); + +  cYcnusOverlayColor = $050001; + +  faFindEveryFile = faReadOnly + faHidden + faSysFile + faArchive; + +  platWin9x = [VER_PLATFORM_WIN32s, VER_PLATFORM_WIN32_WINDOWS]; + + +{ Debugging } +procedure ClearReport(const ReportName: string); +procedure Report(const ReportName, Text: string); +procedure ReportFmt(const ReportName, Fmt: string; const Args: array of const); + +{ Params } +procedure GetParams(Strings: TStrings); overload; +function GetParams(const Separator: string = ' '): string; overload; + +function ParamNum(const S: string): Integer; +function ParamPrefixNum(const Prefix: string): Integer; +function Param(const S: string): Boolean; +function ParamPrefix(const Prefix: string): Boolean; + +function Switch(const Switch: string; const PrefixChars: TCharSet = SwitchChars; +  IgnoreCase: Boolean = True): Boolean; +function GetParam(const Prefix: string = ''; const Default: string = ''): string; + +{ Dirs & UserName} +function GetMyDir(FullPath: Boolean = False): string; +function WinDir: string; +function SysDir: string; +function UserName: string; + +{ Strings & Chars} +function FirstChar(const S: string): Char; +function LastChar(const S: string): Char; + +function CharPos(C: Char; const S: string; Offset: Integer = 1): Integer; overload; +function CharPos(C: TCharSet; const S: string; Offset: Integer = 1): Integer; overload; +function CharPosR(C: Char; const S: string; Offset: Integer = -1): Integer; +function PosEx(const SubStr, S: string; Offset: Integer = 1): Integer; +function PosExText(const SubStr, S: string; Offset: Integer = 1): Integer; +function PosExAnsiText(const SubStr, S: string; Offset: Integer = 1): Integer; + +function UntilChar(const S: string; Brake: Char): string; overload; +function UntilChar(const S: string; Brake: TCharSet): string; overload; +function UntilLastChar(const S: string; Brake: Char; +  IgnoreNoBrake: Boolean = True): string; + +function FromChar(const S: string; Brake: Char): string; overload; +function FromChar(const S: string; Brake: TCharSet): string; overload; +function FromLastChar(const S: string; Brake: Char; +  IgnoreNoBrake: Boolean = False): string; + +function BetweenChars(const S: string; Start, Finish: Char; +  Inclusive: Boolean = False): string; + +function UntilStr(const S: string; Brake: string): string; +function FromStr(const S: string; Brake: string): string; + +function StringWrap(const S: string; Width: Integer; const LineEnd: string = EOL): string; + +{ Splitting & Combining } +function Split(const S, Separator: string; IgnoreMultiSep: Boolean = True; +  MinCount: Integer = 0): TStrA; overload; +procedure Split(const S, Separator: string; Strings: TStrings; +  IgnoreMultiSep: Boolean = True); overload; +function Split(const S: string; Separators: TCharSet; +  IgnoreMultiSep: Boolean = True; MinCount: Integer = 0): TStrA; overload; + +procedure TileStr(const S: string; BrakeStart: Integer; BrakeEnd: Integer; +  out Left, Right: string); + +function Join(Strings: TStrings; Separator: string = ' '): string; overload; +function Join(StrA: TStrA; Separator: string = ' '): string; overload; + +function MulStr(const S: string; Count: Integer): string; + +{ Strings ausrichten } +function AlignR(const S: string; Width: Integer; Filler: Char = ' '): string; +function MaxStr(const S: string; MaxLen: Integer): string; + +{ Stringing } +function TrimAll(const S: string): string; + +function ControlChar(C: Char): Boolean; +function FriendlyChar(C: Char): Char; + +function FriendlyStr(const S: string): string; overload; +function FriendlyStr(a: TByteA): string; overload; + +function Quote(const S: string; Quoter: Char = '"'): string; +function UnQuote(const S: string): string; +function DeQuote(const S: string): string; + +function StrNumerus(const Value: Integer; const Singular, Plural: string; +  const Zero: string = '0'): string; + +function MakeStr(const Items: array of const; Separator: string = ''): string; +procedure ShowText(const Items: array of const; Separator: string = ''); + +{ Delete } +function DeleteChars(const S: string; C: Char): string; overload; +function DeleteChars(const S: string; C: TCharSet): string; overload; +function ExtractChars(const S: string; C: TCharSet): string; + +{ Find } +function CharCount(const S: string; C: Char): Integer; + +function CharIn(const S: string; C: Char): Boolean; overload; +function CharIn(const S: string; C: TCharSet): Boolean; overload; + +function StrAtPos(const S: string; Pos: Integer; const Str: string): Boolean; +function StrAtBegin(const S, Str: string): Boolean; +function StrIn(const S, SubStr: string): Boolean; overload; +function StrIn(A: TStrA; const S: string): Boolean; overload; +function StrIn(SL: TStrings; const S: string): Boolean; overload; +function StrIndex(A: TStrA; const S: string): Integer; overload; +function StrIndex(SL: TStrings; const S: string): Integer; overload; + +function TextAtPos(const S: string; Pos: Integer; const Text: string): Boolean; +function TextAtBegin(const S, Text: string): Boolean; +function TextIn(const S, Text: string): Boolean; overload; +function TextIn(A: TStrA; const Text: string): Boolean; overload; +function TextIn(SL: TStrings; const Text: string): Boolean; overload; +function TextIndex(A: TStrA; const Text: string): Integer; overload; +function TextIndex(SL: TStrings; const Text: string): Integer; overload; + +{ Replace } +function ReplaceChars(const S: string; Old, New: Char): string; overload; +function ReplaceChars(const S: string; Old: TCharSet; New: Char): string; overload; + +function Replace(const S, Old, New: string): string; + +{ TStrings } +function SLOfFile(const FileName: string): TStringList; +function ContainsEmptyLines(SL: TStrings): Boolean; +procedure DeleteEmptyLines(SL: TStrings); +procedure DeleteCommentLines(SL: TStrings; const CommentSign: string = '//'); +procedure WriteSL(Strings: TStrings; const Prefix: string = ''; +  const Suffix: string = ''); + +function FindLine(SL: TStrings; const S: string): Integer; + +procedure QuickSortSL(SL: TStringList); + +{ TStrA } +function IncStrA(StrA: TStrA): Integer; + +{ TByteA } +function StrOfByteA(a: TByteA): string; +function ByteAOfStr(const S: string): TByteA; +function ByteAOfInt(i: Integer): TByteA; +function IntOfByteA(A: TByteA): Integer; +function ByteAOfHex(const Hex: string): TByteA; + +function SameByteA(const A, B: TByteA): Boolean; +function Reverse(a: TByteA): TByteA; +function SaveByteA(Data: TByteA; const FileName: string; Overwrite: Boolean = True): Boolean; +function LoadByteA(const FileName: string): TByteA; + +function Endian(i: Integer): Integer; + +{ Files } +function SizeOfFile(const FileName: string): Integer; +function FileEx(const FileName: string; AllowFolders: Boolean = False): Boolean; +function LWPSolve(const Dir: string): string; +function LWPSlash(const Dir: string): string; + +function ExtractDrive(const FileName: string): string; +function ExtractPath(const FileName: string): string; +function ExtractPrefix(const FileName: string): string; +function ExtractSuffix(const FileName: string): string; + +function IsValidFileName(const FileName: string): Boolean; +function MakeValidFileName(FileName: string; const Default: string = 'File'): string; + +{ Converting } +function IsValidInteger(const S: string): Boolean; +function IsValidCardinal(const S: string): Boolean; + +function StrOfBool(flag: Boolean; const TrueStr: string = 'True'; +  const FalseStr: string = 'False'): string; +function StrOfInt(i: Integer): string; +function CardOfStr(const S: string): Cardinal; + +function HexOrd(Hex: Char): THex; +function ByteOfHex(Hex: THexByteStr): Byte; + +function DecOfHex(const Hex: string): string; +function HexOfByte(b: Byte): THexByteStr; +function HexOfCard(i: Cardinal): string; overload; +function HexOfCard(i: Cardinal; Digits: Integer): string; overload; + +function PascalHexArray(a: TByteA; Name: string): string; + +function HexOfByteA(a: TByteA; Blocks: Integer = 1; +  const Splitter: string = ' '): string; +function BinOfByteA(a: TByteA; Blocks: Integer = 4; +  const Splitter: string = ' '): string; + +function CardOfHex(Hex: string): Cardinal; +function IntOfBin(Bin: string): Cardinal; + +function BinOfIntFill(n: cardinal; MinCount: Integer = 8): string; +function BinOfInt(n: cardinal): string; + +function BaseNOfInt(I: Cardinal; B: TBaseN): string; +function IntOfBaseN(V: string; B: TBaseN): Cardinal; + +{ Ranges } +function KeepIn(i, Bottom, Top: Variant): Variant; +function InRange(Value, Bottom, Top: Variant): Boolean; +function InStrictRange(Value, Bottom, Top: Variant): Boolean; +function Min(const A, B: Integer): Integer; overload; +function Min(const A: TIntA): Integer; overload; +function Max(const A, B: Integer): Integer; overload; +function Max(const A: TIntA): Integer; overload; + +const +  RangesSeparator = ','; +  RangeInnerSeparator = '-'; +  RangeInfinite = '*'; +  RangeSpecialChars = [RangesSeparator, RangeInnerSeparator, RangeInfinite]; + +function RangesOfStr(const S: string): TRanges; +function InRanges(Ranges: TRanges; TestValue: Cardinal): Boolean; + +function Success(Res: Integer; ResultOnSuccess: Integer = ERROR_SUCCESS): Boolean; +function Failure(Res: Integer; ResultOnSuccess: Integer = ERROR_SUCCESS): Boolean; + +function ExpandString(const S: string): string; + +{ Files } +procedure DeleteFiles(const Mask: string; ScanSubDirs: Boolean = True; +  Attributes: Integer = faFindEveryFile); +procedure FileNew(const FileName: string); +function DateTimeOfFileTime(const FileTime: TFileTime): TDateTime; + +{ FileNames } +function GetFileNew(FileName: string; NoFloppyDrives: Boolean = True): string; + +{ Finding Files } +function FindAll(Strings: TStrings; const Mask: string; +  ScanSubDirs: Boolean = True; Attributes: Integer = faFindEveryFile; +  FileReturn: TFileNameFunc = nil): Boolean; +function FindAllFirst(const Mask: string; ScanSubDirs: Boolean = True; +  Attributes: Integer = faFindEveryFile): string; + +function FullOSInfo: string; +function Win32PlatformStr: string; +function Win9x: Boolean; +function WinNT: Boolean; +function Win2000: Boolean; +function WinXP: Boolean; + +var +  MyDir: string = ''; +  LastSuccessRes: Integer = 0; +   +{ Backward compatibility } +{$IFNDEF VER130} +function SameText(const S1, S2: string): Boolean; +{$ENDIF} + +implementation +{$IFNDEF VER140} +uses FileCtrl; +{$ENDIF} + +{$IFNDEF VER130} +function SameText(const S1, S2: string): Boolean; +begin +  Result := CompareText(S1, S2) = 0; +end; +{$ENDIF} + +procedure Report(const ReportName, Text: string); +var +  F: TextFile; +  FileName: string; +begin +  FileName := MyDir + ReportName + '.rep'; +  Assign(F, FileName); +  try +    if not FileExists(FileName) then +      Rewrite(F) +    else +      Append(F); +    WriteLn(F, Text); +  finally +    Close(F); +  end; +end; + +procedure ClearReport(const ReportName: string); +var +  FileName: string; +begin +  FileName := MyDir + ReportName + '.rep'; +  DeleteFile(FileName); +end; + +procedure ReportFmt(const ReportName, Fmt: string; const Args: array of const); +begin +  Report(ReportName, Format(Fmt, Args)); +end; + +procedure GetParams(Strings: TStrings); +var +  P: PChar; +  Param: string; + +  function GetParamStr(var P: PChar; var Param: string): Boolean; +  var +    Quoted: Boolean; +  begin +    Param := ''; + +    repeat +      while (P[0] <> #0) and (P[0] <= ' ') do +        Inc(P); + +      Quoted := False; +      while P[0] <> #0 do begin +        if P[0] = '"' then begin +          Quoted := not Quoted; +          Inc(P); +        Continue; end; +        if (P[0] <= ' ') and not Quoted then +          Break; +        Param := Param + P[0]; +        Inc(P); +      end; +    until (Param <> '') or (P[0] = #0); + +    Result := Param <> ''; +  end; + +begin +  Strings.Clear; +  P := GetCommandLine; +  GetParamStr(P, Param); +  while GetParamStr(P, Param) do +    Strings.Add(Param); +end; + +function GetParams(const Separator: string = ' '): string; +var +  SL: TStringList; +begin +  SL := TStringList.Create; +  GetParams(SL); +  Result := Join(SL, Separator); +  SL.Free; +end; + +function Switch(const Switch: string; const PrefixChars: TCharSet = SwitchChars; +  IgnoreCase: Boolean = True): Boolean; +//= SysUtils.FindCmdLineSwitch +var +  i: Integer; +  s: string; +begin +  Result := True; + +  for i := 1 to ParamCount do begin +    s := ParamStr(i); + +    if (s <> '') and (s[1] in PrefixChars) then begin +    //i know that always s <> '', but this is saver +      s := Copy(s, 2, MaxInt); +      if (s = Switch) or (IgnoreCase and (0=AnsiCompareText(s, Switch))) then +        Exit; +    end; +  end; + +  Result := False; +end; + +function ParamNum(const S: string): Integer; +begin +  for Result := 1 to ParamCount do +    if 0=AnsiCompareText(ParamStr(Result), S) then +      Exit; + +  Result := 0; +end; + +function ParamPrefixNum(const Prefix: string): Integer; +var +  Len: Integer; +begin +  Len := Length(Prefix); +  for Result := 1 to ParamCount do +    if 0=AnsiCompareText(Copy(ParamStr(Result), 1, Len), Prefix) then +      Exit; + +  Result := 0; +end; + +function Param(const S: string): Boolean; +begin +  Result := ParamNum(S) > 0; +end; + +function ParamPrefix(const Prefix: string): Boolean; +begin +  Result := ParamPrefixNum(Prefix) > 0; +end; + +function GetParam(const Prefix: string = ''; const Default: string = ''): string; +var +  i: Integer; +begin +  Result := Default; + +  if Prefix = '' then begin +    Result := ParamStr(1); +  Exit; end; + +  i := ParamPrefixNum(Prefix); +  if i > 0 then +    Result := Copy(ParamStr(i), Length(Prefix) + 1, MaxInt); +end; + +function GetMyDir(FullPath: Boolean = False): string; +var +  Buffer: array[0..260] of Char; +begin +  Result := ''; +  SetString(Result, Buffer, GetModuleFileName(0, Buffer, SizeOf(Buffer))); +  if FullPath then +    Result := GetFileNew(Result); +  Result := ExtractPath(Result); +end; + +function WinDir: string; +var +  Res: PChar; +begin +  Result := '\'; +  GetMem(Res, MAX_PATH); +  GetWindowsDirectory(Res, MAX_PATH); +  Result := Res + '\'; +  FreeMem(Res, MAX_PATH); +end; + +function SysDir: string; +var +  Res: PChar; +begin +  Result := '\'; +  GetMem(Res, MAX_PATH); +  GetSystemDirectory(Res, MAX_PATH); +  Result := Res + '\'; +  FreeMem(Res, MAX_PATH); +end; + +function UserName: string; +var +  Len: Cardinal; +  Res: PChar; +begin +  Result := ''; +  GetMem(Res, MAX_PATH); +  Len := MAX_PATH; +  GetUserName(Res, Len); +  Result := Res; +  FreeMem(Res, MAX_PATH); +end; + +function FirstChar(const S: string): Char; +begin +  if s = '' then +    Result := #0 +  else +    Result := s[1]; +end; + +function LastChar(const S: string): Char; +begin +  if s = '' then +    Result := #0 +  else +    Result := s[Length(s)]; +end; + +function CharPos(C: Char; const S: string; Offset: Integer = 1): Integer; +var +  MaxPosToSearch: Integer; +begin +  Result := Offset; +  MaxPosToSearch := Length(S); + +  while Result <= MaxPosToSearch do begin +    if S[Result] = C then +      Exit; +    Inc(Result); +  end; + +  Result := 0; +end; + +function CharPos(C: TCharSet; const S: string; Offset: Integer = 1): Integer; +var +  MaxPosToSearch: Integer; +begin +  Result := Offset; +  MaxPosToSearch := Length(S); + +  while Result <= MaxPosToSearch do begin +    if S[Result] in C then +      Exit; +    Inc(Result); +  end; + +  Result := 0; +end; + +function CharPosR(C: Char; const S: string; Offset: Integer = -1): Integer; +begin +  if Offset < 0 then +    Result := Length(S) + 1 - Offset +  else +    Result := Offset; +  if Result > Length(S) then +    Result := Length(S); + +  while Result > 0 do begin +    if S[Result] = C then +      Exit; +    Dec(Result); +  end; +end; + +function PosEx(const SubStr, S: string; Offset: Integer = 1): Integer; +var +  MaxPosToSearch, LenSubStr, i: Integer; +begin +  if SubStr = '' then begin +    Result := 0; +  Exit; end; + +  if Offset < 1 then +    Result := 1 +  else +    Result := Offset; + +  LenSubStr := Length(SubStr); +  MaxPosToSearch := Length(S) - LenSubStr + 1; + +  while Result <= MaxPosToSearch do begin +    if S[Result] = SubStr[1] then begin +      i := 1; + +      while (i < LenSubStr) +       and (S[Result + i] = SubStr[i + 1]) do +        Inc(i); + +      if i = LenSubStr then +        Exit; +    end; +    Inc(Result); +  end; + +  Result := 0; +end; + +function PosExText(const SubStr, S: string; Offset: Integer = 1): Integer; +var +  MaxPosToSearch, LenSubStr, i: Integer; + +  function SameChar(a, b: Char): Boolean; +  begin +    Result := UpCase(a) = UpCase(b) +  end; + +begin +  if SubStr = '' then begin +    Result := 0; +  Exit; end; + +  if Offset < 1 then +    Result := 1 +  else +    Result := Offset; + +  LenSubStr := Length(SubStr); +  MaxPosToSearch := Length(S) - LenSubStr + 1; + +  while Result <= MaxPosToSearch do begin +    if SameChar(S[Result], SubStr[1]) then begin +      i := 1; + +      while (i < LenSubStr) +       and (SameChar(S[Result + i], SubStr[i + 1])) do +        Inc(i); + +      if i = LenSubStr then +        Exit; +    end; +    Inc(Result); +  end; + +  Result := 0; +end; + +function PosExAnsiText(const SubStr, S: string; Offset: Integer = 1): Integer; +var +  MaxPosToSearch, LenSubStr, i: Integer; + +  function SameChar(a, b: Char): Boolean; +  begin +    Result := CharLower(PChar(a)) = CharLower(PChar(b)); +  end; + +begin +  if SubStr = '' then begin +    Result := 0; +  Exit; end; + +  if Offset < 1 then +    Result := 1 +  else +    Result := Offset; + +  LenSubStr := Length(SubStr); +  MaxPosToSearch := Length(S) - LenSubStr + 1; + +  while Result <= MaxPosToSearch do begin +    if SameChar(S[Result], SubStr[1]) then begin +      i := 1; + +      while (i < LenSubStr) +       and (SameChar(S[Result + i], SubStr[i + 1])) do +        Inc(i); + +      if i = LenSubStr then +        Exit; +    end; +    Inc(Result); +  end; + +  Result := 0; +end; + +function UntilChar(const S: string; Brake: Char): string; +var +  p: Integer; +begin +  p := CharPos(Brake, S); + +  if p > 0 then +    Result := Copy(S, 1, p - 1) +  else +    Result := S; +end; + +function UntilChar(const S: string; Brake: TCharSet): string; +var +  p: Integer; +begin +  Result := ''; +  p := CharPos(Brake, S); + +  if p > 0 then +    Result := Copy(S, 1, p - 1) +  else +    Result := S; +end; + +function UntilLastChar(const S: string; Brake: Char; +  IgnoreNoBrake: Boolean = True): string; +var +  p: Integer; +begin +  Result := ''; +  p := CharPosR(Brake, S); + +  if p > 0 then +    Result := Copy(S, 1, p - 1) +  else if IgnoreNoBrake then +    Result := S; +end; + +function FromChar(const S: string; Brake: Char): string; +var +  p: Integer; +begin +  Result := ''; +  p := CharPos(Brake, S); + +  if p > 0 then +    Result := Copy(S, p + 1, Length(S) - p); +end; + +function FromChar(const S: string; Brake: TCharSet): string; +var +  p: Integer; +begin +  Result := ''; +  p := CharPos(Brake, S); + +  if p > 0 then +    Result := Copy(S, p + 1, Length(S) - p); +end; + +function FromLastChar(const S: string; Brake: Char; +  IgnoreNoBrake: Boolean = False): string; +var +  p: Integer; +begin +  Result := ''; +  p := CharPosR(Brake, S); + +  if p > 0 then +    Result := Copy(S, p + 1, Length(S) - p) +  else if IgnoreNoBrake then +    Result := S; +end; + +function BetweenChars(const S: string; Start, Finish: Char; +  Inclusive: Boolean = False): string; +var +  p, fin: Integer; +begin +  Result := ''; + +  p := CharPos(Start, S); +  if p = 0 then +    Exit; + +  fin := CharPos(Finish, S, p + 1); +  if fin = 0 then +    Exit; + +  if not Inclusive then begin +    Inc(p); +    Dec(fin); +  end; + +  Result := Copy(S, p, fin - p + 1); +end; + +function UntilStr(const S: string; Brake: string): string; +var +  p: Integer; +begin +  if Length(Brake) = 1 then begin +    Result := UntilChar(S, Brake[1]); +  Exit; end; + +  p := PosEx(Brake, S); + +  if p > 0 then +    Result := Copy(S, 1, p - 1) +  else +    Result := S; +end; + +function FromStr(const S: string; Brake: string): string; +var +  p: Integer; +begin +  if Length(Brake) = 1 then begin +    Result := FromChar(S, Brake[1]); +  Exit; end; + +  Result := ''; +  p := PosEx(Brake, s); + +  if p > 0 then begin +    Inc(p, Length(Brake)); +    Result := Copy(S, p, Length(S) - p + 1); +  end; +end; + +function StringWrap(const S: string; Width: Integer; const LineEnd: string = EOL): string; +var +  i: Integer; +begin +  Result := ''; +  if (S = '') or (Width < 1) then +    Exit; + +  i := 1; +  while True do begin +    Result := Result + Copy(S, i, Width); +    Inc(i, Width); +    if i <= Length(S) then +      Result := Result + LineEnd +    else +      Exit; +  end; +end; + +function Split(const S, Separator: string; IgnoreMultiSep: Boolean = True; +  MinCount: Integer = 0): TStrA; +var +  p, fin, SepLen: Integer; + +  procedure Add(const S: string); +  begin +    if IgnoreMultiSep and (S = '') then +      Exit; +    SetLength(Result, Length(Result) + 1); +    Result[High(Result)] := S; +  end; + +begin +  if S = '' then begin +    if Length(Result) < MinCount then +      SetLength(Result, MinCount); +  Exit; end; + +  Result := nil; +  SepLen := Length(Separator); + +  p := 1; +  fin := PosEx(Separator, S); +  while fin > 0 do begin +    Add(Copy(S, p, fin - p)); +    p := fin + SepLen; +    fin := PosEx(Separator, S, p); +  end; +  Add(Copy(S, p, Length(S) - p + 1)); + +  if Length(Result) < MinCount then +    SetLength(Result, MinCount); +end; + +procedure Split(const S, Separator: string; Strings: TStrings; +  IgnoreMultiSep: Boolean = True);  +var +  p, fin, SepLen: Integer; + +  procedure Add(const S: string); +  begin +    if IgnoreMultiSep and (S = '') then +      Exit; +    Strings.Add(S); +  end; + +begin +  if S = '' then +    Exit; + +  Strings.BeginUpdate; +  SepLen := Length(Separator); +  p := 1; +  fin := PosEx(Separator, S); +  while fin > 0 do begin +    Add(Copy(S, p, fin - p)); +    p := fin + SepLen; +    fin := PosEx(Separator, S, p); +  end; +  Add(Copy(S, p, Length(S) - p + 1)); +  Strings.EndUpdate; +end; + +function Split(const S: string; Separators: TCharSet; +  IgnoreMultiSep: Boolean = True; MinCount: Integer = 0): TStrA; +var +  p, fin: Integer; + +  procedure Add(const S: string); +  begin +    if IgnoreMultiSep and (S = '') then +      Exit; +    SetLength(Result, Length(Result) + 1); +    Result[High(Result)] := S; +  end; + +begin +  if S = '' then begin +    if Length(Result) < MinCount then +      SetLength(Result, MinCount); +  Exit; end; + +  Result := nil; + +  p := 1; +  fin := CharPos(Separators, S); +  while fin > 0 do begin +    Add(Copy(S, p, fin - p)); +    p := fin + 1; +    fin := CharPos(Separators, S, p); +  end; +  Add(Copy(S, p, Length(S) - p + 1)); + +  if Length(Result) < MinCount then +    SetLength(Result, MinCount); +end; + +procedure TileStr(const S: string; BrakeStart: Integer; BrakeEnd: Integer; +  out Left, Right: string); +begin +  Left := Copy(S, 1, BrakeStart-1); +  Right := Copy(S, BrakeEnd + 1, MaxInt); +end; + +function Join(Strings: TStrings; Separator: string = ' '): string; +var +  i, imax: Integer; +begin +  Result := ''; +  imax := Strings.Count-1; +  for i := 0 to imax do begin +    Result := Result + Strings[i]; +    if i < imax then +      Result := Result + Separator; +  end; +end; + +function Join(StrA: TStrA; Separator: string = ' '): string; overload; +var +  i: Integer; +begin +  Result := ''; +  for i := 0 to High(StrA) do begin +    Result := Result + StrA[i]; +    if i < High(StrA) then +      Result := Result + Separator; +  end; +end; + +function MulStr(const S: string; Count: Integer): string; +var +  P: PChar; +  Len, i: Integer; +begin +  Result := ''; +  if Count = 0 then +    Exit; + +  Len := Length(S); +  SetLength(Result, Len * Count); + +  P := Pointer(Result); +  for i := 1 to Count do begin +    Move(Pointer(S)^, P^, Len); +    Inc(P, Len); +  end; +end; + +function AlignR(const S: string; Width: Integer; Filler: Char = ' '): string; +begin +  Result := MulStr(Filler, Width - Length(S)) + S; +end; + +function MaxStr(const S: string; MaxLen: Integer): string; +var +  Len: Integer; +begin +  Len := Length(S); +  if Len <= MaxLen then begin +    Result := S; +  Exit end; + +  Result := Copy(S, 1, MaxLen - 3) + '...'; +end; + +function TrimAll(const S: string): string; +var +  i: Integer; +begin +  for i := 1 to Length(S) do +    if S[i] > #32 then +      Result := Result + S[i]; +end; + +function ControlChar(C: Char): Boolean; +begin +  Result := C in StrangeChars; +end; + +function FriendlyChar(C: Char): Char; +begin +  case C of +    #0: Result := '.'; +    #1..#31: Result := '?'; +    #255: Result := '#'; +  else +    Result := C; +  end; +end; + +function FriendlyStr(const S: string): string; +var +  i: Integer; +begin +  SetLength(Result, Length(S)); +  for i := 1 to Length(S) do +    Result[i] := FriendlyChar(S[i]); +end; + +function FriendlyStr(a: TByteA): string; +var +  i: Integer; +begin +  SetLength(Result, Length(a)); +  for i := 0 to High(a) do +    Result[i + 1] := FriendlyChar(Char(a[i])); +end; + +function Quote(const S: string; Quoter: Char = '"'): string; +begin +  Result := S; + +  if FirstChar(S) <> Quoter then +    Result := Quoter + Result; + +  if LastChar(S) <> Quoter then +    Result := Result + Quoter; +end; + +function DeQuote(const S: string): string; +begin +  Result := ''; +  if Length(S) > 2 then +    Result := Copy(S, 2, Length(S) - 2); +end; + +function UnQuote(const S: string): string; +var +  Start, Len: Integer; +begin +  Start := 1; +  Len := Length(S); + +  if (S <> '') and (S[1] in ([#0..#32] + QuoteChars)) then begin +    if (LastChar(S) = S[1]) then +      Dec(Len); +    Inc(Start); +  end; + +  Result := Copy(S, Start, Len - Start + 1); +end; + +function StrNumerus(const Value: Integer; const Singular, Plural: string; +  const Zero: string = '0'): string; +begin +  if Abs(Value) = 1 then +    Result := IntToStr(Value) + ' ' + Singular +  else if Value = 0 then +    Result := Zero + ' ' + Plural +  else +    Result := IntToStr(Value) + ' ' + Plural; +end; + +function MakeStr(const Items: array of const; Separator: string = ''): string; +const +  BoolStrings: array[Boolean] of string = ('False', 'True'); + +var +  i: Integer; + +  function StrOfP(P: Pointer): string; +  begin +    if P = nil then +      Result := '[nil]' +    else +      Result := '[' + IntToStr(Cardinal(P)) + ']'; +  end; + +  procedure Add(const S: string); +  begin +    Result := Result + s + Separator; +  end; + +begin +  Result := ''; +  for i := 0 to High(Items) do +    with Items[i] do +      case VType of +        vtString:     Add(VString^); +        vtInteger:    Add(IntToStr(VInteger)); +        vtBoolean:    Add(BoolStrings[VBoolean]); +        vtChar:       Add(VChar); +        vtPChar:      Add(VPChar); +        vtExtended:   Add(FloatToStr(VExtended^)); +        vtObject:     if VObject is TComponent then +                        Add(TComponent(VObject).Name) +                      else +                        Add(VObject.ClassName); +        vtClass:      Add(VClass.ClassName); +        vtAnsiString: Add(string(VAnsiString)); +        vtCurrency:   Add(CurrToStr(VCurrency^)); +        vtInt64:      Add(IntToStr(VInt64^)); +        vtVariant:    Add(string(VVariant^)); + +        vtWideChar:   Add(VWideChar); +        vtPWideChar:  Add(VPWideChar); +        vtInterface:  Add(StrOfP(VInterface)); +        vtPointer:    Add(StrOfP(VPointer)); +        vtWideString: Add(WideString(VWideString)); +      end; +  if Result <> '' then +    SetLength(result, Length(Result) - Length(Separator)); +end; + +procedure ShowText(const Items: array of const; Separator: string = ''); +var +  Text: string; +begin +  Text := MakeStr(Items, Separator); + +  MessageBox(0, PChar(Text), 'Info', MB_OK and MB_APPLMODAL); +end; + +function DeleteChars(const S: string; C: Char): string; +var +  i: Integer; +begin +  Result := ''; +  for i := 1 to Length(S) do +    if S[i] <> C then +      Result := Result + S[i]; +end; + +function DeleteChars(const S: string; C: TCharSet): string; +var +  i: Integer; +begin +  Result := ''; +  for i := 1 to Length(S) do +    if not (S[i] in C) then +      Result := Result + S[i]; +end; + +function ExtractChars(const S: string; C: TCharSet): string; +var +  i: Integer; +begin +  Result := ''; +  for i := 1 to Length(S) do +    if S[i] in C then +      Result := Result + S[i]; +end; + +function CharCount(const S: string; C: Char): Integer; +var +  i: Integer; +begin +  Result := 0; +  for i := 1 to Length(S) do +    if S[i] = C then +      Inc(Result); +end; + +function StrAtPos(const S: string; Pos: Integer; const Str: string): Boolean; +begin +  Result := (Str <> '') and (Str = Copy(S, Pos, Length(Str))); +end; + +function TextAtPos(const S: string; Pos: Integer; const Text: string): Boolean; +begin +  Result := (Text <> '') and SameText(Text, Copy(S, Pos, Length(Text))); +end; + +function StrAtBegin(const S, Str: string): Boolean; +begin +  Result := StrAtPos(S, 1, Str); +end; + +function TextAtBegin(const S, Text: string): Boolean; +begin +  Result := TextAtPos(S, 1, Text); +end; + +function CharIn(const S: string; C: Char): Boolean; +var +  i: Integer; +begin +  Result := True; +  for i := 1 to Length(S) do +    if S[i] = C then Exit; +  Result := False; +end; + +function CharIn(const S: string; C: TCharSet): Boolean; +var +  i: Integer; +begin +  Result := False; +  for i := 1 to Length(S) do begin +    Result := S[i] in C; +    if Result then +      Exit; +  end; +end; + +function StrIn(const S, SubStr: string): Boolean; +begin +  Result := PosEx(SubStr, S) > 0; +end; + +function StrIn(SL: TStrings; const S: string): Boolean; +var +  i: Integer; +begin +  Result := False; +  for i := 0 to SL.Count-1 do begin +    Result := (S = SL[i]); +    if Result then +      Exit; +  end; +end; + +function StrIn(A: TStrA; const S: string): Boolean; +var +  i: Integer; +begin +  Result := False; +  for i := Low(A) to High(A) do begin +    Result := (S = A[i]); +    if Result then +      Exit; +  end; +end; + +function TextIn(const S, Text: string): Boolean; +begin +  Result := PosExText(Text, S) > 0; +end; + +function TextIn(SL: TStrings; const Text: string): Boolean; +var +  i: Integer; +begin +  Result := False; +  for i := 0 to SL.Count-1 do begin +    Result := SameText(Text, SL[i]); +    if Result then +      Exit; +  end; +end; + +function TextIn(A: TStrA; const Text: string): Boolean; +var +  i: Integer; +begin +  Result := False; +  for i := Low(A) to High(A) do begin +    Result := SameText(Text, A[i]); +    if Result then +      Exit; +  end; +end; + +function StrIndex(SL: TStrings; const S: string): Integer; +begin +  for Result := 0 to SL.Count-1 do +    if S = SL[Result] then +      Exit; +  Result := -1; +end; + +function StrIndex(A: TStrA; const S: string): Integer; +begin +  for Result := Low(A) to High(A) do +    if S = A[Result] then +      Exit; +  Result := -1; +end; + +function TextIndex(SL: TStrings; const Text: string): Integer; +begin +  for Result := 0 to SL.Count-1 do +    if SameText(Text, SL[Result]) then +      Exit; +  Result := -1; +end; + +function TextIndex(A: TStrA; const Text: string): Integer; +begin +  for Result := Low(A) to High(A) do +    if SameText(Text, A[Result]) then +      Exit; +  Result := -1; +end; + +function ReplaceChars(const S: string; Old, New: Char): string; +var +  i: Integer; +begin +  Result := S; +  for i := 1 to Length(Result) do +    if Result[i] = Old then +      Result[i] := New; +end; + +function ReplaceChars(const S: string; Old: TCharSet; New: Char): string; +var +  i: Integer; +begin +  Result := S; +  for i := 1 to Length(Result) do +    if Result[i] in Old then +      Result[i] := New; +end; + +function Replace(const S, Old, New: string): string; +var +  oldp, ps: Integer; +begin +  ps := 1; +  Result := ''; +  while True do begin +    oldp := ps; +    ps := PosEx(Old, S, oldp); +    if ps = 0 then begin +      Result := Result + Copy(S, oldp, Length(S) - oldp + 1); +    Exit; end; +    Result := Result + Copy(S, oldp, ps - oldp) + New; +    Inc(ps, Length(Old)); +  end; +end; + +function SLOfFile(const FileName: string): TStringList; +begin +  Result := TStringList.Create; +  if FileExists(FileName) then +    Result.LoadFromFile(FileName); +end; + +function ContainsEmptyLines(SL: TStrings): Boolean; +begin +  Result := StrIn(SL, ''); +end; + +procedure DeleteEmptyLines(SL: TStrings); +var +  i: Integer; +begin +  i := 0; +  while i < SL.Count do begin +    if SL[i] = '' then +      SL.Delete(i) +    else +      Inc(i); +  end; +end; + +procedure DeleteCommentLines(SL: TStrings; const CommentSign: string = '//'); +var +  i: Integer; +begin +  i := 0; +  while i < SL.Count do begin +    if (SL[i] = '') or (StrAtBegin(TrimLeft(SL[i]), CommentSign)) then +      SL.Delete(i) +    else +      Inc(i); +  end; +end; + +function FindLine(SL: TStrings; const S: string): Integer; +begin +  for Result := 0 to SL.Count-1 do +    if TextAtBegin(SL[Result], S) then +      Exit; +  Result := -1; +end; + +procedure QuickSortSL(SL: TStringList); + +  procedure Sort(l, r: Integer); +  var +    i,j: Integer; +    z,x: string; +  begin +    i := l; +    j := r; +    x := SL[(j + i) div 2]; +    repeat +      while SL[i] < x do Inc(i); +      while SL[j] > x do Dec(j); +      if i <= j then begin +        z := SL[i]; +        SL[i] := SL[j]; +        SL[j] := z; +        Inc(i); Dec(j); +      end; +    until i > j; +    if j > l then Sort(l, j); +    if i < r then Sort(i, r); +  end; + +begin +  if SL.Count > 0 then +    Sort(0, SL.Count-1); +end; + +function IncStrA(StrA: TStrA): Integer; +begin +  SetLength(StrA, Length(StrA) + 1); +  Result := High(StrA); +end; + +function StrOfByteA(a: TByteA): string; +begin +  Result := string(Copy(a, 0, Length(a))); +end; + +function ByteAOfStr(const S: string): TByteA; +begin +  Result := TByteA(Copy(S, 1, Length(s))); +end; + +function ByteAOfInt(i: Integer): TByteA; +begin +  SetLength(Result, SizeOf(Integer)); +  Move(i, Pointer(Result)^, SizeOf(Integer)); +end; + +function IntOfByteA(A: TByteA): Integer; +begin +  Result := 0; +  Move(Pointer(A)^, Result, Min(Length(A), SizeOf(Integer))); +end; + +function ByteAOfHex(const Hex: string): TByteA; +var +  i: Integer; +  h: string; +begin +  h := ExtractChars(Hex, HexadecimalChars); +  SetLength(Result, Length(h) div 2); +  for i := 0 to High(Result) do +    Result[i] := ByteOfHex(Copy(h, (i shl 1) + 1, 2)); +end; + +function SizeOfFile(const FileName: string): Integer; +var +  F: file; +begin +  AssignFile(F, FileName); +  {$I-}Reset(F, 1);{$I+} +  if IOResult = 0 then begin +    Result := FileSize(F); +    CloseFile(F); +  end else +    Result := 0; +end; + +function FileEx(const FileName: string; AllowFolders: Boolean = False): Boolean; +var +  FindData: TWin32FindData; +begin +  if FileName = '' then begin +    Result := False; +  Exit; end; + +  Result := (AllowFolders and DirectoryExists(FileName)) or +    (FindFirstFile(PChar(FileName), FindData) <> INVALID_HANDLE_VALUE); +  Result := Result and not CharIn(FileName, WildCards); +  Result := Result and (AllowFolders +    or ((FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0)); +end; + +function LWPSolve(const Dir: string): string; +begin +  if (Dir <> '') and (Dir[Length(Dir)] = '\') then begin +    Result := Copy(Dir, 1, Length(Dir) - 1); +  end else +    Result := Dir; +end; + +function LWPSlash(const Dir: string): string; +begin +  if (Dir <> '') and (Dir[Length(Dir)] = '\') then begin +    Result := Copy(Dir, 1, Length(Dir)); +  end else +    Result := Dir + '\'; +end; + +function ExtractDrive(const FileName: string): string; +begin +  Result := ''; +  if (Length(FileName) >= 2) and (FileName[2] = ':') then +    Result := UpperCase(FileName[1] + ':\'); +end; + +function ExtractPath(const FileName: string): string; +var +  p: Integer; +begin +  p := CharPosR('\', FileName); +  if P > 0 then +    Result := Copy(FileName, 1, p) +  else +    Result := FileName; +end; + +function ExtractPrefix(const FileName: string): string; +begin +  Result := UntilLastChar(ExtractFileName(FileName), '.'); +end; + +function ExtractSuffix(const FileName: string): string; +begin +  Result := FromLastChar(ExtractFileName(FileName), '.'); +end; + +function SameByteA(const A, B: TByteA): Boolean; +begin +  Result := (A = B) or ((Length(A) = Length(B)) and CompareMem(A, B, Length(A))); +end; + +function Reverse(A: TByteA): TByteA; +var +  i: Integer; +begin +  SetLength(Result, Length(A)); + +  for i := 0 to High(A) do +    Result[High(Result) - i] := A[i]; +end; + +function Endian(i: Integer): Integer; +type +  EndianArray = packed array[0..3] of Byte; +var +  a, b: EndianArray; +begin +  a := EndianArray(i); +  b[0] := a[3]; +  b[1] := a[2]; +  b[2] := a[1]; +  b[3] := a[0]; +  Result := Integer(b); +end; + +function SaveByteA(Data: TByteA; const FileName: string; +  Overwrite: Boolean = True): Boolean; +var +  F: file; +begin +  if FileExists(FileName) and not Overwrite then begin +    Result := False; +  Exit end; + +  AssignFile(F, FileName); +  {$I-}Rewrite(F, 1);{$I+} +  if IOResult = 0 then begin +    if Length(Data) > 0 then +      BlockWrite(F, Data[0], Length(Data)); +    CloseFile(F); +    Result := True; +  end else +    Result := False; +end; + +function LoadByteA(const FileName: string): TByteA; +var +  F: file; +begin +  AssignFile(F, FileName); +  {$I-}Reset(F, 1);{$I+} +  if IOResult = 0 then begin +    SetLength(Result, FileSize(F)); +    if Length(Result) > 0 then +      BlockRead(F, Result[0], FileSize(F)); +    CloseFile(F); +  end else +    SetLength(Result, 0); +end; + +function IsValidFileName(const FileName: string): Boolean; +begin +  Result := (FileName <> '') and not CharIn(FileName, FileNameEnemies) +    and CharIn(Trim(FileName), AllChars - ['.']); +end; + +function MakeValidFileName(FileName: string; const Default: string = 'File'): string; +begin +  if FileName = '' then +    FileName := Default; + +  if CharIn(FileName, FileNameEnemies) then +    Result := ReplaceChars(FileName, FileNameEnemies, '_') +  else if not CharIn(Trim(FileName), AllChars - ['.']) then +    Result := Default +  else +    Result := FileName; +end; + +function IsValidInteger(const S: string): Boolean; +{const +  LowInt = '2147483648'; +  HighInt = '2147483647'; +var +  len, RealLen, i, o: Integer; +  c: Char; +begin +  Result := False; +  if S = '' then +    Exit; + +  len := Length(S); +  o := 1; +   +  if S[1] = '-' then begin +    if len = 1 then +      Exit; +    Inc(o); +    while (o <= len) and (S[o] = '0') do +      Inc(o); +    if o > len then +      Exit; +    if o < len then begin +      RealLen := len - o + 1; +      if RealLen > Length(LowInt) then +        Exit +      else if RealLen = Length(LowInt) then begin +        for i := 1 to Length(LowInt) do begin +          c := S[i + o - 1]; +          if (c < '0') or (c > LowInt[i]) then +            Exit; +          if c in ['0'..Char((Byte(LowInt[i])-1))] then +            Break; +        end; +        Inc(o, i); +      end; +    end; +  end else begin +    while (o <= len) and (S[o] = '0') do +      Inc(o); +    if o <= len then begin +      RealLen := len - o + 1; +      if RealLen > Length(HighInt) then +        Exit +      else if RealLen = Length(HighInt) then begin +        for i := 1 to Length(HighInt) do begin +          c := S[i + o - 1]; +          if (c < '0') or (c > HighInt[i]) then +            Exit; +          if c in ['0'..Char((Byte(HighInt[i])-1))] then +            Break; +        end; +        Inc(o, i); +      end; +    end; +  end; + +  for i := o to len do +    if not (S[i] in ['0'..'9']) then +      Exit; + +  Result := True;  } +var +  i: Int64; +begin +  i := StrToInt64Def(S, High(Int64)); +  Result := (i >= Low(Integer)) and (i <= High(Integer)); +end; + +function IsValidCardinal(const S: string): Boolean; +{const +  HighCard = '4294967295'; +var +  len, RealLen, i, o: Integer; +begin +  Result := False; +  if S = '' then +    Exit; + +  len := Length(S); +  o := 1; +   +  while (o <= len) and (S[o] = '0') do +    Inc(o); +  if o <= len then begin +    RealLen := len - o + 1; +    if RealLen > Length(HighCard) then +      Exit +    else if RealLen = Length(HighCard) then begin +      for i := 1 to Length(HighCard) do begin +        if S[i + o - 1] > HighCard[i] then +          Exit; +        if S[i + o - 1] in ['0'..Char((Byte(HighCard[i])-1))] then +          Break; +      end; +      Inc(o, i); +    end; +  end; + +  for i := o to len do +    if not (S[i] in ['0'..'9']) then +      Exit; + +  Result := True;  } +var +  i: Int64; +begin +  i := StrToInt64Def(S, -1); +  Result := (i >= 0) and (i <= High(Cardinal)); +end; + +function StrOfBool(flag: Boolean; const TrueStr: string = 'True'; +  const FalseStr: string = 'False'): string; +begin +  if Flag then +    Result := TrueStr +  else +    Result := FalseStr; +end; + +function StrOfInt(i: Integer): string; +begin +{  if i = 0 then begin +    Result := '0'; +  Exit end; + +  while i > 0 do begin +    Result := Char(Byte('0') + (i mod 10)) + Result; +    i := i div 10; +  end;} +  Result := IntToStr(i); +end; + +function CardOfStr(const S: string): Cardinal; +var +  Res: Int64; +begin +  Res := StrToInt64Def(S, -1); +  if Res > High(Cardinal) then +    Res := High(Cardinal) +  else if Res < 0 then +    Res := 0; +  Result := Cardinal(Res); +end; + +function HexOrd(Hex: Char): THex; +begin +  case Hex of +    '0'..'9': +      Result := Byte(Hex) - 48; +    'A'..'F': +      Result := Byte(Hex) - 55; +    'a'..'f': +      Result := Byte(Hex) - 87; +    else +      Result := 0; +  end; +end; + +function ByteOfHex(Hex: THexByteStr): Byte; +begin +  Result := (HexOrd(Hex[1]) shl 4) + HexOrd(Hex[2]); +end; + +function DecOfHex(const Hex: string): string; +begin +  Result := IntToStr(CardOfHex(Hex)); +end; + +function HexOfByte(b: Byte): THexByteStr; +begin +  Result := HexChar[(b and $F0) shr 4] +          + HexChar[ b and $0F       ]; +end; + +{function HexOfCard2(c: Cardinal): string; +var +  Data: array[0..(1 shl 4) - 1] of Char; +  i: Integer; +begin +  for i := 0 to (1 shl 4) - 1 do +    if i < 10 then +      Data[i] := Char(Ord('0') + i) +    else +      Data[i] := Char(Ord('A') + i - 10); + +  Result := Data[(c and (((1 shl (1 shl 2)) - 1) shl (7 shl 2))) shr (7 shl 2)] +          + Data[(c and (((1 shl (1 shl 2)) - 1) shl (6 shl 2))) shr (6 shl 2)] +          + Data[(c and (((1 shl (1 shl 2)) - 1) shl (5 shl 2))) shr (5 shl 2)] +          + Data[(c and (((1 shl (1 shl 2)) - 1) shl (4 shl 2))) shr (4 shl 2)] +          + Data[(c and (((1 shl (1 shl 2)) - 1) shl (3 shl 2))) shr (3 shl 2)] +          + Data[(c and (((1 shl (1 shl 2)) - 1) shl (2 shl 2))) shr (2 shl 2)] +          + Data[(c and (((1 shl (1 shl 2)) - 1) shl (1 shl 2))) shr (1 shl 2)] +          + Data[(c and (((1 shl (1 shl 2)) - 1) shl (0 shl 2))) shr (0 shl 2)]; +end; } + +function HexOfCard(i: Cardinal): string; +var +  a: Cardinal; +begin +  Result := ''; +  while i > 0 do begin +    a := i and $F; +    Result := HexChar[a] + Result; +    i := i shr 4; +  end; +end; + +function HexOfCard(i: Cardinal; Digits: Integer): string; +var +  a: Cardinal; +begin +  Result := ''; +  while i > 0 do begin +    a := i and $F; +    Result := HexChar[a] + Result; +    i := i shr 4; +  end; +  Result := MulStr('0', Digits - Length(Result)) + Result; +end; + +function PascalHexArray(a: TByteA; Name: string): string; +var +  i, len: Integer; +begin +  Result := 'const' + EOL + +    '  ' + Name + ': array[0..' + IntToStr(High(a)) + '] of Byte = ('; + +  len := Length(a); +  for i := 0 to len-1 do begin +    if (i mod 19) = 0 then +      Result := Result + EOL + '  ' + '  '; +    Result := Result + '$' + HexOfByte(a[i]); +    if i < len-1 then +      Result := Result + ','; +  end; +  Result := Result + EOL + '  );'; +end; + +function HexOfByteA(a: TByteA; Blocks: Integer = 1; +  const Splitter: string = ' '): string; +var +  i: Integer; +begin +  Result := ''; + +  if Blocks > 0 then +    for i := 0 to High(a) do begin +      Result := Result + HexOfByte(a[i]); +      if i < High(a) then +        if ((i+1) mod Blocks) = 0 then +          Result := Result + Splitter; +    end +  else +    for i := 0 to High(a) do +      Result := Result + HexOfByte(a[i]); +end; + +function BinOfByteA(a: TByteA; Blocks: Integer = 4; +  const Splitter: string = ' '): string; +var +  i, max: Integer; +  Bit: Boolean; +begin +  Result := ''; + +  if Blocks > 0 then begin +    max := 8 * (High(a)) + 7; +    for i := 0 to max do begin +      Bit := 7-(i mod 8) in TBitSet(a[i div 8]); +      Result := Result + Char(Byte('0') + Byte(Bit)); +      if i < max then +        if ((i+1) mod Blocks) = 0 then +          Result := Result + Splitter; +    end; +  end else +    for i := 0 to High(a) do +      Result := Result + Char(Byte('0') + a[i] shr (i and 8)); +end; + +function CardOfHex(Hex: string): Cardinal; +var +  i: Integer; +begin +  Result := 0; +  Hex := Copy(ExtractChars(Hex, HexadecimalChars), 1, 8); + +  for i := 1 to Length(Hex) do +    if Hex[i] <> '0' then +      Inc(Result, HexOrd(Hex[i]) shl ((Length(Hex) - i) shl 2)); +end; + +function IntOfBin(Bin: string): Cardinal; +var +  i: Integer; +begin +  Result := 0; +  Bin := Copy(ExtractChars(Bin, BinaryChars), 1, 32); + +  for i := Length(Bin) downto 1 do +    if Bin[i] = '1' then +      Inc(Result, 1 shl (Length(Bin) - i)); +end; + +function BinOfInt(n: Cardinal): string; +var +  a: Integer; +begin +  if n = 0 then begin +    Result := '0'; +  exit; end; + +  Result := ''; +  while n > 0 do begin +    a := n and 1; +    Result := Char(a + Byte('0')) + Result; +    n := n shr 1; +  end; +end; + +function BinOfIntFill(n: Cardinal; MinCount: Integer = 8): string; +var +  a: Integer; +begin +  if n = 0 then begin +    Result := MulStr('0', MinCount); +  Exit; end; + +  Result := ''; +  while n > 0 do begin +    a := n and 1; +    Result := Char(a + Byte('0')) + Result; +    n := n shr 1; +  end; +  Result := MulStr('0', MinCount - Length(Result)) + Result; +end; + +function BaseNOfInt(I: Cardinal; B: TBaseN): string; +var +  a: Integer; +begin +  if (B < 2) or (i = 0) then begin +    Result := '0'; +  Exit; end; + +  Result := ''; +  while i > 0 do begin +    a := i mod B; +    Result := BaseNChar[a] + Result; +    i := i div B; +  end; +end; + +function IntOfBaseN(V: string; B: TBaseN): Cardinal; +var +  i: Integer; +  F: Cardinal; +  c: Byte; +begin +  Result := 0; +  V := TrimAll(V); +  F := 1; +  for i := Length(V) downto 1 do begin +    c := Byte(UpCase(V[i])); +    case Char(c) of +      '0'..'9': c := c - 48; +      'A'..'Z': c := c - 55; +    end; +    if c < B then +      Result := Result + Byte(c) * F; +    F := F * B; +  end; +end; + +function KeepIn(i, Bottom, Top: Variant): Variant; +begin +  Result := i; +  if Result > Top then +    Result := Top +  else if Result < Bottom then +    Result := Bottom; +end; + +function InRange(Value, Bottom, Top: Variant): Boolean; +begin +  Result := (Value >= Bottom) and (Value <= Top); +end; + +function InStrictRange(Value, Bottom, Top: Variant): Boolean; +begin +  Result := (Value > Bottom) and (Value < Top); +end; + +function Min(const A, B: Integer): Integer; +begin +  if A < B then +    Result := A +  else +    Result := B; +end; + +function Min(const A: TIntA): Integer; +var +  i: Integer; +begin +  Result := 0; +  if Length(A) = 0 then +    Exit; + +  Result := A[0]; +  for i := 1 to High(A) do +    if A[i] < Result then +      Result := A[i]; +end; + +function Max(const A, B: Integer): Integer; +begin +  if A > B then +    Result := A +  else +    Result := B; +end; + +function Max(const A: TIntA): Integer; +var +  i: Integer; +begin +  Result := 0; +  if Length(A) = 0 then +    Exit; + +  Result := A[0]; +  for i := 1 to High(A) do +    if A[i] > Result then +      Result := A[i]; +end; + +function RangesOfStr(const S: string): TRanges; +var +  SL: TStringList; +  r, b, t: string; +  i, p: Integer; + +  function TryStrToCard(const S: string; out Value: Cardinal): Boolean; +  var +    E: Integer; +  begin +    Val(S, Value, E); +    Result := E = 0; +  end; + +begin +  Result := nil; +  SL := TStringList.Create; +  try +    Split(S, RangesSeparator, SL); +    SetLength(Result, SL.Count); +    for i := 0 to SL.Count-1 do begin +      r := SL[i]; +      with Result[i] do begin +        p := CharPos(RangeInnerSeparator, r); +        Simple := p = 0; // no '-' found +        if Simple then begin +          if r = RangeInfinite then begin // * --> *-* +            Simple := False; +            Bottom := Low(Bottom); +            Top := High(Top); +          end else if not TryStrToCard(r, Value) then +            Break; + +        end else begin +          TileStr(r, p, p, b, t); + +          if b = RangeInfinite then +            Bottom := Low(Bottom) +          else if not TryStrToCard(b, Bottom) then +            Break; + +          if t = RangeInfinite then +            Top := High(Top) +          else if not TryStrToCard(t, Top) then +            Break; +          if Bottom > Top then begin +            p := Bottom; Bottom := Top; Top := p; +          end; +        end; +      end; +    end; + +    if i <> SL.Count then +      Result := nil; + +  finally +    SL.Free; +  end; +end; + +function InRanges(Ranges: TRanges; TestValue: Cardinal): Boolean; +var +  i: Integer; +begin +  Result := True; + +  for i := 0 to High(Ranges) do +    with Ranges[i] do +      if Simple then begin +        if TestValue = Value then +          Exit; +      end else begin +        if InRange(TestValue, Bottom, Top) then +          Exit; +      end; + +  Result := False; +end; + +procedure WriteSL(Strings: TStrings; const Prefix: string = ''; +  const Suffix: string = ''); +var +  i: Integer; +begin +  for i := 0 to Strings.Count-1 do +    WriteLn(Prefix + Strings[i] + Suffix); +end; + +function Success(Res: Integer; ResultOnSuccess: Integer = ERROR_SUCCESS): Boolean; +begin +  Result := (Res = ResultOnSuccess); +  LastSuccessRes := Res; +end; + +function Failure(Res: Integer; ResultOnSuccess: Integer = ERROR_SUCCESS): Boolean; +begin +  Result := not Success(Res, ResultOnSuccess); +end; + +function ExpandString(const S: string): string; +var +  Len: Integer; +  P, Res: PChar; +begin +  Result := ''; +  P := PChar(S); +  Len := ExpandEnvironmentStrings(P, nil, 0); +  if Len = 0 then +    Exit; + +  GetMem(Res, Len); +  ExpandEnvironmentStrings(P, Res, Len); + +  Result := Res; +  FreeMem(Res, Len); +end; + +function FindAll(Strings: TStrings; const Mask: string; +  ScanSubDirs: Boolean = True; Attributes: Integer = faFindEveryFile; +  FileReturn: TFileNameFunc = nil): Boolean; +var +  Path, FileName: string; + +  procedure ScanDir(const Path, FileName: string); +  var +    PSR: TSearchRec; +    Res: Integer; + +    procedure Add(const S: string); +    begin +      if S <> '' then +        Strings.Add(S); +    end; + +  begin +    Res := FindFirst(Path + FileName, Attributes, PSR); +    while Success(Res, 0) do begin +      if Assigned(FileReturn) then +        Add(FileReturn(Path + PSR.Name)) +      else +        Add(Path + PSR.Name); +      Res := FindNext(PSR); +    end; +    FindClose(PSR); +    if not ScanSubDirs then +      Exit; + +    Res := FindFirst(Path + '*', faDirectory, PSR); +    while Success(Res, 0) do begin +      if (PSR.Attr and faDirectory > 0) +       and (PSR.Name <> '.') and (PSR.Name <> '..') then +        ScanDir(Path + PSR.Name + '\', FileName); +      Res := FindNext(PSR); +    end; +    FindClose(PSR); +  end; + +begin +  Strings.Clear; +  Path := ExtractPath(Mask); +  FileName := ExtractFileName(Mask); +  ScanDir(Path, FileName); +  Result := Strings.Count > 0; +end; + +function FindAllFirst(const Mask: string; ScanSubDirs: Boolean = True; +  Attributes: Integer = faFindEveryFile): string; +var +  Path, FileName: string; + +  function ScanDir(const Path, FileName: string): Boolean; +  var +    PSR: TSearchRec; +    Res: Integer; +  begin +    Result := False; +    if Success(FindFirst(Path + FileName, Attributes, PSR), 0) then begin +      FindAllFirst := Path + PSR.Name; +      Result := True; +      FindClose(PSR); +    Exit; end; +    if not ScanSubDirs then +      Exit; + +    Res := FindFirst(Path + '*', faDirectory, PSR); +    while not Result and Success(Res, 0) do begin +      if (PSR.Attr and faDirectory > 0) +       and (PSR.Name <> '.') and (PSR.Name <> '..') then +        Result := ScanDir(Path + PSR.Name + '\', FileName); +      Res := FindNext(PSR); +    end; +    FindClose(PSR); +  end; +begin +  Result := ''; +  Path := ExtractPath(Mask); +  FileName := ExtractFileName(Mask); +  ScanDir(Path, FileName); +end; + +procedure DeleteFiles(const Mask: string; ScanSubDirs: Boolean = True; +  Attributes: Integer = faFindEveryFile); +var +  Path, FileName: string; + +  procedure ScanDir(const Path, FileName: string); +  var +    PSR: TSearchRec; +    Res: Integer; + +    procedure TryDeleteFile(const FileName: string); +    begin +      try +        DeleteFile(Path + PSR.Name); +      except +      end; +    end; + +  begin +    Res := FindFirst(Path + FileName, Attributes, PSR); +    while Success(Res, 0) do begin +      TryDeleteFile(Path + PSR.Name); +      Res := FindNext(PSR); +    end; +    FindClose(PSR); +    if not ScanSubDirs then +      Exit; + +    Res := FindFirst(Path + '*', faDirectory, PSR); +    while Success(Res, 0) do begin +      if (PSR.Attr and faDirectory > 0) +       and (PSR.Name <> '.') and (PSR.Name <> '..') then begin +        ScanDir(Path + PSR.Name + '\', FileName); +        TryDeleteFile(Path + PSR.Name); +      end; +      Res := FindNext(PSR); +    end; +    FindClose(PSR); +  end; +begin +  Path := ExtractPath(Mask); +  FileName := ExtractFileName(Mask); +  ScanDir(Path, FileName); +end; + +function GetFileNew(FileName: string; NoFloppyDrives: Boolean = True): string; +var +  Drive: string; +  pf, pd, Len: Integer; +  PSR: TSearchRec; +begin +  Result := ''; +  FileName := Trim(FileName); +  if Length(FileName) < 2 then +    Exit; + +  Drive := ExtractDrive(FileName); +  if not DirectoryExists(Drive) then +    Exit; + +  if NoFloppyDrives and (Drive[1] in ['A', 'B']) then +    Exit; + +  Len := Length(FileName); +  Result := Drive; +  pf := Length(Drive) + 1; +  while pf <= Len do begin +    if FileName[pf] = '\' then begin +      Result := Result + '\'; +      Inc(pf); +    Continue; end; + +    pd := CharPos('\', FileName, pf); +    if pd = 0 then begin +      if 0=FindFirst(Result + Copy(FileName, pf, MaxInt), faFindEveryFile, PSR) then begin +        Result := Result + PSR.Name; +      Break; end else begin +        FindClose(PSR); +        if 0=FindFirst(Result + Copy(FileName, pf, MaxInt), faDirectory, PSR) then +          Result := Result + PSR.Name + '\' +        else +          Result := ''; +        FindClose(PSR); +        if Result = '' then +          Break; +      end; +    end; + +    if 0=FindFirst(Result + Copy(FileName, pf, pd - pf), faDirectory, PSR) then +      Result := Result + PSR.Name + '\' +    else +      Result := ''; +    FindClose(PSR); +    if Result = '' then +      Break; + +    pf := pd + 1; +  end; + +  if (Result <> '') and not FileEx(Result, True) then +    Result := ''; +end; + +function DateTimeOfFileTime(const FileTime: TFileTime): TDateTime; +var +  LocalFileTime: TFileTime; +  Res: Integer; +begin +  Result := 0; + +  FileTimeToLocalFileTime(FileTime, LocalFileTime); +  if not FileTimeToDosDateTime(LocalFileTime, LongRec(Res).Hi, +   LongRec(Res).Lo) then +    Res := -1; + +  if (Res = -1) or (Res = 0) then +    Exit; +  try +    Result := FileDateToDateTime(Res); +  except +  end; +end; + +procedure FileNew(const FileName: string); +var +  Handle: Integer; +begin +  Handle := FileCreate(FileName); +  FileClose(Handle); +end; + +function Win32PlatformStr: string; +const +  PlatformStrings: array[VER_PLATFORM_WIN32s..VER_PLATFORM_WIN32_NT] of string = +    ('VER_PLATFORM_WIN32s', 'VER_PLATFORM_WIN32_WINDOWS', 'VER_PLATFORM_WIN32_NT'); +begin +  Result := PlatformStrings[Win32Platform]; +end; + +function FullOSInfo: string; +begin +  Result := Format( +    'Platform: %s' + EOL + +    'Version: %d.%d Build %d' + EOL + +    'CSD: %s', +    [ +      Win32PlatformStr, +      Win32MajorVersion, Win32MinorVersion, Win32BuildNumber, +      Win32CSDVersion +    ] +  ); +end; + +function Win9x: Boolean; +begin +  Result := Win32Platform = VER_PLATFORM_WIN32_WINDOWS; +end; + +function WinNT: Boolean; +begin +  Result := Win32Platform = VER_PLATFORM_WIN32_NT; +end; + +function Win2000: Boolean; +begin +  Result := (Win32Platform = VER_PLATFORM_WIN32_NT) +            and (Win32MajorVersion = 4); +end; + +function WinXP: Boolean; +begin +  Result := Win32MajorVersion >= 5; +end; + +initialization +  MyDir := GetMyDir; + +end. + +unit FifoStream; + +interface + +uses Classes, windows, Dialogs; + +const +  DefaultChunksize = 32768; // 32kb per chunk as default. + +type +  PMemChunk = ^TMemChunk; +  TMemChunk = record +    Filled: Longword; +    Read: Longword; +    Data: pointer; +  end; + +  TFifo = class +  private +    FBuffers: TList; +    FChunksize: Longword; +    FCritSect: TRTLCriticalSection; +    FIsWinNT: boolean; +    FBytesInFifo: LongWord; +  protected +    function GetBytesInFifo: LongWord; +  public +    constructor Create; +    destructor Destroy; override; +    procedure Write(Data: pointer; Size: LongWord); +    procedure Read(Buff: pointer; var ReqSize: LongWord); +    procedure PeekData(Buff: pointer; var ReqSize: LongWord); +  published +    property BytesInFifo: LongWord read FBytesInFifo; +  end; + +implementation + +constructor TFifo.Create; +begin +  inherited; +  FBuffers := TList.Create; +  // set default chunksize... +  FChunksize := DefaultChunksize; +  InitializeCriticalSection(FCritSect); +end; + +destructor TFifo.Destroy; +var +  I: Integer; +begin +  EnterCriticalSection(FCritSect); +  for I := 0 to FBuffers.count - 1 do +  begin +    FreeMem(PMemChunk(Fbuffers[I]).Data); +    Dispose(PMemChunk(Fbuffers[I])); +  end; +  FBuffers.Clear; +  FBuffers.Free; +  LeaveCriticalSection(FCritSect); + +  DeleteCriticalSection(FCritSect); +  inherited; +end; + +function TFifo.GetBytesInFifo: LongWord; +begin +  Result := 0; +  if FBuffers.Count = 0 then +  begin +    exit; +  end +  else +  begin +    if FBuffers.Count > 1 then +      Inc(Result, (FBuffers.Count - 1) * FChunkSize); +    Inc(Result, PMemChunk(FBuffers[Fbuffers.Count - 1]).Filled); +    Dec(Result, PMemChunk(FBuffers[0]).Read); +  end; +end; + +procedure TFifo.Write(Data: pointer; Size: LongWord); +var +  Privpointer: pointer; +  PrivSize: LongWord; +  Chunk: PMemChunk; +  PosInChunk: pointer; +begin +  if LongWord(Data) = 0 then +  begin +    // null pointer? somebody is trying to fool us, get out... +    Exit; +  end; +  EnterCriticalSection(FCritSect); +  PrivPointer := Data; +  PrivSize := 0; +  // are already buffers there? +  if FBuffers.count > 0 then +  begin +    // is the last one of them not completely filled? +    if PMemChunk(FBuffers[FBuffers.count - 1]).filled < FChunksize then +      // not completely filled, so fill up the buffer. +    begin +      Chunk := PMemChunk(FBuffers[FBuffers.count - 1]); +      // fetch chunkdata. +      PosInChunk := Chunk.Data; +      // move to current fill pos... +      Inc(LongWord(PosInChunk), Chunk.Filled); +      // can we fill the chunk completely? +      if Size > FChunksize - Chunk.Filled then +      begin +        // yes we can. +        Move(PrivPointer^, PosInChunk^, FChunksize - Chunk.Filled); +        Inc(PrivSize, FChunksize - Chunk.Filled); +        Inc(LongWord(PrivPointer), FChunksize - Chunk.Filled); +        Chunk.Filled := FChunkSize; +      end +      else +        // we have to less data for filling the chunk completely, +        // just put everything in. +      begin +        Move(PrivPointer^, PosInChunk^, Size); +        Inc(PrivSize, Size); +        Inc(Chunk.Filled, Size); +      end; +    end; +  end; +  // as long as we have remaining stuff put it into new chunks. +  while (PrivSize < Size) do +  begin +    new(Chunk); +    GetMem(Chunk.Data, FChunksize); +    Chunk.Read := 0; +    // can we fill an entire chunk with the remaining data? +    if Privsize + FChunksize < Size then +    begin +      // yes we can, so put the stuff in. +      Move(Privpointer^, Chunk.Data^, FChunksize); +      Inc(LongWord(PrivPointer), FChunksize); +      Inc(PrivSize, FChunksize); +      Chunk.Filled := FChunksize; +    end +    else // we have to less data to fill the entire chunk, just put the remaining stuff in. +    begin +      Move(Privpointer^, Chunk.Data^, Size - Privsize); +      Chunk.Filled := Size - Privsize; +      Inc(PrivSize, Size - Privsize); +    end; +    Fbuffers.Add(Chunk); +  end; +  if Size <> Privsize then +    Showmessage('miscalculation in TFifo.write'); +  FBytesInFifo := GetBytesInFifo; +  LeaveCriticalSection(FCritSect); +end; + +procedure TFifo.Read(Buff: pointer; var ReqSize: LongWord); +var +  PrivSize: Integer; +  Privpos: pointer; +  Chunk: PMemChunk; +  ChunkPos: pointer; +begin +  if LongWord(Buff) = 0 then +  begin +    // null pointer? somebody is trying to fool us, get out... +    Exit; +  end; +  EnterCriticalSection(FCritSect); +  PrivSize := 0; +  Privpos := Buff; +  while FBuffers.Count > 0 do +  begin +    Chunk := PMemChunk(FBuffers[0]); +    ChunkPos := Chunk.data; +    Inc(LongWord(ChunkPos), Chunk.Read); +    // does the remaining part of the chunk fit into the buffer? +    if PrivSize + (Chunk.Filled - Chunk.read) < ReqSize then +    begin // yep, it fits +      Move(ChunkPos^, Privpos^, Chunk.Filled - Chunk.read); +      Inc(PrivSize, Chunk.Filled - Chunk.read); +      FreeMem(Chunk.Data); +      Dispose(Chunk); +      FBuffers.Delete(0); +    end +    else // remaining part didn't fit, get as much as we can and increment the +      // read attribute. +    begin +      Move(ChunkPos^, Privpos^, ReqSize - PrivSize); +      Inc(Chunk.read, ReqSize - PrivSize); +      Inc(PrivSize, ReqSize - PrivSize); +      // as we filled the buffer, we'll have to break here. +      break; +    end; +  end; +  FBytesInFifo := GetBytesInFifo; +  LeaveCriticalSection(FCritSect); +  ReqSize := PrivSize; +end; + +// read Data from Stream without removing it from the Stream... + +procedure TFifo.PeekData(Buff: pointer; var ReqSize: LongWord); +var +  PrivSize: Integer; +  Privpos: pointer; +  Chunk: PMemChunk; +  ChunkPos: pointer; +  ChunkNr: Integer; +begin +  if LongWord(Buff) = 0 then +  begin +    // null pointer? somebody is trying to fool us, get out... +    Exit; +  end; +  EnterCriticalSection(FCritSect); +  PrivSize := 0; +  Privpos := Buff; +  ChunkNr := 0; +  while FBuffers.Count > ChunkNr do +  begin +    Chunk := PMemChunk(FBuffers[ChunkNr]); +    ChunkPos := Chunk.data; +    Inc(LongWord(ChunkPos), Chunk.Read); +    // does the remaining part of the chunk fit into the buffer? +    if PrivSize + (Chunk.Filled - Chunk.read) < ReqSize then +    begin // yep, it fits +      Move(ChunkPos^, Privpos^, Chunk.Filled - Chunk.read); +      Inc(PrivSize, Chunk.Filled - Chunk.read); +      Inc(ChunkNr); +    end +    else // remaining part didn't fit, get as much as we can and increment the +      // read attribute. +    begin +      Move(ChunkPos^, Privpos^, ReqSize - PrivSize); +      Inc(PrivSize, ReqSize - PrivSize); +      // as we filled the buffer, we'll have to break here. +      break; +    end; +  end; +  LeaveCriticalSection(FCritSect); +  ReqSize := PrivSize; +end; + +end.  | 
