📄 jclsysutils.pas
字号:
{**************************************************************************************************}
{ }
{ Project JEDI Code Library (JCL) }
{ }
{ The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
{ you may not use this file except in compliance with the License. You may obtain a copy of the }
{ License at http://www.mozilla.org/MPL/ }
{ }
{ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
{ ANY KIND, either express or implied. See the License for the specific language governing rights }
{ and limitations under the License. }
{ }
{ The Original Code is JclSysUtils.pas. }
{ }
{ The Initial Developer of the Original Code is Marcel van Brakel. }
{ Portions created by Marcel van Brakel are Copyright (C) Marcel van Brakel. All rights reserved. }
{ }
{ Contributors: }
{ Alexander Radchenko, }
{ Andreas Hausladen (ahuser) }
{ Anthony Steele }
{ Bernhard Berger }
{ Heri Bender }
{ Jeff }
{ Jeroen Speldekamp }
{ Marcel van Brakel }
{ Peter Friese }
{ Petr Vones (pvones) }
{ Python }
{ Robert Marquardt (marquardt) }
{ Robert R. Marsh }
{ Robert Rossmair (rrossmair) }
{ Rudy Velthuis }
{ Uwe Schuster (uschuster) }
{ Wayne Sherman }
{ }
{**************************************************************************************************}
{ }
{ Description: Various pointer and class related routines. }
{ }
{**************************************************************************************************}
// Last modified: $Date: 2005/03/08 16:10:08 $
// For history see end of file
unit JclSysUtils;
{$I jcl.inc}
interface
uses
{$IFDEF MSWINDOWS}
Windows,
{$ENDIF MSWINDOWS}
Classes, TypInfo,
JclBase;
// Pointer manipulation
procedure GetAndFillMem(var P: Pointer; const Size: Integer; const Value: Byte);
procedure FreeMemAndNil(var P: Pointer);
function PCharOrNil(const S: string): PChar;
function PAnsiCharOrNil(const S: AnsiString): PAnsiChar;
{$IFDEF SUPPORTS_WIDESTRING}
function PWideCharOrNil(const W: WideString): PWideChar;
{$ENDIF SUPPORTS_WIDESTRING}
function SizeOfMem(const APointer: Pointer): Integer;
function WriteProtectedMemory(BaseAddress, Buffer: Pointer; Size: Cardinal;
out WrittenBytes: Cardinal): Boolean;
// Guards
type
ISafeGuard = interface
function ReleaseItem: Pointer;
function GetItem: Pointer;
procedure FreeItem;
property Item: Pointer read GetItem;
end;
IMultiSafeGuard = interface (IInterface)
function AddItem(Item: Pointer): Pointer;
procedure FreeItem(Index: Integer);
function GetCount: Integer;
function GetItem(Index: Integer): Pointer;
function ReleaseItem(Index: Integer): Pointer;
property Count: Integer read GetCount;
property Items[Index: Integer]: Pointer read GetItem;
end;
function Guard(Mem: Pointer; out SafeGuard: ISafeGuard): Pointer; overload;
function Guard(Obj: TObject; out SafeGuard: ISafeGuard): TObject; overload;
function Guard(Mem: Pointer; var SafeGuard: IMultiSafeGuard): Pointer; overload;
function Guard(Obj: TObject; var SafeGuard: IMultiSafeGuard): TObject; overload;
function GuardGetMem(Size: Cardinal; out SafeGuard: ISafeGuard): Pointer;
function GuardAllocMem(Size: Cardinal; out SafeGuard: ISafeGuard): Pointer;
// Binary search
function SearchSortedList(List: TList; SortFunc: TListSortCompare; Item: Pointer;
Nearest: Boolean = False): Integer;
type
TUntypedSearchCompare = function(Param: Pointer; ItemIndex: Integer; const Value): Integer;
function SearchSortedUntyped(Param: Pointer; ItemCount: Integer; SearchFunc: TUntypedSearchCompare;
const Value; Nearest: Boolean = False): Integer;
// Dynamic array sort and search routines
type
TDynArraySortCompare = function (Item1, Item2: Pointer): Integer;
procedure SortDynArray(const ArrayPtr: Pointer; ElementSize: Cardinal; SortFunc: TDynArraySortCompare);
// Usage: SortDynArray(Array, SizeOf(Array[0]), SortFunction);
function SearchDynArray(const ArrayPtr: Pointer; ElementSize: Cardinal; SortFunc: TDynArraySortCompare;
ValuePtr: Pointer; Nearest: Boolean = False): Integer;
// Usage: SearchDynArray(Array, SizeOf(Array[0]), SortFunction, @SearchedValue);
{ Various compare functions for basic types }
function DynArrayCompareByte(Item1, Item2: Pointer): Integer;
function DynArrayCompareShortInt(Item1, Item2: Pointer): Integer;
function DynArrayCompareWord(Item1, Item2: Pointer): Integer;
function DynArrayCompareSmallInt(Item1, Item2: Pointer): Integer;
function DynArrayCompareInteger(Item1, Item2: Pointer): Integer;
function DynArrayCompareCardinal(Item1, Item2: Pointer): Integer;
function DynArrayCompareInt64(Item1, Item2: Pointer): Integer;
function DynArrayCompareSingle(Item1, Item2: Pointer): Integer;
function DynArrayCompareDouble(Item1, Item2: Pointer): Integer;
function DynArrayCompareExtended(Item1, Item2: Pointer): Integer;
function DynArrayCompareFloat(Item1, Item2: Pointer): Integer;
function DynArrayCompareAnsiString(Item1, Item2: Pointer): Integer;
function DynArrayCompareAnsiText(Item1, Item2: Pointer): Integer;
function DynArrayCompareString(Item1, Item2: Pointer): Integer;
function DynArrayCompareText(Item1, Item2: Pointer): Integer;
// Object lists
procedure ClearObjectList(List: TList);
procedure FreeObjectList(var List: TList);
// Reference memory stream
type
TJclReferenceMemoryStream = class(TCustomMemoryStream)
public
constructor Create(const Ptr: Pointer; Size: Longint);
function Write(const Buffer; Count: Longint): Longint; override;
end;
// Replacement for the C ternary conditional operator ? :
function Iff(const Condition: Boolean; const TruePart, FalsePart: string): string; overload;
function Iff(const Condition: Boolean; const TruePart, FalsePart: Char): Char; overload;
function Iff(const Condition: Boolean; const TruePart, FalsePart: Byte): Byte; overload;
function Iff(const Condition: Boolean; const TruePart, FalsePart: Integer): Integer; overload;
function Iff(const Condition: Boolean; const TruePart, FalsePart: Cardinal): Cardinal; overload;
function Iff(const Condition: Boolean; const TruePart, FalsePart: Float): Float; overload;
function Iff(const Condition: Boolean; const TruePart, FalsePart: Boolean): Boolean; overload;
function Iff(const Condition: Boolean; const TruePart, FalsePart: Pointer): Pointer; overload;
function Iff(const Condition: Boolean; const TruePart, FalsePart: Int64): Int64; overload;
{$IFDEF SUPPORTS_VARIANT}
{$IFDEF COMPILER6_UP} { TODO -cFPC : Check FPC }
// because Compiler 5 can not differentiate between Variant and Byte, Integer, ... in case of overload
function Iff(const Condition: Boolean; const TruePart, FalsePart: Variant): Variant; overload;
{$ENDIF COMPILER6_UP}
{$ENDIF SUPPORTS_VARIANT}
// Classes information and manipulation
type
EJclVMTError = class(EJclError);
// Virtual Methods
{$IFNDEF FPC}
function GetVirtualMethodCount(AClass: TClass): Integer;
{$ENDIF ~FPC}
function GetVirtualMethod(AClass: TClass; const Index: Integer): Pointer;
procedure SetVirtualMethod(AClass: TClass; const Index: Integer; const Method: Pointer);
// Dynamic Methods
type
TDynamicIndexList = array [0..MaxInt div 16] of Word;
PDynamicIndexList = ^TDynamicIndexList;
TDynamicAddressList = array [0..MaxInt div 16] of Pointer;
PDynamicAddressList = ^TDynamicAddressList;
function GetDynamicMethodCount(AClass: TClass): Integer;
function GetDynamicIndexList(AClass: TClass): PDynamicIndexList;
function GetDynamicAddressList(AClass: TClass): PDynamicAddressList;
function HasDynamicMethod(AClass: TClass; Index: Integer): Boolean;
{$IFNDEF FPC}
function GetDynamicMethod(AClass: TClass; Index: Integer): Pointer;
{$ENDIF ~FPC}
{ init table methods }
function GetInitTable(AClass: TClass): PTypeInfo;
{ field table methods }
type
PFieldEntry = ^TFieldEntry;
TFieldEntry = packed record
OffSet: Integer;
IDX: Word;
Name: ShortString;
end;
PFieldClassTable = ^TFieldClassTable;
TFieldClassTable = packed record
Count: Smallint;
Classes: array [0..8191] of ^TPersistentClass;
end;
PFieldTable = ^TFieldTable;
TFieldTable = packed record
EntryCount: Word;
FieldClassTable: PFieldClassTable;
FirstEntry: TFieldEntry;
{Entries: array [1..65534] of TFieldEntry;}
end;
function GetFieldTable(AClass: TClass): PFieldTable;
{ method table }
type
PMethodEntry = ^TMethodEntry;
TMethodEntry = packed record
EntrySize: Word;
Address: Pointer;
Name: ShortString;
end;
PMethodTable = ^TMethodTable;
TMethodTable = packed record
Count: Word;
FirstEntry: TMethodEntry;
{Entries: array [1..65534] of TMethodEntry;}
end;
function GetMethodTable(AClass: TClass): PMethodTable;
function GetMethodEntry(MethodTable: PMethodTable; Index: Integer): PMethodEntry;
// Class Parent
procedure SetClassParent(AClass: TClass; NewClassParent: TClass);
function GetClassParent(AClass: TClass): TClass;
{$IFNDEF FPC}
function IsClass(Address: Pointer): Boolean;
function IsObject(Address: Pointer): Boolean;
{$ENDIF ~FPC}
// Interface information
function GetImplementorOfInterface(const I: IInterface): TObject;
// Numeric formatting routines
type
TDigitCount = 0..255;
TDigitValue = -1..35; // invalid, '0'..'9', 'A'..'Z'
TNumericSystemBase = 2..Succ(High(TDigitValue));
TJclNumericFormat = class(TObject)
private
FWantedPrecision: TDigitCount;
FPrecision: TDigitCount;
FNumberOfFractionalDigits: TDigitCount;
FExpDivision: Integer;
FDigitBlockSize: TDigitCount;
FWidth: TDigitCount;
FSignChars: array [Boolean] of Char;
FBase: TNumericSystemBase;
FFractionalPartSeparator: Char;
FDigitBlockSeparator: Char;
FShowPositiveSign: Boolean;
FPaddingChar: Char;
FMultiplier: string;
function GetDigitValue(Digit: Char): Integer;
function GetNegativeSign: Char;
function GetPositiveSign: Char;
procedure InvalidDigit(Digit: Char);
procedure SetPrecision(const Value: TDigitCount);
procedure SetBase(const Value: TNumericSystemBase);
procedure SetNegativeSign(const Value: Char);
procedure SetPositiveSign(const Value: Char);
procedure SetExpDivision(const Value: Integer);
protected
function IntToStr(const Value: Int64; out FirstDigitPos: Integer): string; overload;
function ShowSign(const Value: Float): Boolean; overload;
function ShowSign(const Value: Int64): Boolean; overload;
function SignChar(const Value: Float): Char; overload;
function SignChar(const Value: Int64): Char; overload;
property WantedPrecision: TDigitCount read FWantedPrecision;
public
constructor Create;
function Digit(DigitValue: TDigitValue): Char;
function DigitValue(Digit: Char): TDigitValue;
function IsDigit(Value: Char): Boolean;
function Sign(Value: Char): Integer;
procedure GetMantissaExp(const Value: Float; out Mantissa: string; out Exponent: Integer);
function FloatToHTML(const Value: Float): string;
function IntToStr(const Value: Int64): string; overload;
function FloatToStr(const Value: Float): string; overload;
function StrToInt(const Value: string): Int64;
property Base: TNumericSystemBase read FBase write SetBase;
property Precision: TDigitCount read FPrecision write SetPrecision;
property NumberOfFractionalDigits: TDigitCount read FNumberOfFractionalDigits write FNumberOfFractionalDigits;
property ExponentDivision: Integer read FExpDivision write SetExpDivision;
property DigitBlockSize: TDigitCount read FDigitBlockSize write FDigitBlockSize;
property DigitBlockSeparator: Char read FDigitBlockSeparator write FDigitBlockSeparator;
property FractionalPartSeparator: Char read FFractionalPartSeparator write FFractionalPartSeparator;
property Multiplier: string read FMultiplier write FMultiplier;
property PaddingChar: Char read FPaddingChar write FPaddingChar;
property ShowPositiveSign: Boolean read FShowPositiveSign write FShowPositiveSign;
property Width: TDigitCount read FWidth write FWidth;
property NegativeSign: Char read GetNegativeSign write SetNegativeSign;
property PositiveSign: Char read GetPositiveSign write SetPositiveSign;
end;
function IntToStrZeroPad(Value, Count: Integer): AnsiString;
// Child processes
type
// e.g. TStrings.Append
TTextHandler = procedure(const Text: string) of object;
const
ABORT_EXIT_CODE = {$IFDEF MSWINDOWS} ERROR_CANCELLED {$ELSE} 1223 {$ENDIF};
function Execute(const CommandLine: string; OutputLineCallback: TTextHandler; RawOutput: Boolean = False;
AbortPtr: PBoolean = nil): Cardinal; overload;
function Execute(const CommandLine: string; var Output: string; RawOutput: Boolean = False;
AbortPtr: PBoolean = nil): Cardinal; overload;
// Console Utilities
function ReadKey: Char;
// Loading of modules (DLLs)
type
{$IFDEF MSWINDOWS}
TModuleHandle = HINST;
{$ENDIF MSWINDOWS}
{$IFDEF LINUX}
TModuleHandle = Pointer;
{$ENDIF LINUX}
const
INVALID_MODULEHANDLE_VALUE = TModuleHandle(0);
function LoadModule(var Module: TModuleHandle; FileName: string): Boolean;
function LoadModuleEx(var Module: TModuleHandle; FileName: string; Flags: Cardinal): Boolean;
procedure UnloadModule(var Module: TModuleHandle);
function GetModuleSymbol(Module: TModuleHandle; SymbolName: string): Pointer;
function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: string; var Accu: Boolean): Pointer;
function ReadModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
function WriteModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
// Conversion Utilities
type
EJclConversionError = class(EJclError);
function StrToBoolean(const S: string): Boolean;
function IntToBool(I: Integer): Boolean;
function BoolToInt(B: Boolean): Integer;
// RTL package information
{$IFNDEF FPC}
function SystemTObjectInstance: LongWord;
function IsCompiledWithPackages: Boolean;
{$ENDIF ~FPC}
// GUID
function JclGUIDToString(const GUID: TGUID): string;
function JclStringToGUID(const S: string): TGUID;
implementation
uses
{$IFDEF HAS_UNIT_TYPES}
Types,
{$ENDIF HAS_UNIT_TYPES}
{$IFDEF UNIX}
{$IFDEF HAS_UNIT_LIBC}
Libc,
{$ELSE ~HAS_UNIT_LIBC}
dl,
{$ENDIF ~HAS_UNIT_LIBC}
{$ENDIF UNIX}
{$IFDEF MSWINDOWS}
JclConsole,
{$ENDIF MSWINDOWS}
SysUtils,
JclResources, JclStrings, JclMath;
// Pointer manipulation
procedure GetAndFillMem(var P: Pointer; const Size: Integer; const Value: Byte);
begin
GetMem(P, Size);
FillChar(P^, Size, Value);
end;
procedure FreeMemAndNil(var P: Pointer);
var
Q: Pointer;
begin
Q := P;
P := nil;
FreeMem(Q);
end;
function PCharOrNil(const S: string): PChar;
begin
Result := Pointer(S);
end;
function PAnsiCharOrNil(const S: AnsiString): PAnsiChar;
begin
Result := Pointer(S);
end;
{$IFDEF SUPPORTS_WIDESTRING}
function PWideCharOrNil(const W: WideString): PWideChar;
begin
Result := Pointer(W);
end;
{$ENDIF SUPPORTS_WIDESTRING}
{$IFDEF MSWINDOWS}
type
PUsed = ^TUsed;
TUsed = record
SizeFlags: Integer;
end;
const
cThisUsedFlag = 2;
cPrevFreeFlag = 1;
cFillerFlag = Integer($80000000);
cFlags = cThisUsedFlag or cPrevFreeFlag or cFillerFlag;
function SizeOfMem(const APointer: Pointer): Integer;
var
U: PUsed;
begin
if IsMemoryManagerSet then
Result:= -1
else
begin
Result := 0;
if APointer <> nil then
begin
U := APointer;
U := PUsed(PChar(U) - SizeOf(TUsed));
if (U.SizeFlags and cThisUsedFlag) <> 0 then
Result := (U.SizeFlags) and (not cFlags - SizeOf(TUsed));
end;
end;
end;
{$ENDIF MSWINDOWS}
{$IFDEF LINUX}
function SizeOfMem(const APointer: Pointer): Integer;
begin
if IsMemoryManagerSet then
Result:= -1
else
begin
if APointer <> nil then
Result := malloc_usable_size(APointer)
else
Result := 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -