{
pascalx.lang — основной модуль для разработки программ и библиотек.
Copyright © 2021 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или
изменять её на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она может быть полезна,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.
}
unit pascalx.lang;
{$MODE OBJFPC}
interface
uses
{$IFDEF WINDOWS} windows, {$ENDIF}
interfacebase,
sysutils,
classes,
typinfo;
{$ASMMODE INTEL,CALLING REGISTER,INLINE ON,TYPEINFO ON}
{%region public }
type
_Interface = interface;
_Property = interface;
_Class = interface;
Runnable = interface;
Value = interface;
ValueExtended = interface;
_Object = class;
RefCountInterfacedObject = class;
DynamicalyAllocatedObject = class;
ValueOfBoolean = class;
ValueOfLong = class;
ValueOfFloat = class;
ValueOfDouble = class;
ValueOfReal = class;
ValueOfAnsiString = class;
ValueOfUnicodeString = class;
ValueOfObject = class;
ValueOfInterface = class;
RealValueRepresenter = class;
Task = class;
Thread = class;
Monitor = class;
Throwable = class;
Exception = class;
PropertyException = class;
PropertyNotFoundException = class;
IllegalPropertyTypeException = class;
IllegalPropertyAccessException = class;
RuntimeException = class;
ArithmeticException = class;
ClassCastException = class;
IllegalStateException = class;
IllegalMonitorStateException = class;
IllegalArgumentException = class;
NumberFormatException = class;
IndexOutOfBoundsException = class;
ArrayIndexOutOfBoundsException = class;
StringIndexOutOfBoundsException = class;
NegativeArraySizeException = class;
NullPointerException = class;
SecurityException = class;
UnsupportedOperationException = class;
Error = class;
ClassContentError = class;
AbstractMethodError = class;
MachineError = class;
StackOverflowError = class;
MemoryError = class;
OutOfMemoryError = class;
InvalidPointerError = class;
boolean = system.Boolean;
char = system.Char;
wchar = system.WideChar;
byte = system.Int8;
short = system.Int16;
int = system.Int32;
long = system.Int64;
float = system.Single;
double = system.Double;
real = packed array [0..9] of system.UInt8;
{ boolean[] } boolean_Array1d = packed array of boolean;
{ char[] } char_Array1d = packed array of char;
{ wchar[] } wchar_Array1d = packed array of wchar;
{ byte[] } byte_Array1d = packed array of byte;
{ short[] } short_Array1d = packed array of short;
{ int[] } int_Array1d = packed array of int;
{ long[] } long_Array1d = packed array of long;
{ float[] } float_Array1d = packed array of float;
{ double[] } double_Array1d = packed array of double;
{ real[] } real_Array1d = packed array of real;
{ TObject[] } TObject_Array1d = packed array of TObject;
{ IUnknown[] } IUnknown_Array1d = packed array of IUnknown;
{ _Property[] } _Property_Array1d = packed array of _Property;
{ _Class[] } _Class_Array1d = packed array of _Class;
{ Runnable[] } Runnable_Array1d = packed array of Runnable;
{ Value[] } Value_Array1d = packed array of Value;
{ AnsiString[] } AnsiString_Array1d = packed array of AnsiString;
{ UnicodeString[] } UnicodeString_Array1d = packed array of UnicodeString;
{ boolean[][] } boolean_Array2d = packed array of boolean_Array1d;
{ char[][] } char_Array2d = packed array of char_Array1d;
{ wchar[][] } wchar_Array2d = packed array of wchar_Array1d;
{ byte[][] } byte_Array2d = packed array of byte_Array1d;
{ short[][] } short_Array2d = packed array of short_Array1d;
{ int[][] } int_Array2d = packed array of int_Array1d;
{ long[][] } long_Array2d = packed array of long_Array1d;
{ float[][] } float_Array2d = packed array of float_Array1d;
{ double[][] } double_Array2d = packed array of double_Array1d;
{ real[][] } real_Array2d = packed array of real_Array1d;
{ TObject[][] } TObject_Array2d = packed array of TObject_Array1d;
{ IUnknown[][] } IUnknown_Array2d = packed array of IUnknown_Array1d;
{ _Property[][] } _Property_Array2d = packed array of _Property_Array1d;
{ _Class[][] } _Class_Array2d = packed array of _Class_Array1d;
{ Runnable[][] } Runnable_Array2d = packed array of Runnable_Array1d;
{ Value[][] } Value_Array2d = packed array of Value_Array1d;
{ AnsiString[][] } AnsiString_Array2d = packed array of AnsiString_Array1d;
{ UnicodeString[][] } UnicodeString_Array2d = packed array of UnicodeString_Array1d;
TObjectExtended = class helper for TObject
private
class function getPropertyInfo(const name: AnsiString): PPropInfo;
public
function getClass(): _Class;
function getIdentityHashCode(): long;
function isStoredProperty(const name: AnsiString): boolean;
function readPropertyOfBoolean(const name: AnsiString): boolean;
function readPropertyOfLong(const name: AnsiString): long;
function readPropertyOfDouble(const name: AnsiString): double;
function readPropertyOfObject(const name: AnsiString): TObject;
function readPropertyOfInterface(const name: AnsiString): IUnknown;
function readPropertyOfAnsiString(const name: AnsiString): AnsiString;
function readPropertyOfUnicodeString(const name: AnsiString): UnicodeString;
procedure writePropertyOfBoolean(const name: AnsiString; value: boolean);
procedure writePropertyOfLong(const name: AnsiString; value: long);
procedure writePropertyOfDouble(const name: AnsiString; value: double);
procedure writePropertyOfObject(const name: AnsiString; value: TObject);
procedure writePropertyOfInterface(const name: AnsiString; value: IUnknown);
procedure writePropertyOfAnsiString(const name: AnsiString; const value: AnsiString);
procedure writePropertyOfUnicodeString(const name: AnsiString; const value: UnicodeString);
end;
_Interface = interface(IUnknown) ['{F5377D1E-7AF2-4BBA-822E-778B4F7D652F}']
function getInterface(const iid: TGuid; out obj): boolean; overload;
function getInterface(const iid: ShortString; out obj): boolean; overload;
function getInterfaceWeak(const iid: TGuid; out obj): boolean;
function getInterfaceByStr(const iid: ShortString; out obj): boolean;
function fieldAddress(const name: ShortString): Pointer;
function safeCallException(exceptObject: TObject; exceptAddress: Pointer): HResult;
function equals(anot: TObject): boolean;
function getHashCode(): long;
function toString(): AnsiString;
procedure dispatch(var message);
procedure dispatchStr(var message);
procedure defaultHandler(var message);
procedure defaultHandlerStr(var message);
end;
_Property = interface(_Interface) ['{F5377D1E-7AF2-4BBA-822E-778B4F7D6530}']
function isReadable(): boolean;
function isWriteable(): boolean;
function isStoreable(): boolean;
function getType(): _Class;
function getName(): AnsiString;
end;
_Class = interface(_Interface) ['{F5377D1E-7AF2-4BBA-822E-778B4F7D6531}']
function isPrimitive(): boolean;
function isInterface(): boolean;
function isInstance(ref: TObject): boolean;
function isAssignableFrom(cls: _Class): boolean;
function getPrimitiveType(): int;
function getProperty(const name: AnsiString): _Property;
function getSuperclass(): _Class;
function getInterfaces(): _Class_Array1d;
function getProperties(): _Property_Array1d;
function getCanonicalName(): AnsiString;
function getSimpleName(): AnsiString;
function getUnitName(): AnsiString;
function createInstance(): DynamicalyAllocatedObject;
end;
Runnable = interface(_Interface) ['{5BF760E3-0DD8-49EE-AEB9-F3A7978E21CD}']
procedure run();
end;
Value = interface(_Interface) ['{A3919068-04E5-47B0-A10D-591E2A664127}']
function getType(): int;
function booleanValue(): boolean;
function intValue(): int;
function longValue(): long;
function floatValue(): float;
function doubleValue(): double;
function realValue(): real;
function ansiStringValue(): AnsiString;
function unicodeStringValue(): UnicodeString;
function objectValue(): TObject;
function interfaceValue(): IUnknown;
end;
ValueExtended = interface(Value) ['{A3919068-04E5-47B0-A10D-591E2A664128}']
function getSize(): int;
procedure writeToByteArray(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLE(const dst: byte_Array1d; offset: int);
end;
_Object = class(TObject, IUnknown, _Interface)
public
constructor create();
destructor destroy; override;
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function queryInterface({$IFDEF FPC_HAS_CONSTREF} constref {$ELSE} const {$ENDIF} iid: TGuid; out obj): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF}; virtual;
function _addref(): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF}; virtual;
function _release(): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF}; virtual;
procedure afterConstruction(); override;
procedure beforeDestruction(); override;
end;
RefCountInterfacedObject = class(_Object)
public
class function newInstance(): TObject; override; final;
public
function _addref(): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF}; override; final;
function _release(): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF}; override; final;
procedure afterConstruction(); override; final;
procedure beforeDestruction(); override; final;
private
refcount: int;
end;
DynamicalyAllocatedObject = class(RefCountInterfacedObject)
public
constructor create(); virtual;
end;
ValueOfBoolean = class(RefCountInterfacedObject, Value, ValueExtended)
public
constructor create(value: boolean);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getType(): int;
function booleanValue(): boolean;
function intValue(): int;
function longValue(): long;
function floatValue(): float;
function doubleValue(): double;
function realValue(): real;
function ansiStringValue(): AnsiString;
function unicodeStringValue(): UnicodeString;
function objectValue(): TObject;
function interfaceValue(): IUnknown;
function getSize(): int;
procedure writeToByteArray(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLE(const dst: byte_Array1d; offset: int);
private
value: byte;
end;
ValueOfLong = class(RefCountInterfacedObject, Value, ValueExtended)
public
constructor create(value: long; &type: int = 0);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getType(): int;
function booleanValue(): boolean;
function intValue(): int;
function longValue(): long;
function floatValue(): float;
function doubleValue(): double;
function realValue(): real;
function ansiStringValue(): AnsiString;
function unicodeStringValue(): UnicodeString;
function objectValue(): TObject;
function interfaceValue(): IUnknown;
function getSize(): int;
procedure writeToByteArray(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLE(const dst: byte_Array1d; offset: int);
private
value: long;
&type: int;
end;
ValueOfFloat = class(RefCountInterfacedObject, Value, ValueExtended)
public
constructor create(value: float);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getType(): int;
function booleanValue(): boolean;
function intValue(): int;
function longValue(): long;
function floatValue(): float;
function doubleValue(): double;
function realValue(): real;
function ansiStringValue(): AnsiString;
function unicodeStringValue(): UnicodeString;
function objectValue(): TObject;
function interfaceValue(): IUnknown;
function getSize(): int;
procedure writeToByteArray(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLE(const dst: byte_Array1d; offset: int);
private
value: float;
end;
ValueOfDouble = class(RefCountInterfacedObject, Value, ValueExtended)
public
constructor create(value: double);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getType(): int;
function booleanValue(): boolean;
function intValue(): int;
function longValue(): long;
function floatValue(): float;
function doubleValue(): double;
function realValue(): real;
function ansiStringValue(): AnsiString;
function unicodeStringValue(): UnicodeString;
function objectValue(): TObject;
function interfaceValue(): IUnknown;
function getSize(): int;
procedure writeToByteArray(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLE(const dst: byte_Array1d; offset: int);
private
value: double;
end;
ValueOfReal = class(RefCountInterfacedObject, Value, ValueExtended)
private
class function realIsEquals(const value1, value2: real): boolean; static;
public
constructor create(const value: real);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getType(): int;
function booleanValue(): boolean;
function intValue(): int;
function longValue(): long;
function floatValue(): float;
function doubleValue(): double;
function realValue(): real;
function ansiStringValue(): AnsiString;
function unicodeStringValue(): UnicodeString;
function objectValue(): TObject;
function interfaceValue(): IUnknown;
function getSize(): int;
procedure writeToByteArray(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLE(const dst: byte_Array1d; offset: int);
private
value: real;
end;
ValueOfAnsiString = class(RefCountInterfacedObject, Value)
public
constructor create(const value: AnsiString);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getType(): int;
function booleanValue(): boolean;
function intValue(): int;
function longValue(): long;
function floatValue(): float;
function doubleValue(): double;
function realValue(): real;
function ansiStringValue(): AnsiString;
function unicodeStringValue(): UnicodeString;
function objectValue(): TObject;
function interfaceValue(): IUnknown;
private
value: AnsiString;
end;
ValueOfUnicodeString = class(RefCountInterfacedObject, Value)
public
constructor create(const value: UnicodeString);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getType(): int;
function booleanValue(): boolean;
function intValue(): int;
function longValue(): long;
function floatValue(): float;
function doubleValue(): double;
function realValue(): real;
function ansiStringValue(): AnsiString;
function unicodeStringValue(): UnicodeString;
function objectValue(): TObject;
function interfaceValue(): IUnknown;
private
value: UnicodeString;
end;
ValueOfObject = class(RefCountInterfacedObject, Value)
public
constructor create(value: TObject; owned: boolean = true);
destructor destroy; override;
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getType(): int;
function booleanValue(): boolean; virtual;
function intValue(): int; virtual;
function longValue(): long; virtual;
function floatValue(): float; virtual;
function doubleValue(): double; virtual;
function realValue(): real; virtual;
function ansiStringValue(): AnsiString; virtual;
function unicodeStringValue(): UnicodeString; virtual;
function objectValue(): TObject;
function interfaceValue(): IUnknown;
private
value: TObject;
owned: boolean;
end;
ValueOfInterface = class(RefCountInterfacedObject, Value)
public
constructor create(value: IUnknown);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getType(): int;
function booleanValue(): boolean; virtual;
function intValue(): int; virtual;
function longValue(): long; virtual;
function floatValue(): float; virtual;
function doubleValue(): double; virtual;
function realValue(): real; virtual;
function ansiStringValue(): AnsiString; virtual;
function unicodeStringValue(): UnicodeString; virtual;
function objectValue(): TObject;
function interfaceValue(): IUnknown;
private
value: IUnknown;
end;
RealValueRepresenter = class(_Object)
public
class function pow10(const value: real; power: int): real; static;
private
class function tab_04_00(power: int): real; static;
class function tab_08_05(power: int): real; static;
class function tab_12_09(power: int): real; static;
public
constructor create(significandDigits, orderDigits: int; orderRequired: boolean = false);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function parseReal(const str: AnsiString): real; virtual;
function parseFloat(const str: AnsiString): float; virtual;
function parseDouble(const str: AnsiString): double; virtual;
function getOrderDigits(): int; virtual;
function getSignificandDigits(): int; virtual;
function toString(const value: real): AnsiString; overload; virtual;
protected
function parse(const str: AnsiString): real; virtual;
private
orderRequired: boolean;
orderDigits: int;
significandDigits: int;
minRepresentValue: long;
maxRepresentValue: long;
limitValueWithoutExponent: real;
limitValueWithFractialPart: real;
end;
Task = class(_Object, Runnable)
public
constructor create();
destructor destroy; override;
function getScheduledTime(): long;
procedure run(); virtual; abstract;
procedure cancel(); virtual;
procedure schedule(delay: int); virtual; overload;
procedure schedule(delay, period: int); virtual; overload;
protected
procedure cancelled(); virtual;
private
periodic: boolean;
period: int;
runningTime: long;
scheduledTime: long;
end;
Thread = class(TThread, IUnknown, _Interface, Runnable)
private
class var threadNumber: int;
class function nextThreadNumber(): int; static;
public
constructor create(); overload;
constructor create(const name: AnsiString); overload;
constructor create(target: Runnable); overload;
constructor create(target: Runnable; const name: AnsiString); overload;
function toString(): AnsiString; override;
function queryInterface({$IFDEF FPC_HAS_CONSTREF} constref {$ELSE} const {$ENDIF} iid: TGuid; out obj): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF}; virtual;
function _addref(): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF}; virtual;
function _release(): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF}; virtual;
function getName(): AnsiString;
procedure run(); virtual;
protected
procedure execute(); override; final;
private
fTarget: Runnable;
fName: AnsiString;
end;
Monitor = class(_Object)
private type
ThreadEntry = class;
SuspendTask = class;
ThreadEntry_Array1d = packed array of ThreadEntry;
ThreadEntry = class(_Object)
public
constructor create(owner: Monitor; monitorThread: TThread; state: int);
destructor destroy; override;
procedure suspend();
procedure resume();
private
fState: int;
fEntryCount: long;
fMonitorEvent: PRTLEvent;
fMonitorThread: TThread;
fSuspendTask: Task;
fOwner: Monitor;
end;
SuspendTask = class(Task)
public
constructor create(owner: Monitor; entry: ThreadEntry);
procedure run(); override;
private
fEntry: ThreadEntry;
fOwner: Monitor;
end;
public
procedure afterConstruction(); override; final;
procedure beforeDestruction(); override; final;
procedure notify();
procedure notifyAll();
procedure wait(millis: int = 0);
private
procedure push(entry: ThreadEntry);
procedure pop();
private
fWaitingCount: int;
fNotifiesCount: long;
fOwningEntry: ThreadEntry;
fWaitingEntries: ThreadEntry_Array1d;
fMonitorSynchronize: TRTLCriticalSection;
end;
Throwable = class(_Object)
public
constructor create(const message: AnsiString = ''; helpContext: int = 0);
function toString(): AnsiString; override;
procedure printStackTrace();
private
fMessage: AnsiString;
fHelpContext: int;
published
property helpContext: int read fHelpContext write fHelpContext;
property message: AnsiString read fMessage write fMessage;
end;
Exception = class(Throwable);
PropertyException = class(Exception);
PropertyNotFoundException = class(PropertyException);
IllegalPropertyTypeException = class(PropertyException);
IllegalPropertyAccessException = class(PropertyException);
RuntimeException = class(Exception);
ArithmeticException = class(RuntimeException);
ClassCastException = class(RuntimeException);
IllegalStateException = class(RuntimeException);
IllegalMonitorStateException = class(IllegalStateException);
IllegalArgumentException = class(RuntimeException);
NumberFormatException = class(IllegalArgumentException);
IndexOutOfBoundsException = class(RuntimeException);
ArrayIndexOutOfBoundsException = class(IndexOutOfBoundsException);
StringIndexOutOfBoundsException = class(IndexOutOfBoundsException);
NegativeArraySizeException = class(RuntimeException);
NullPointerException = class(RuntimeException);
SecurityException = class(RuntimeException);
UnsupportedOperationException = class(RuntimeException);
Error = class(Throwable);
ClassContentError = class(Error);
AbstractMethodError = class(ClassContentError);
MachineError = class(Error);
StackOverflowError = class(MachineError);
MemoryError = class(MachineError)
private
disallowFree: boolean;
public
procedure freeInstance(); override;
end;
OutOfMemoryError = class(MemoryError);
InvalidPointerError = class(MemoryError);
const { специальные значения }
CHAR_MIN_VALUE = char(#$00);
CHAR_MAX_VALUE = char(#$ff);
WCHAR_MIN_VALUE = wchar(#$0000);
WCHAR_MAX_VALUE = wchar(#$ffff);
BYTE_MIN_VALUE = byte(-$80);
BYTE_MAX_VALUE = byte($7f);
SHORT_MIN_VALUE = short(-$8000);
SHORT_MAX_VALUE = short($7fff);
INT_MIN_VALUE = int(-$80000000);
INT_MAX_VALUE = int($7fffffff);
LONG_MIN_VALUE = long(-$8000000000000000);
LONG_MAX_VALUE = long($7fffffffffffffff);
FLOAT_NAN = float(0.0 / 0.0);
FLOAT_POSITIVE_INFINITY = float(+1.0 / 0.0);
FLOAT_NEGATIVE_INFINITY = float(-1.0 / 0.0);
FLOAT_MIN_VALUE = float(1.40129846432481707e-45);
FLOAT_MAX_VALUE = float(3.40282346638528860e+38);
DOUBLE_NAN = double(0.0 / 0.0);
DOUBLE_POSITIVE_INFINITY = double(+1.0 / 0.0);
DOUBLE_NEGATIVE_INFINITY = double(-1.0 / 0.0);
DOUBLE_MIN_VALUE = double(4.94065645841246544e-324);
DOUBLE_MAX_VALUE = double(1.79769313486231571e+308);
DIRECTORY_SEPARATOR = char({$IF DEFINED(WINDOWS)} '\' {$ELSE} '/' {$ENDIF});
LINE_ENDING = AnsiString({$IF DEFINED(WINDOWS)} #$0d#$0a {$ELSEIF DEFINED(UNIX)} #$0a {$ELSE} #$0d {$ENDIF});
const { диапазон поддерживаемых оснований систем счисления }
MIN_RADIX = int(2);
MAX_RADIX = int(36);
const { значения для _Class }
TYPE_BOOLEAN = int(18);
TYPE_CHAR = int(2);
TYPE_WCHAR = int(17);
TYPE_BYTE = int(30);
TYPE_SHORT = int(32);
TYPE_INT = int(1);
TYPE_LONG = int(19);
TYPE_UBYTE = int(31);
TYPE_USHORT = int(33);
TYPE_UINT = int(35);
TYPE_ULONG = int(20);
TYPE_FLOAT = int(4);
TYPE_DOUBLE = int(38);
TYPE_REAL = int(39); { не используется в _Class }
TYPE_ANSISTRING = int(9);
TYPE_UNICODESTRING = int(24);
TYPE_CLASS = int(15);
TYPE_INTERFACE = int(14);
const { значения для RealValueRepresenter }
MIN_ORDER_DIGITS = int(1);
MAX_ORDER_DIGITS = int(4);
REAL_ORDER_DIGITS = int(4);
FLOAT_ORDER_DIGITS = int(2);
DOUBLE_ORDER_DIGITS = int(3);
MIN_SIGNIFICAND_DIGITS = int(2);
MAX_SIGNIFICAND_DIGITS = int(18);
REAL_SIGNIFICAND_DIGITS = int(18);
FLOAT_SIGNIFICAND_DIGITS = int(7);
DOUBLE_SIGNIFICAND_DIGITS = int(15);
resourcestring
msgPropertyNotFound = 'Не найдено свойство ';
msgIllegalPropertyType = 'Другой тип свойства ';
msgIllegalPropertyAccess = 'Нет соответствующего доступа у свойства ';
msgArithmeticError = 'Ошибка арифметики';
msgClassCast = 'Ошибка приведения к типу';
msgIllegalMonitorState = 'Недопустимое состояние блокирующего монитора';
msgIllegalArgument = 'Недопустимое значение параметра ';
msgIllegalNumberFormat = 'Недопустимый формат числа';
msgIllegalRadix = 'Недопустимое основание системы счисления';
msgIndexOutOfBounds = 'Индекс выходит из диапазона';
msgArrayIndexOutOfBounds = 'Индекс элемента массива выходит из диапазона';
msgStringIndexOutOfBounds = 'Индекс символа строки выходит из диапазона';
msgNegativeArraySize = 'Длина массива не может быть отрицательной';
msgNullPointer = 'Нулевой указатель не может быть разыменован';
msgNullPointerArgument = 'Нулевой указатель в параметре ';
msgSecurity = 'Нет доступа';
msgUnsupportedOperation = 'Операция не поддерживается';
msgAbstractMethod = 'Попытка вызова абстрактного метода';
msgStackOverflow = 'Стак вызовов переполнен';
msgOutOfMemory = 'Out of memory';
msgInvalidPointer = 'Invalid pointer';
{%endregion}
{%region routine }
function charIsDigit(c: char): boolean; overload;
function charIsDigit(c: wchar): boolean; overload;
function charIsLowerCase(c: char): boolean; overload;
function charIsLowerCase(c: wchar): boolean; overload;
function charIsUpperCase(c: char): boolean; overload;
function charIsUpperCase(c: wchar): boolean; overload;
function charToLowerCase(c: char): char; overload;
function charToLowerCase(c: wchar): wchar; overload;
function charToUpperCase(c: char): char; overload;
function charToUpperCase(c: wchar): wchar; overload;
function byteParse(const str: AnsiString; radix: int = 10): byte;
function shortByteSwap(value: short): short;
function shortParse(const str: AnsiString; radix: int = 10): short;
function intBitsToFloat(bits: int): float;
function intByteSwap(value: int): int;
function intSar(value: int; bits: int): int;
function intAbs(value: int): int; inline;
function intMax(value1, value2: int): int; inline;
function intMin(value1, value2: int): int; inline;
function intBound(minimum, value, maximum: int): int; inline;
function intParse(const str: AnsiString; radix: int = 10): int;
function intToString(value: int; radix: int = 10): AnsiString;
function intToBinaryString(value: int): AnsiString;
function intToOctalString(value: int): AnsiString;
function intToHexString(value: int): AnsiString;
function intToFloat(value: int): float;
function intToDouble(value: int): double;
function longBitsToDouble(bits: long): double;
function longByteSwap(value: long): long;
function longSar(value: long; bits: int): long;
function longAbs(value: long): long; inline;
function longMax(value1, value2: long): long; inline;
function longMin(value1, value2: long): long; inline;
function longBound(minimum, value, maximum: long): long; inline;
function longParse(const str: AnsiString; radix: int = 10): long;
function longToString(value: long; radix: int = 10): AnsiString;
function longToBinaryString(value: long): AnsiString;
function longToOctalString(value: long): AnsiString;
function longToHexString(value: long): AnsiString;
function longToFloat(value: long): float;
function longToDouble(value: long): double;
function ulongCmp(uvalue1, uvalue2: long): int;
function ulongDiv(uvalue1, uvalue2: long): long;
function ulongRem(uvalue1, uvalue2: long): long;
function ulongToReal(uvalue: long): real;
function floatIsNaN(value: float): boolean;
function floatIsInfinite(value: float): boolean;
function floatToIntBits(value: float): int;
function floatCmpl(value1, value2: float): int;
function floatCmpg(value1, value2: float): int;
function floatAbs(value: float): float;
function floatMax(value1, value2: float): float;
function floatMin(value1, value2: float): float;
function floatMod(value1, value2: float): float;
function floatBound(minimum, value, maximum: float): float;
function floatParse(const str: AnsiString): float;
function floatToString(value: float): AnsiString;
function floatToInt(value: float): int;
function floatToLong(value: float): long;
function floatToDouble(value: float): double;
function doubleIsNaN(value: double): boolean;
function doubleIsInfinite(value: double): boolean;
function doubleToLongBits(value: double): long;
function doubleCmpl(value1, value2: double): int;
function doubleCmpg(value1, value2: double): int;
function doubleAbs(value: double): double;
function doubleMax(value1, value2: double): double;
function doubleMin(value1, value2: double): double;
function doubleMod(value1, value2: double): double;
function doubleBound(minimum, value, maximum: double): double;
function doubleParse(const str: AnsiString): double;
function doubleToString(value: double): AnsiString;
function doubleToInt(value: double): int;
function doubleToLong(value: double): long;
function doubleToFloat(value: double): float;
function REAL_NAN: real; inline;
function REAL_POSITIVE_INFINITY: real; inline;
function REAL_NEGATIVE_INFINITY: real; inline;
function REAL_MIN_VALUE: real; inline;
function REAL_MAX_VALUE: real; inline;
function realIsNaN(const value: real): boolean;
function realIsInfinite(const value: real): boolean;
function realBuild(exponent: int; significand: long): real; inline;
function realSignificand(const value: real): long; inline;
function realExponent(const value: real): int; inline;
function realCmpl(const value1, value2: real): int;
function realCmpg(const value1, value2: real): int;
function realAbs(const value: real): real;
function realMax(const value1, value2: real): real;
function realMin(const value1, value2: real): real;
function realMod(const value1, value2: real): real;
function realBound(const minimum, value, maximum: real): real;
function realParse(const str: AnsiString): real;
function realToString(const value: real): AnsiString;
function realToInt(const value: real): int;
function realToLong(const value: real): long;
function realToFloat(const value: real): float;
function realToDouble(const value: real): double;
function stringToUTF8(const str: UnicodeString): AnsiString;
function stringToUTF16(const str: AnsiString): UnicodeString;
function stringBuildUTF8(const charCodes: int_Array1d; offset, length: int): AnsiString;
function stringBuildUTF16(const charCodes: int_Array1d; offset, length: int): UnicodeString;
function stringToCharCodes(const str: AnsiString): int_Array1d; overload;
function stringToCharCodes(const str: UnicodeString): int_Array1d; overload;
function stringToCharArray(const str: AnsiString): char_Array1d;
function stringToWCharArray(const str: UnicodeString): wchar_Array1d;
function stringToByteArray(const str: AnsiString): byte_Array1d;
function stringToShortArray(const str: UnicodeString): short_Array1d;
function stringToLowerCase(const str: AnsiString): AnsiString; overload;
function stringToLowerCase(const str: UnicodeString): UnicodeString; overload;
function stringToUpperCase(const str: AnsiString): AnsiString; overload;
function stringToUpperCase(const str: UnicodeString): UnicodeString; overload;
function stringReplace(const str: AnsiString; oldCharacter, newCharacter: char): AnsiString; overload;
function stringReplace(const str: UnicodeString; oldCharacter, newCharacter: wchar): UnicodeString; overload;
function stringStartsWith(const prefix, str: AnsiString; position: int = 1): boolean; overload;
function stringStartsWith(const prefix, str: UnicodeString; position: int = 1): boolean; overload;
function stringEndsWith(const suffix, str: AnsiString): boolean; overload;
function stringEndsWith(const suffix, str: UnicodeString): boolean; overload;
function stringIndexOf(const prefix, str: AnsiString; startFromIndex: int = 1): int; overload;
function stringIndexOf(const prefix, str: UnicodeString; startFromIndex: int = 1): int; overload;
function stringLastIndexOf(const prefix, str: AnsiString; startFromIndex: int = INT_MAX_VALUE): int; overload;
function stringLastIndexOf(const prefix, str: UnicodeString; startFromIndex: int = INT_MAX_VALUE): int; overload;
function stringTrim(const str: AnsiString): AnsiString; overload;
function stringTrim(const str: UnicodeString): UnicodeString; overload;
function stringCopy(const str: AnsiString): AnsiString; overload;
function stringCopy(const str: AnsiString; beginIndex: int): AnsiString; overload;
function stringCopy(const str: AnsiString; beginIndex, endIndex: int): AnsiString; overload;
function stringCopy(const str: UnicodeString): UnicodeString; overload;
function stringCopy(const str: UnicodeString; beginIndex: int): UnicodeString; overload;
function stringCopy(const str: UnicodeString; beginIndex, endIndex: int): UnicodeString; overload;
function stringSplit(const str: AnsiString): AnsiString_Array1d; overload;
function stringSplit(const str: UnicodeString): UnicodeString_Array1d; overload;
function systemGetTickCount(): long;
function systemGetCurrentDirectory(): UnicodeString;
function systemGetCommandLine(): UnicodeString_Array1d;
function pointerToLongBits(p: Pointer): long; inline;
function classForType(const info: TGuid): _Class; overload;
function classForType(const info: TClass): _Class; overload;
function classForType(const info: Pointer): _Class; overload;
function classForName(const name: AnsiString): _Class;
function AnsiString_create(length: int): AnsiString; overload;
function AnsiString_create(const src: byte_Array1d; offset, length: int): AnsiString; overload;
function AnsiString_create(const src: char_Array1d; offset, length: int): AnsiString; overload;
function UnicodeString_create(length: int): UnicodeString; overload;
function UnicodeString_create(const src: short_Array1d; offset, length: int): UnicodeString; overload;
function UnicodeString_create(const src: wchar_Array1d; offset, length: int): UnicodeString; overload;
function boolean_Array1d_create(length: int): boolean_Array1d; overload;
function boolean_Array1d_create(const elements: array of boolean): boolean_Array1d; overload;
function char_Array1d_create(length: int): char_Array1d; overload;
function char_Array1d_create(const elements: array of char): char_Array1d; overload;
function wchar_Array1d_create(length: int): wchar_Array1d; overload;
function wchar_Array1d_create(const elements: array of wchar): wchar_Array1d; overload;
function byte_Array1d_create(length: int): byte_Array1d; overload;
function byte_Array1d_create(const elements: array of byte): byte_Array1d; overload;
function short_Array1d_create(length: int): short_Array1d; overload;
function short_Array1d_create(const elements: array of short): short_Array1d; overload;
function int_Array1d_create(length: int): int_Array1d; overload;
function int_Array1d_create(const elements: array of int): int_Array1d; overload;
function long_Array1d_create(length: int): long_Array1d; overload;
function long_Array1d_create(const elements: array of long): long_Array1d; overload;
function float_Array1d_create(length: int): float_Array1d; overload;
function float_Array1d_create(const elements: array of float): float_Array1d; overload;
function double_Array1d_create(length: int): double_Array1d; overload;
function double_Array1d_create(const elements: array of double): double_Array1d; overload;
function real_Array1d_create(length: int): real_Array1d; overload;
function real_Array1d_create(const elements: array of real): real_Array1d; overload;
function TObject_Array1d_create(length: int): TObject_Array1d; overload;
function TObject_Array1d_create(const elements: array of TObject): TObject_Array1d; overload;
function IUnknown_Array1d_create(length: int): IUnknown_Array1d; overload;
function IUnknown_Array1d_create(const elements: array of IUnknown): IUnknown_Array1d; overload;
function AnsiString_Array1d_create(length: int): AnsiString_Array1d; overload;
function AnsiString_Array1d_create(const elements: array of AnsiString): AnsiString_Array1d; overload;
function UnicodeString_Array1d_create(length: int): UnicodeString_Array1d; overload;
function UnicodeString_Array1d_create(const elements: array of UnicodeString): UnicodeString_Array1d; overload;
function boolean_Array2d_create(length: int): boolean_Array2d; overload;
function boolean_Array2d_create(length1, length2: int): boolean_Array2d; overload;
function boolean_Array2d_create(const elements: array of boolean_Array1d): boolean_Array2d; overload;
function char_Array2d_create(length: int): char_Array2d; overload;
function char_Array2d_create(length1, length2: int): char_Array2d; overload;
function char_Array2d_create(const elements: array of char_Array1d): char_Array2d; overload;
function wchar_Array2d_create(length: int): wchar_Array2d; overload;
function wchar_Array2d_create(length1, length2: int): wchar_Array2d; overload;
function wchar_Array2d_create(const elements: array of wchar_Array1d): wchar_Array2d; overload;
function byte_Array2d_create(length: int): byte_Array2d; overload;
function byte_Array2d_create(length1, length2: int): byte_Array2d; overload;
function byte_Array2d_create(const elements: array of byte_Array1d): byte_Array2d; overload;
function short_Array2d_create(length: int): short_Array2d; overload;
function short_Array2d_create(length1, length2: int): short_Array2d; overload;
function short_Array2d_create(const elements: array of short_Array1d): short_Array2d; overload;
function int_Array2d_create(length: int): int_Array2d; overload;
function int_Array2d_create(length1, length2: int): int_Array2d; overload;
function int_Array2d_create(const elements: array of int_Array1d): int_Array2d; overload;
function long_Array2d_create(length: int): long_Array2d; overload;
function long_Array2d_create(length1, length2: int): long_Array2d; overload;
function long_Array2d_create(const elements: array of long_Array1d): long_Array2d; overload;
function float_Array2d_create(length: int): float_Array2d; overload;
function float_Array2d_create(length1, length2: int): float_Array2d; overload;
function float_Array2d_create(const elements: array of float_Array1d): float_Array2d; overload;
function double_Array2d_create(length: int): double_Array2d; overload;
function double_Array2d_create(length1, length2: int): double_Array2d; overload;
function double_Array2d_create(const elements: array of double_Array1d): double_Array2d; overload;
function real_Array2d_create(length: int): real_Array2d; overload;
function real_Array2d_create(length1, length2: int): real_Array2d; overload;
function real_Array2d_create(const elements: array of real_Array1d): real_Array2d; overload;
function TObject_Array2d_create(length: int): TObject_Array2d; overload;
function TObject_Array2d_create(length1, length2: int): TObject_Array2d; overload;
function TObject_Array2d_create(const elements: array of TObject_Array1d): TObject_Array2d; overload;
function IUnknown_Array2d_create(length: int): IUnknown_Array2d; overload;
function IUnknown_Array2d_create(length1, length2: int): IUnknown_Array2d; overload;
function IUnknown_Array2d_create(const elements: array of IUnknown_Array1d): IUnknown_Array2d; overload;
function AnsiString_Array2d_create(length: int): AnsiString_Array2d; overload;
function AnsiString_Array2d_create(length1, length2: int): AnsiString_Array2d; overload;
function AnsiString_Array2d_create(const elements: array of AnsiString_Array1d): AnsiString_Array2d; overload;
function UnicodeString_Array2d_create(length: int): UnicodeString_Array2d; overload;
function UnicodeString_Array2d_create(length1, length2: int): UnicodeString_Array2d; overload;
function UnicodeString_Array2d_create(const elements: array of UnicodeString_Array1d): UnicodeString_Array2d; overload;
function arrayequalsfPrimitive(const src: boolean_Array1d; srcOffset: int; const dst: boolean_Array1d; dstOffset: int; length: int): int; overload;
function arrayequalsfPrimitive(const src: char_Array1d; srcOffset: int; const dst: char_Array1d; dstOffset: int; length: int): int; overload;
function arrayequalsfPrimitive(const src: wchar_Array1d; srcOffset: int; const dst: wchar_Array1d; dstOffset: int; length: int): int; overload;
function arrayequalsfPrimitive(const src: byte_Array1d; srcOffset: int; const dst: byte_Array1d; dstOffset: int; length: int): int; overload;
function arrayequalsfPrimitive(const src: short_Array1d; srcOffset: int; const dst: short_Array1d; dstOffset: int; length: int): int; overload;
function arrayequalsfPrimitive(const src: int_Array1d; srcOffset: int; const dst: int_Array1d; dstOffset: int; length: int): int; overload;
function arrayequalsfPrimitive(const src: long_Array1d; srcOffset: int; const dst: long_Array1d; dstOffset: int; length: int): int; overload;
function arrayequalsfInterface(const src; srcOffset: int; const dst; dstOffset: int; length: int): int;
function arrayequalsfObject(const src; srcOffset: int; const dst; dstOffset: int; length: int): int;
function arrayequalsfArray(const src; srcOffset: int; const dst; dstOffset: int; length: int): int;
function arrayequalsbPrimitive(const src: boolean_Array1d; srcOffset: int; const dst: boolean_Array1d; dstOffset: int; length: int): int; overload;
function arrayequalsbPrimitive(const src: char_Array1d; srcOffset: int; const dst: char_Array1d; dstOffset: int; length: int): int; overload;
function arrayequalsbPrimitive(const src: wchar_Array1d; srcOffset: int; const dst: wchar_Array1d; dstOffset: int; length: int): int; overload;
function arrayequalsbPrimitive(const src: byte_Array1d; srcOffset: int; const dst: byte_Array1d; dstOffset: int; length: int): int; overload;
function arrayequalsbPrimitive(const src: short_Array1d; srcOffset: int; const dst: short_Array1d; dstOffset: int; length: int): int; overload;
function arrayequalsbPrimitive(const src: int_Array1d; srcOffset: int; const dst: int_Array1d; dstOffset: int; length: int): int; overload;
function arrayequalsbPrimitive(const src: long_Array1d; srcOffset: int; const dst: long_Array1d; dstOffset: int; length: int): int; overload;
function arrayequalsbInterface(const src; srcOffset: int; const dst; dstOffset: int; length: int): int;
function arrayequalsbObject(const src; srcOffset: int; const dst; dstOffset: int; length: int): int;
function arrayequalsbArray(const src; srcOffset: int; const dst; dstOffset: int; length: int): int;
function arrayfindeqfPrimitive(const src: boolean_Array1d; offset, length: int; value: boolean): int; overload;
function arrayfindeqfPrimitive(const src: char_Array1d; offset, length: int; value: char): int; overload;
function arrayfindeqfPrimitive(const src: wchar_Array1d; offset, length: int; value: wchar): int; overload;
function arrayfindeqfPrimitive(const src: byte_Array1d; offset, length: int; value: int): int; overload;
function arrayfindeqfPrimitive(const src: short_Array1d; offset, length: int; value: int): int; overload;
function arrayfindeqfPrimitive(const src: int_Array1d; offset, length: int; value: int): int; overload;
function arrayfindeqfPrimitive(const src: long_Array1d; offset, length: int; value: long): int; overload;
function arrayfindeqfInterface(const src; offset, length: int; value: IUnknown): int;
function arrayfindeqfObject(const src; offset, length: int; value: TObject): int;
function arrayfindeqfArray(const src; offset, length: int; const value): int;
function arrayfindeqbPrimitive(const src: boolean_Array1d; offset, length: int; value: boolean): int; overload;
function arrayfindeqbPrimitive(const src: char_Array1d; offset, length: int; value: char): int; overload;
function arrayfindeqbPrimitive(const src: wchar_Array1d; offset, length: int; value: wchar): int; overload;
function arrayfindeqbPrimitive(const src: byte_Array1d; offset, length: int; value: int): int; overload;
function arrayfindeqbPrimitive(const src: short_Array1d; offset, length: int; value: int): int; overload;
function arrayfindeqbPrimitive(const src: int_Array1d; offset, length: int; value: int): int; overload;
function arrayfindeqbPrimitive(const src: long_Array1d; offset, length: int; value: long): int; overload;
function arrayfindeqbInterface(const src; offset, length: int; value: IUnknown): int;
function arrayfindeqbObject(const src; offset, length: int; value: TObject): int;
function arrayfindeqbArray(const src; offset, length: int; const value): int;
function arrayfindnefPrimitive(const src: boolean_Array1d; offset, length: int; value: boolean): int; overload;
function arrayfindnefPrimitive(const src: char_Array1d; offset, length: int; value: char): int; overload;
function arrayfindnefPrimitive(const src: wchar_Array1d; offset, length: int; value: wchar): int; overload;
function arrayfindnefPrimitive(const src: byte_Array1d; offset, length: int; value: int): int; overload;
function arrayfindnefPrimitive(const src: short_Array1d; offset, length: int; value: int): int; overload;
function arrayfindnefPrimitive(const src: int_Array1d; offset, length: int; value: int): int; overload;
function arrayfindnefPrimitive(const src: long_Array1d; offset, length: int; value: long): int; overload;
function arrayfindnefInterface(const src; offset, length: int; value: IUnknown): int;
function arrayfindnefObject(const src; offset, length: int; value: TObject): int;
function arrayfindnefArray(const src; offset, length: int; const value): int;
function arrayfindnebPrimitive(const src: boolean_Array1d; offset, length: int; value: boolean): int; overload;
function arrayfindnebPrimitive(const src: char_Array1d; offset, length: int; value: char): int; overload;
function arrayfindnebPrimitive(const src: wchar_Array1d; offset, length: int; value: wchar): int; overload;
function arrayfindnebPrimitive(const src: byte_Array1d; offset, length: int; value: int): int; overload;
function arrayfindnebPrimitive(const src: short_Array1d; offset, length: int; value: int): int; overload;
function arrayfindnebPrimitive(const src: int_Array1d; offset, length: int; value: int): int; overload;
function arrayfindnebPrimitive(const src: long_Array1d; offset, length: int; value: long): int; overload;
function arrayfindnebInterface(const src; offset, length: int; value: IUnknown): int;
function arrayfindnebObject(const src; offset, length: int; value: TObject): int;
function arrayfindnebArray(const src; offset, length: int; const value): int;
procedure arrayfillPrimitives(const dst: boolean_Array1d; offset, length: int; value: boolean); overload;
procedure arrayfillPrimitives(const dst: char_Array1d; offset, length: int; value: char); overload;
procedure arrayfillPrimitives(const dst: wchar_Array1d; offset, length: int; value: wchar); overload;
procedure arrayfillPrimitives(const dst: byte_Array1d; offset, length: int; value: int); overload;
procedure arrayfillPrimitives(const dst: short_Array1d; offset, length: int; value: int); overload;
procedure arrayfillPrimitives(const dst: int_Array1d; offset, length: int; value: int); overload;
procedure arrayfillPrimitives(const dst: long_Array1d; offset, length: int; value: long); overload;
procedure arrayfillPrimitives(const dst: float_Array1d; offset, length: int; value: float); overload;
procedure arrayfillPrimitives(const dst: double_Array1d; offset, length: int; value: double); overload;
procedure arrayfillPrimitives(const dst: real_Array1d; offset, length: int; const value: real); overload;
procedure arrayfillAnsiStrings(const dst: AnsiString_Array1d; offset, length: int; const value: AnsiString);
procedure arrayfillUnicodeStrings(const dst: UnicodeString_Array1d; offset, length: int; const value: UnicodeString);
procedure arrayfillInterfaces(const dst; offset, length: int; value: IUnknown);
procedure arrayfillObjects(const dst; offset, length: int; value: TObject);
procedure arrayfillArrays(const dst; offset, length: int; const value);
procedure arraycopyPrimitives(const src: boolean_Array1d; srcOffset: int; const dst: boolean_Array1d; dstOffset: int; length: int); overload;
procedure arraycopyPrimitives(const src: char_Array1d; srcOffset: int; const dst: char_Array1d; dstOffset: int; length: int); overload;
procedure arraycopyPrimitives(const src: wchar_Array1d; srcOffset: int; const dst: wchar_Array1d; dstOffset: int; length: int); overload;
procedure arraycopyPrimitives(const src: byte_Array1d; srcOffset: int; const dst: byte_Array1d; dstOffset: int; length: int); overload;
procedure arraycopyPrimitives(const src: short_Array1d; srcOffset: int; const dst: short_Array1d; dstOffset: int; length: int); overload;
procedure arraycopyPrimitives(const src: int_Array1d; srcOffset: int; const dst: int_Array1d; dstOffset: int; length: int); overload;
procedure arraycopyPrimitives(const src: long_Array1d; srcOffset: int; const dst: long_Array1d; dstOffset: int; length: int); overload;
procedure arraycopyPrimitives(const src: float_Array1d; srcOffset: int; const dst: float_Array1d; dstOffset: int; length: int); overload;
procedure arraycopyPrimitives(const src: double_Array1d; srcOffset: int; const dst: double_Array1d; dstOffset: int; length: int); overload;
procedure arraycopyPrimitives(const src: real_Array1d; srcOffset: int; const dst: real_Array1d; dstOffset: int; length: int); overload;
procedure arraycopyAnsiStrings(const src: AnsiString_Array1d; srcOffset: int; const dst: AnsiString_Array1d; dstOffset: int; length: int);
procedure arraycopyUnicodeStrings(const src: UnicodeString_Array1d; srcOffset: int; const dst: UnicodeString_Array1d; dstOffset: int; length: int);
procedure arraycopyInterfaces(const src; srcOffset: int; const dst; dstOffset: int; length: int);
procedure arraycopyObjects(const src; srcOffset: int; const dst; dstOffset: int; length: int);
procedure arraycopyArrays(const src; srcOffset: int; const dst; dstOffset: int; length: int);
procedure arrayCheckBounds(const method: AnsiString; arrayLength, offset, length: int);
procedure synchronized(m: Monitor);
procedure synchronizedEnd(m: Monitor);
procedure classInfoAdd(const typeInfos: array of Pointer);
{%endregion}
{%region operator }
operator :=(value: byte): real;
operator :=(value: short): real;
operator :=(value: int): real;
operator :=(value: long): real;
operator :=(value: float): real;
operator :=(value: double): real;
operator =(const value1, value2: real): boolean;
operator <(const value1, value2: real): boolean;
operator >(const value1, value2: real): boolean;
operator <=(const value1, value2: real): boolean;
operator >=(const value1, value2: real): boolean;
operator <>(const value1, value2: real): boolean;
operator +(const value1, value2: real): real;
operator -(const value1, value2: real): real;
operator *(const value1, value2: real): real;
operator /(const value1, value2: real): real;
operator +(const value: real): real;
operator -(const value: real): real;
{%endregion}
implementation
{%region private }
const { значения для TObjectExtended }
TM_FIELD = int(0);
TM_SPECIAL = int(1);
TM_VIRTUAL = int(2);
TM_CONST = int(3);
const { значения для Monitor }
RUNNING = int(1);
WAITING = int(2);
SUSPENDED = int(3);
type
PFXContext = ^FXContext;
Scheduler = class;
Information = class;
PrimitiveInformation = class;
GuidInformation = class;
ClassInformation = class;
InterfaceInformation = class;
PropertyInformation = class;
TypeEnumeration = class;
long2 = packed array [0..1] of long;
{ Task[] } Task_Array1d = packed array of Task;
{ Pointer[] } Pointer_Array1d = packed array of Pointer;
{ PTypeInfo[] } PTypeInfo_Array1d = packed array of PTypeInfo;
{$IFDEF WINDOWS}
FunctionGetExceptionObject = function(errorNumber: int; const rec: windows.TExceptionRecord): TObject;
FunctionGetExceptionClass = function(errorNumber: int): TClass;
{$ENDIF}
FXContext = packed record
fcw: short;
fsw: short;
ftw: byte; rsvd00: byte;
fop: short;
fip: long;
fdp: long;
mxcsr: int;
mxcsrMask: int;
st0: real; rsvd01: packed array [0..5] of byte;
st1: real; rsvd02: packed array [0..5] of byte;
st2: real; rsvd03: packed array [0..5] of byte;
st3: real; rsvd04: packed array [0..5] of byte;
st4: real; rsvd05: packed array [0..5] of byte;
st5: real; rsvd06: packed array [0..5] of byte;
st6: real; rsvd07: packed array [0..5] of byte;
st7: real; rsvd08: packed array [0..5] of byte;
xmm0: long2;
xmm1: long2;
xmm2: long2;
xmm3: long2;
xmm4: long2;
xmm5: long2;
xmm6: long2;
xmm7: long2;
xmm8: long2;
xmm9: long2;
xmm10: long2;
xmm11: long2;
xmm12: long2;
xmm13: long2;
xmm14: long2;
xmm15: long2;
rsvd09: packed array [0..47] of byte;
available: packed array [0..47] of byte;
end;
RealStruct = packed record
significand: long;
exponent: short;
end;
Scheduler = class(_Object, Runnable)
public
constructor create();
destructor destroy; override;
function indexOf(t: Task): int;
function cancel(t: Task): boolean;
function pop(): Task;
procedure push(t: Task);
procedure updateTimer();
procedure freeTimer();
procedure run();
private
fCount: int;
fQueue: Task_Array1d;
fTimer: THandle;
fSynchronize: TRTLCriticalSection;
end;
Information = class(RefCountInterfacedObject, _Class)
public
function isPrimitive(): boolean; virtual;
function isInterface(): boolean; virtual; abstract;
function isInstance(ref: TObject): boolean;
function isAssignableFrom(cls: _Class): boolean;
function getPrimitiveType(): int; virtual;
function getProperty(const name: AnsiString): _Property; virtual;
function getSuperclass(): _Class; virtual;
function getInterfaces(): _Class_Array1d; virtual;
function getProperties(): _Property_Array1d; virtual;
function getCanonicalName(): AnsiString; virtual; abstract;
function getSimpleName(): AnsiString; virtual; abstract;
function getUnitName(): AnsiString; virtual;
function createInstance(): DynamicalyAllocatedObject; virtual;
protected
function isInheritedFrom(const cls: Information): boolean; virtual;
function isInterfaceImplements(const cls: Information): boolean; virtual;
end;
PrimitiveInformation = class(Information)
public
constructor create(info: int; const name: AnsiString = '');
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function isPrimitive(): boolean; override;
function isInterface(): boolean; override;
function getPrimitiveType(): int; override;
function getCanonicalName(): AnsiString; override;
function getSimpleName(): AnsiString; override;
private
custom: boolean;
info: int;
name: AnsiString;
end;
GuidInformation = class(Information)
public
constructor create(const info: TGuid);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function isInterface(): boolean; override;
function getCanonicalName(): AnsiString; override;
function getSimpleName(): AnsiString; override;
private
info: TGuid;
end;
ClassInformation = class(Information)
private
class function typeInfoToLangType(tinfo: PTypeInfo): int; static;
class function propInfoToProperty(pinfo: PPropInfo): _Property; static;
public
constructor create(info: TClass);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function isInterface(): boolean; override;
function getProperty(const name: AnsiString): _Property; override;
function getSuperclass(): _Class; override;
function getInterfaces(): _Class_Array1d; override;
function getProperties(): _Property_Array1d; override;
function getCanonicalName(): AnsiString; override;
function getSimpleName(): AnsiString; override;
function getUnitName(): AnsiString; override;
function createInstance(): DynamicalyAllocatedObject; override;
protected
function isInheritedFrom(const cls: Information): boolean; override;
function isInterfaceImplements(const cls: Information): boolean; override;
private
info: TClass;
end;
InterfaceInformation = class(Information)
public
constructor create(info: PTypeInfo);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function isInterface(): boolean; override;
function getSuperclass(): _Class; override;
function getInterfaces(): _Class_Array1d; override;
function getCanonicalName(): AnsiString; override;
function getSimpleName(): AnsiString; override;
function getUnitName(): AnsiString; override;
protected
function isInheritedFrom(const cls: Information): boolean; override;
function isInterfaceImplements(const cls: Information): boolean; override;
private
info: PTypeInfo;
end;
PropertyInformation = class(RefCountInterfacedObject, _Property)
public
constructor create(readable, writeable, storeable: boolean; &type: _Class; const name: AnsiString);
function isReadable(): boolean;
function isWriteable(): boolean;
function isStoreable(): boolean;
function getType(): _Class;
function getName(): AnsiString;
private
flags: int;
&type: _Class;
name: AnsiString;
end;
TypeEnumeration = class(_Object)
public
constructor create(info: PTypeInfo);
function hasMoreElements(): boolean;
function nextElement(): _Class;
private
info: PTypeInfo;
end;
var
constantPoolLong: packed array [0..1] of long = (
$000000007fffffff, $7fffffffffffffff
);
constantPoolFloat: packed array [0..0] of float = (
2.14748365e+09
);
constantPoolDouble: packed array [0..1] of double = (
2.14748364800000000e+009, 9.22337203685477581e+018
);
typeInfosLength: int;
typeInfosData: PTypeInfo_Array1d;
primitivesData: _Class_Array1d;
defaultContext: FXContext;
realRepresenter: RealValueRepresenter;
floatRepresenter: RealValueRepresenter;
doubleRepresenter: RealValueRepresenter;
schedulerInstance: Scheduler;
{$IFDEF WINDOWS}
previousGetExceptionObject: FunctionGetExceptionObject;
previousGetExceptionClass: FunctionGetExceptionClass;
{$ENDIF}
previousExceptionHandler: TErrorProc;
outOfMemory: MemoryError;
invalidPointer: MemoryError;
{%endregion}
{%region routine }
procedure fxcontextLoadFrom(context: PFXContext); assembler; nostackframe;
asm
db $48
fxrstor [rcx]
end;
procedure fxcontextSaveTo(context: PFXContext); assembler; nostackframe;
asm
db $48
fxsave [rcx]
end;
function interlockedIncrement(intField: Pointer): int; assembler; nostackframe;
asm
mov eax, $01
lock xadd [rcx], eax
inc eax
end;
function interlockedDecrement(intField: Pointer): int; assembler; nostackframe;
asm
mov eax, -$01
lock xadd [rcx], eax
dec eax
end;
function round(const value: real): long; assembler; nostackframe;
asm
fld tbyte[rcx]
fild qword[rip+constantPoolLong-@0+$08]
@0: fcomip st, st(1)
jnp @1
ffree st
fincstp
xor eax, eax
ret
@1: ja @3
ffree st
fincstp
mov rax, [rip+constantPoolLong-@2+$08]
@2: ret
@3: lea rsp, [rsp-$08]
fistp qword[rsp]
pop rax
end;
function log2(const value: real): real; assembler; nostackframe;
asm
fld1
fld tbyte[rdx]
fyl2x
fstp tbyte[rcx]
end;
function getDigit(character: char; radix: int): int;
begin
result := -1;
if (radix >= MIN_RADIX) and (radix <= MAX_RADIX) then begin
if (character >= '0') and (character <= '9') then begin
result := int(character) - int('0');
end else
if (character >= 'a') and (character <= 'z') or (character >= 'A') and (character <= 'Z') then begin
result := (int(character) and $1f) + 9;
end;
end;
if result >= radix then begin
result := -1;
end;
end;
function getDigitRepresentation(digit: int): char;
begin
if (digit >= $00) and (digit < $0a) then begin
result := char(digit + int('0'));
end else
if (digit >= $0a) and (digit < MAX_RADIX) then begin
result := char(digit + (int('a') - $0a));
end else begin
result := '?';
end;
end;
function charIsDigit(c: char): boolean;
begin
result := (c >= '0') and (c <= '9');
end;
function charIsDigit(c: wchar): boolean;
begin
result := (c >= '0') and (c <= '9');
end;
function charIsLowerCase(c: char): boolean;
begin
result := (c >= 'a') and (c <= 'z');
end;
function charIsLowerCase(c: wchar): boolean;
begin
result := (c >= 'a') and (c <= 'z') or (c >= #$00df) and (c <= #$00f6) or (c >= #$00f8) and (c <= #$00ff) or (c >= #$0430) and (c <= #$045f);
end;
function charIsUpperCase(c: char): boolean;
begin
result := (c >= 'A') and (c <= 'Z');
end;
function charIsUpperCase(c: wchar): boolean;
begin
result := (c >= 'A') and (c <= 'Z') or (c >= #$00c0) and (c <= #$00d6) or (c >= #$00d8) and (c <= #$00de) or (c >= #$0400) and (c <= #$042f);
end;
function charToLowerCase(c: char): char;
begin
if charIsUpperCase(c) then begin
result := char(int(c) + $20);
end else begin
result := c;
end;
end;
function charToLowerCase(c: wchar): wchar;
begin
if charIsUpperCase(c) then begin
if (c >= #$0400) and (c <= #$040f) then begin
result := wchar(int(c) + $0050);
end else begin
result := wchar(int(c) + $0020);
end;
end else begin
result := c;
end;
end;
function charToUpperCase(c: char): char;
begin
if charIsLowerCase(c) then begin
result := char(int(c) - $20);
end else begin
result := c;
end;
end;
function charToUpperCase(c: wchar): wchar;
begin
if charIsLowerCase(c) then begin
if (c >= #$0450) and (c <= #$045f) then begin
result := wchar(int(c) - $0050);
end else begin
result := wchar(int(c) - $0020);
end;
end else begin
result := c;
end;
end;
function byteParse(const str: AnsiString; radix: int = 10): byte;
var
value: int;
begin
value := intParse(str, radix);
if (value < BYTE_MIN_VALUE) or (value > BYTE_MAX_VALUE) then begin
raise NumberFormatException.create('byteParse: ' + msgIllegalNumberFormat);
end;
result := byte(value);
end;
function shortByteSwap(value: short): short; assembler; nostackframe;
asm
mov ax, cx
xchg al, ah
end;
function shortParse(const str: AnsiString; radix: int = 10): short;
var
value: int;
begin
value := intParse(str, radix);
if (value < SHORT_MIN_VALUE) or (value > SHORT_MAX_VALUE) then begin
raise NumberFormatException.create('shortParse: ' + msgIllegalNumberFormat);
end;
result := short(value);
end;
function intBitsToFloat(bits: int): float; assembler; nostackframe;
asm
movd xmm0, ecx
end;
function intByteSwap(value: int): int; assembler; nostackframe;
asm
mov eax, ecx
bswap eax
end;
function intSar(value: int; bits: int): int; assembler; nostackframe;
asm
mov eax, ecx
mov ecx, edx
sar eax, cl
end;
function intAbs(value: int): int; inline;
begin
if value < 0 then begin
result := -value;
end else begin
result := value;
end;
end;
function intMax(value1, value2: int): int; inline;
begin
if value1 < value2 then begin
result := value2;
end else begin
result := value1;
end;
end;
function intMin(value1, value2: int): int; inline;
begin
if value1 < value2 then begin
result := value1;
end else begin
result := value2;
end;
end;
function intBound(minimum, value, maximum: int): int; inline;
begin
result := intMin(intMax(minimum, value), maximum);
end;
function intParse(const str: AnsiString; radix: int = 10): int;
var
negative: boolean;
i: int;
len: int;
limit: int;
digit: int;
mulmin: int;
begin
len := length(str);
if len <= 0 then begin
raise NumberFormatException.create('intParse: ' + msgIllegalNumberFormat);
end;
if radix > MAX_RADIX then begin
raise NumberFormatException.create('intParse: ' + msgIllegalRadix);
end;
if radix < MIN_RADIX then begin
raise NumberFormatException.create('intParse: ' + msgIllegalRadix);
end;
result := 0;
i := 0;
if str[1] = '-' then begin
inc(i);
negative := true;
limit := int($80000000);
end else begin
negative := false;
limit := int($80000001);
end;
mulmin := limit div radix;
if i < len then begin
digit := getDigit(str[i + 1], radix);
inc(i);
if digit < 0 then begin
raise NumberFormatException.create('intParse: ' + msgIllegalNumberFormat);
end;
result := -digit;
end;
while i < len do begin
digit := getDigit(str[i + 1], radix);
inc(i);
if (digit < 0) or (result < mulmin) then begin
raise NumberFormatException.create('intParse: ' + msgIllegalNumberFormat);
end;
result := result * radix;
if result < limit + digit then begin
raise NumberFormatException.create('intParse: ' + msgIllegalNumberFormat);
end;
result := result - digit;
end;
if negative then begin
if i < 2 then begin
raise NumberFormatException.create('intParse: ' + msgIllegalNumberFormat);
end;
exit;
end;
result := -result;
end;
function intToString(value: int; radix: int = 10): AnsiString;
var
negative: boolean;
i: int;
len: int;
negradix: int;
buf: char_Array1d;
begin
negative := value < 0;
i := 32;
len := i + 1;
buf := char_Array1d_create(len);
if (radix > MAX_RADIX) or (radix < MIN_RADIX) then radix := 10;
if not negative then value := -value;
negradix := -radix;
while value <= negradix do begin
buf[i] := getDigitRepresentation(-(value mod radix));
value := value div radix;
dec(i);
end;
buf[i] := getDigitRepresentation(-value);
if negative then begin
dec(i);
buf[i] := '-';
end;
result := AnsiString_create(buf, i, len - i);
end;
function intToUnsignedString(value: int; shift: int): AnsiString;
var
i: int;
len: int;
mask: int;
buf: char_Array1d;
begin
i := 32;
len := i;
mask := (1 shl shift) - 1;
buf := char_Array1d_create(len);
repeat
dec(i);
buf[i] := getDigitRepresentation(value and mask);
value := value shr shift;
until value = 0;
result := AnsiString_create(buf, i, len - i);
end;
function intToBinaryString(value: int): AnsiString;
begin
result := intToUnsignedString(value, 1);
end;
function intToOctalString(value: int): AnsiString;
begin
result := intToUnsignedString(value, 3);
end;
function intToHexString(value: int): AnsiString;
begin
result := intToUnsignedString(value, 4);
end;
function intToFloat(value: int): float; assembler; nostackframe;
asm
cvtsi2ss xmm0, ecx
end;
function intToDouble(value: int): double; assembler; nostackframe;
asm
cvtsi2sd xmm0, ecx
end;
function longBitsToDouble(bits: long): double; assembler; nostackframe;
asm
movq xmm0, rcx
end;
function longByteSwap(value: long): long; assembler; nostackframe;
asm
mov rax, rcx
bswap rax
end;
function longSar(value: long; bits: int): long; assembler; nostackframe;
asm
mov rax, rcx
mov ecx, edx
sar rax, cl
end;
function longAbs(value: long): long; inline;
begin
if value < 0 then begin
result := -value;
end else begin
result := value;
end;
end;
function longMax(value1, value2: long): long; inline;
begin
if value1 < value2 then begin
result := value2;
end else begin
result := value1;
end;
end;
function longMin(value1, value2: long): long; inline;
begin
if value1 < value2 then begin
result := value1;
end else begin
result := value2;
end;
end;
function longBound(minimum, value, maximum: long): long; inline;
begin
result := longMin(longMax(minimum, value), maximum);
end;
function longParse(const str: AnsiString; radix: int = 10): long;
var
negative: boolean;
i: int;
len: int;
limit: long;
digit: long;
mulmin: long;
begin
len := length(str);
if len <= 0 then begin
raise NumberFormatException.create('longParse: ' + msgIllegalNumberFormat);
end;
if radix > MAX_RADIX then begin
raise NumberFormatException.create('longParse: ' + msgIllegalRadix);
end;
if radix < MIN_RADIX then begin
raise NumberFormatException.create('longParse: ' + msgIllegalRadix);
end;
result := 0;
i := 0;
if str[1] = '-' then begin
inc(i);
negative := true;
limit := $8000000000000000;
end else begin
negative := false;
limit := $8000000000000001;
end;
mulmin := limit div radix;
if i < len then begin
digit := getDigit(str[i + 1], radix);
inc(i);
if digit < 0 then begin
raise NumberFormatException.create('longParse: ' + msgIllegalNumberFormat);
end;
result := -digit;
end;
while i < len do begin
digit := getDigit(str[i + 1], radix);
inc(i);
if (digit < 0) or (result < mulmin) then begin
raise NumberFormatException.create('longParse: ' + msgIllegalNumberFormat);
end;
result := result * radix;
if result < limit + digit then begin
raise NumberFormatException.create('longParse: ' + msgIllegalNumberFormat);
end;
result := result - digit;
end;
if negative then begin
if i < 2 then begin
raise NumberFormatException.create('longParse: ' + msgIllegalNumberFormat);
end;
exit;
end;
result := -result;
end;
function longToString(value: long; radix: int = 10): AnsiString;
var
negative: boolean;
i: int;
len: int;
posradix: long;
negradix: long;
buf: char_Array1d;
begin
negative := value < 0;
i := 64;
len := i + 1;
buf := char_Array1d_create(len);
if (radix > MAX_RADIX) or (radix < MIN_RADIX) then radix := 10;
if not negative then value := -value;
posradix := radix;
negradix := -posradix;
while value <= negradix do begin
buf[i] := getDigitRepresentation(int(-(value mod posradix)));
value := value div posradix;
dec(i);
end;
buf[i] := getDigitRepresentation(int(-value));
if negative then begin
dec(i);
buf[i] := '-';
end;
result := AnsiString_create(buf, i, len - i);
end;
function longToUnsignedString(value: long; shift: int): AnsiString;
var
i: int;
len: int;
mask: long;
buf: char_Array1d;
begin
i := 64;
len := i;
mask := (1 shl shift) - 1;
buf := char_Array1d_create(len);
repeat
dec(i);
buf[i] := getDigitRepresentation(int(value and mask));
value := value shr shift;
until value = 0;
result := AnsiString_create(buf, i, len - i);
end;
function longToBinaryString(value: long): AnsiString;
begin
result := longToUnsignedString(value, 1);
end;
function longToOctalString(value: long): AnsiString;
begin
result := longToUnsignedString(value, 3);
end;
function longToHexString(value: long): AnsiString;
begin
result := longToUnsignedString(value, 4);
end;
function longToFloat(value: long): float; assembler; nostackframe;
asm
cvtsi2ss xmm0, rcx
end;
function longToDouble(value: long): double; assembler; nostackframe;
asm
cvtsi2sd xmm0, rcx
end;
function ulongCmp(uvalue1, uvalue2: long): int; assembler; nostackframe;
asm
cmp rcx, rdx
jb @lt
je @eq
mov eax, $01
ret
@lt: mov eax, -$01
ret
@eq: xor eax, eax
end;
function ulongDiv(uvalue1, uvalue2: long): long; assembler; nostackframe;
asm
mov rax, rcx
mov rcx, rdx
xor rdx, rdx
div rcx
end;
function ulongRem(uvalue1, uvalue2: long): long; assembler; nostackframe;
asm
mov rax, rcx
mov rcx, rdx
xor rdx, rdx
div rcx
mov rax, rdx
end;
function ulongToReal(uvalue: long): real; assembler; nostackframe;
asm
cmp rdx, $00
jl @0
push rdx
fild qword[rsp]
jmp @exit
@0: btr rdx, $3f
push rdx
fild qword[rsp]
fld qword[rip+constantPoolDouble-@1+$08]
@1: faddp st(1), st
@exit: fstp tbyte[rcx]
lea rsp, [rsp+$08]
end;
function floatIsNaN(value: float): boolean;
begin
result := value <> value;
end;
function floatIsInfinite(value: float): boolean;
begin
result := (value = FLOAT_POSITIVE_INFINITY) or (value = FLOAT_NEGATIVE_INFINITY);
end;
function floatToIntBits(value: float): int; assembler; nostackframe;
asm
movd eax, xmm0
end;
function floatCmpl(value1, value2: float): int; assembler; nostackframe;
asm
comiss xmm0, xmm1
jp @lt
jc @lt
jz @eq
@gt: mov eax, $01
ret
@lt: mov eax, -$01
ret
@eq: xor eax, eax
end;
function floatCmpg(value1, value2: float): int; assembler; nostackframe;
asm
comiss xmm0, xmm1
jp @gt
jc @lt
jz @eq
@gt: mov eax, $01
ret
@lt: mov eax, -$01
ret
@eq: xor eax, eax
end;
function floatAbs(value: float): float; assembler; nostackframe;
asm
mov eax, $7fffffff
movd xmm1, eax
pand xmm0, xmm1
end;
function floatMax(value1, value2: float): float;
begin
if value1 <> value1 then begin
result := value1;
exit;
end;
if value2 <> value2 then begin
result := value2;
exit;
end;
if (value1 = 0.0) and (value2 = 0.0) and (floatToIntBits(value1) = INT_MIN_VALUE) or (value1 < value2) then begin
result := value2;
exit;
end;
result := value1;
end;
function floatMin(value1, value2: float): float;
begin
if value1 <> value1 then begin
result := value1;
exit;
end;
if value2 <> value2 then begin
result := value2;
exit;
end;
if (value1 = 0.0) and (value2 = 0.0) and (floatToIntBits(value2) = INT_MIN_VALUE) or (value1 > value2) then begin
result := value2;
exit;
end;
result := value1;
end;
function floatMod(value1, value2: float): float; assembler; nostackframe;
asm
lea rsp, [rsp-$10]
movss [rsp], xmm0
movss [rsp+$08], xmm1
fld dword[rsp+$08]
fld dword[rsp]
@loop: fprem
fnstsw ax
test eax, $0400
jnz @loop
fstp st(1)
fstp dword[rsp]
movss xmm0, [rsp]
lea rsp, [rsp+$10]
end;
function floatBound(minimum, value, maximum: float): float;
begin
result := floatMin(floatMax(minimum, value), maximum);
end;
function floatParse(const str: AnsiString): float;
begin
result := floatRepresenter.parseFloat(str);
end;
function floatToString(value: float): AnsiString;
begin
result := floatRepresenter.toString(value);
end;
function floatToInt(value: float): int; assembler; nostackframe;
asm
movss xmm1, xmm0
movss xmm2, dword[rip+constantPoolFloat-@0+$00]
@0: movss xmm3, xmm0
cvttps2dq xmm0, xmm0
cmpss xmm1, xmm1, $07
cmpss xmm2, xmm3, $02
paddd xmm0, xmm2
pand xmm0, xmm1
movd eax, xmm0
end;
function floatToLong(value: float): long; assembler; nostackframe;
asm
cvtss2sd xmm0, xmm0
movsd xmm1, xmm0
movsd xmm2, qword[rip+constantPoolDouble-@0+$08]
@0: movsd xmm3, xmm0
cvttsd2si rax, xmm0
movq xmm0, rax
cmpsd xmm1, xmm1, $07
cmpsd xmm2, xmm3, $02
paddq xmm0, xmm2
pand xmm0, xmm1
movq rax, xmm0
end;
function floatToDouble(value: float): double; assembler; nostackframe;
asm
cvtss2sd xmm0, xmm0
end;
function doubleIsNaN(value: double): boolean;
begin
result := value <> value;
end;
function doubleIsInfinite(value: double): boolean;
begin
result := (value = DOUBLE_POSITIVE_INFINITY) or (value = DOUBLE_NEGATIVE_INFINITY);
end;
function doubleToLongBits(value: double): long; assembler; nostackframe;
asm
movq rax, xmm0
end;
function doubleCmpl(value1, value2: double): int; assembler; nostackframe;
asm
comisd xmm0, xmm1
jp @lt
jc @lt
jz @eq
@gt: mov eax, $01
ret
@lt: mov eax, -$01
ret
@eq: xor eax, eax
end;
function doubleCmpg(value1, value2: double): int; assembler; nostackframe;
asm
comisd xmm0, xmm1
jp @gt
jc @lt
jz @eq
@gt: mov eax, $01
ret
@lt: mov eax, -$01
ret
@eq: xor eax, eax
end;
function doubleAbs(value: double): double; assembler; nostackframe;
asm
mov rax, [rip+constantPoolLong-@0+$08]
@0: movq xmm1, rax
pand xmm0, xmm1
end;
function doubleMax(value1, value2: double): double;
begin
if value1 <> value1 then begin
result := value1;
exit;
end;
if value2 <> value2 then begin
result := value2;
exit;
end;
if (value1 = 0.0) and (value2 = 0.0) and (doubleToLongBits(value1) = LONG_MIN_VALUE) or (value1 < value2) then begin
result := value2;
exit;
end;
result := value1;
end;
function doubleMin(value1, value2: double): double;
begin
if value1 <> value1 then begin
result := value1;
exit;
end;
if value2 <> value2 then begin
result := value2;
exit;
end;
if (value1 = 0.0) and (value2 = 0.0) and (doubleToLongBits(value2) = LONG_MIN_VALUE) or (value1 > value2) then begin
result := value2;
exit;
end;
result := value1;
end;
function doubleMod(value1, value2: double): double; assembler; nostackframe;
asm
lea rsp, [rsp-$10]
movsd [rsp], xmm0
movsd [rsp+$08], xmm1
fld qword[rsp+$08]
fld qword[rsp]
@loop: fprem
fnstsw ax
test eax, $0400
jnz @loop
fstp st(1)
fstp qword[rsp]
movsd xmm0, [rsp]
lea rsp, [rsp+$10]
end;
function doubleBound(minimum, value, maximum: double): double;
begin
result := doubleMin(doubleMax(minimum, value), maximum);
end;
function doubleParse(const str: AnsiString): double;
begin
result := doubleRepresenter.parseDouble(str);
end;
function doubleToString(value: double): AnsiString;
begin
result := doubleRepresenter.toString(value);
end;
function doubleToInt(value: double): int; assembler; nostackframe;
asm
movsd xmm1, xmm0
movsd xmm2, qword[rip+constantPoolDouble-@0+$00]
@0: movsd xmm3, xmm0
cvttpd2dq xmm0, xmm0
cmpsd xmm1, xmm1, $07
cmpsd xmm2, xmm3, $02
paddd xmm0, xmm2
pand xmm0, xmm1
movd eax, xmm0
end;
function doubleToLong(value: double): long; assembler; nostackframe;
asm
movsd xmm1, xmm0
movsd xmm2, qword[rip+constantPoolDouble-@0+$08]
@0: movsd xmm3, xmm0
cvttsd2si rax, xmm0
movq xmm0, rax
cmpsd xmm1, xmm1, $07
cmpsd xmm2, xmm3, $02
paddq xmm0, xmm2
pand xmm0, xmm1
movq rax, xmm0
end;
function doubleToFloat(value: double): float; assembler; nostackframe;
asm
cvtsd2ss xmm0, xmm0
end;
function REAL_NAN: real; inline;
begin
result := realBuild($ffff, $c000000000000000);
end;
function REAL_POSITIVE_INFINITY: real; inline;
begin
result := realBuild($7fff, $8000000000000000);
end;
function REAL_NEGATIVE_INFINITY: real; inline;
begin
result := realBuild($ffff, $8000000000000000);
end;
function REAL_MIN_VALUE: real; inline;
begin
result := realBuild($0000, $0000000000000001);
end;
function REAL_MAX_VALUE: real; inline;
begin
result := realBuild($7ffe, $ffffffffffffffff);
end;
function realIsNaN(const value: real): boolean;
begin
result := value <> value;
end;
function realIsInfinite(const value: real): boolean;
begin
result := (value = REAL_POSITIVE_INFINITY) or (value = REAL_NEGATIVE_INFINITY);
end;
function realBuild(exponent: int; significand: long): real; inline;
begin
RealStruct(result).significand := significand;
RealStruct(result).exponent := short(exponent);
end;
function realSignificand(const value: real): long; inline;
begin
result := RealStruct(value).significand;
end;
function realExponent(const value: real): int; inline;
begin
result := RealStruct(value).exponent;
end;
function realCmpl(const value1, value2: real): int; assembler; nostackframe;
asm
fld tbyte[rdx]
fld tbyte[rcx]
fcomip st, st(1)
ffree st
fincstp
jp @lt
jc @lt
jz @eq
@gt: mov eax, $01
ret
@lt: mov eax, -$01
ret
@eq: xor eax, eax
end;
function realCmpg(const value1, value2: real): int; assembler; nostackframe;
asm
fld tbyte[rdx]
fld tbyte[rcx]
fcomip st, st(1)
ffree st
fincstp
jp @gt
jc @lt
jz @eq
@gt: mov eax, $01
ret
@lt: mov eax, -$01
ret
@eq: xor eax, eax
end;
function realAbs(const value: real): real; assembler; nostackframe;
asm
mov r8, [rdx]
movsx eax, word[rdx+$08]
and eax, $7fff
mov [rcx], r8
mov [rcx+$08], ax
end;
function realMax(const value1, value2: real): real;
begin
if value1 <> value1 then begin
result := value1;
exit;
end;
if value2 <> value2 then begin
result := value2;
exit;
end;
if (value1 = 0.0) and (value2 = 0.0) and (realExponent(value1) = SHORT_MIN_VALUE) and (realSignificand(value1) = 0) or (value1 < value2) then begin
result := value2;
exit;
end;
result := value1;
end;
function realMin(const value1, value2: real): real;
begin
if value1 <> value1 then begin
result := value1;
exit;
end;
if value2 <> value2 then begin
result := value2;
exit;
end;
if (value1 = 0.0) and (value2 = 0.0) and (realExponent(value2) = SHORT_MIN_VALUE) and (realSignificand(value2) = 0) or (value1 > value2) then begin
result := value2;
exit;
end;
result := value1;
end;
function realMod(const value1, value2: real): real; assembler; nostackframe;
asm
fld tbyte[r8]
fld tbyte[rdx]
@loop: fprem
fnstsw ax
test eax, $0400
jnz @loop
fstp st(1)
fstp tbyte[rcx]
end;
function realBound(const minimum, value, maximum: real): real;
begin
result := realMin(realMax(minimum, value), maximum);
end;
function realParse(const str: AnsiString): real;
begin
result := realRepresenter.parseReal(str);
end;
function realToString(const value: real): AnsiString;
begin
result := realRepresenter.toString(value);
end;
function realToInt(const value: real): int; assembler; nostackframe;
asm
fld tbyte[rcx]
fild qword[rip+constantPoolLong-@0+$00]
@0: fcomip st, st(1)
jnp @1
ffree st
fincstp
xor eax, eax
ret
@1: ja @3
ffree st
fincstp
mov eax, $7fffffff
ret
@3: lea rsp, [rsp-$08]
fisttp dword[rsp]
pop rax
end;
function realToLong(const value: real): long; assembler; nostackframe;
asm
fld tbyte[rcx]
fild qword[rip+constantPoolLong-@0+$08]
@0: fcomip st, st(1)
jnp @1
ffree st
fincstp
xor eax, eax
ret
@1: ja @3
ffree st
fincstp
mov rax, [rip+constantPoolLong-@2+$08]
@2: ret
@3: lea rsp, [rsp-$08]
fisttp qword[rsp]
pop rax
end;
function realToFloat(const value: real): float; assembler; nostackframe;
asm
lea rsp, [rsp-$08]
fld tbyte[rcx]
fstp dword[rsp]
movss xmm0, [rsp]
lea rsp, [rsp+$08]
end;
function realToDouble(const value: real): double; assembler; nostackframe;
asm
lea rsp, [rsp-$08]
fld tbyte[rcx]
fstp qword[rsp]
movsd xmm0, [rsp]
lea rsp, [rsp+$08]
end;
function stringToUTF8(const str: UnicodeString): AnsiString;
var
i: int;
slen: int;
rlen: int;
capa: int;
code: int;
char1: int;
char2: int;
buf: byte_Array1d;
begin
slen := length(str);
if slen <= 0 then begin
result := '';
exit;
end;
rlen := 0;
capa := int(longMin(long(slen) shl 2, INT_MAX_VALUE));
buf := byte_Array1d_create(capa);
i := 0;
while i < slen do begin
char1 := int(str[i + 1]);
inc(i);
if (char1 < $d800) or (char1 >= $e000) then begin
code := char1;
end else
if char1 >= $dc00 then begin
code := char1 and $03ff;
end else begin
char2 := 0;
if i < slen then begin
char2 := int(str[i + 1]);
if (char2 < $dc00) or (char2 >= $e000) then begin
char2 := 0;
end else begin
inc(i);
end;
end;
code := ((char1 and $03ff) shl 10) + (char2 and $03ff) + $010000;
end;
if (code >= $000001) and (code < $000080) then begin
if rlen >= capa then break;
buf[rlen] := byte(code);
inc(rlen);
end else
if (code >= $000000) and (code < $000800) then begin
if rlen >= capa - 1 then break;
buf[rlen] := byte($c0 + (code shr 6));
buf[rlen + 1] := byte($80 + (code and $3f));
inc(rlen, 2);
end else
if (code >= $000800) and (code < $010000) then begin
if rlen >= capa - 2 then break;
buf[rlen] := byte($e0 + (code shr 12));
buf[rlen + 1] := byte($80 + ((code shr 6) and $3f));
buf[rlen + 2] := byte($80 + (code and $3f));
inc(rlen, 3);
end else
if (code >= $010000) and (code < $200000) then begin
if rlen >= capa - 3 then break;
buf[rlen] := byte($f0 + (code shr 18));
buf[rlen + 1] := byte($80 + ((code shr 12) and $3f));
buf[rlen + 2] := byte($80 + ((code shr 6) and $3f));
buf[rlen + 3] := byte($80 + (code and $3f));
inc(rlen, 4);
end;
end;
result := AnsiString_create(buf, 0, rlen);
end;
function stringToUTF16(const str: AnsiString): UnicodeString;
var
i: int;
slen: int;
rlen: int;
capa: int;
code: int;
char1: int;
char2: int;
char3: int;
char4: int;
buf: short_Array1d;
begin
slen := length(str);
if slen <= 0 then begin
result := '';
exit;
end;
rlen := 0;
capa := int(longMin(long(slen) shl 1, INT_MAX_VALUE));
buf := short_Array1d_create(capa);
i := 0;
while i < slen do begin
char1 := int(str[i + 1]);
inc(i);
if (char1 >= $00) and (char1 < $80) then begin
if rlen >= capa then break;
buf[rlen] := short(char1);
inc(rlen);
end else
if (char1 >= $c0) and (char1 < $e0) then begin
if rlen >= capa then break;
char2 := 0;
if i < slen then begin
char2 := int(str[i + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(i);
end;
end;
buf[rlen] := short(((char1 and $1f) shl 6) or (char2 and $3f));
inc(rlen);
end else
if (char1 >= $e0) and (char1 < $f0) then begin
char2 := 0;
char3 := 0;
if i < slen then begin
char2 := int(str[i + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(i);
end;
end;
if i < slen then begin
char3 := int(str[i + 1]);
if (char3 and $c0) <> $80 then begin
char3 := 0;
end else begin
inc(i);
end;
end;
code := ((char1 and $0f) shl 12) or ((char2 and $3f) shl 6) or (char3 and $3f);
if (code < $d800) or (code >= $e000) then begin
if rlen >= capa then break;
buf[rlen] := short(code);
inc(rlen);
end;
end else
if (char1 >= $f0) and (char1 < $f8) then begin
char2 := 0;
char3 := 0;
char4 := 0;
if i < slen then begin
char2 := int(str[i + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(i);
end;
end;
if i < slen then begin
char3 := int(str[i + 1]);
if (char3 and $c0) <> $80 then begin
char3 := 0;
end else begin
inc(i);
end;
end;
if i < slen then begin
char4 := int(str[i + 1]);
if (char4 and $c0) <> $80 then begin
char4 := 0;
end else begin
inc(i);
end;
end;
code := ((char1 and $07) shl 18) or ((char2 and $3f) shl 12) or ((char3 and $3f) shl 6) or (char4 and $3f);
if (code < $00d800) or (code >= $00e000) and (code < $010000) then begin
if rlen >= capa then break;
buf[rlen] := short(code);
inc(rlen);
end else
if (code >= $010000) and (code < $110000) then begin
if rlen >= capa - 1 then break;
dec(code, $010000);
buf[rlen] := short($d800 + (code shr 10));
buf[rlen + 1] := short($dc00 + (code and $03ff));
inc(rlen, 2);
end;
end;
end;
result := UnicodeString_create(buf, 0, rlen);
end;
function stringBuildUTF8(const charCodes: int_Array1d; offset, length: int): AnsiString;
var
i: int;
rlen: int;
capa: int;
code: int;
buf: byte_Array1d;
begin
arrayCheckBounds('stringBuildUTF8', system.length(charCodes), offset, length);
rlen := 0;
capa := int(longMin(long(length) * 6, INT_MAX_VALUE));
buf := byte_Array1d_create(capa);
for i := offset to offset + length - 1 do begin
code := charCodes[i];
if (code >= $00000001) and (code < $00000080) then begin
if rlen >= capa then break;
buf[rlen] := byte(code);
inc(rlen);
end else
if (code >= $00000000) and (code < $00000800) then begin
if rlen >= capa - 1 then break;
buf[rlen] := byte($c0 + (code shr 6));
buf[rlen + 1] := byte($80 + (code and $3f));
inc(rlen, 2);
end else
if (code >= $00000800) and (code < $00010000) then begin
if rlen >= capa - 2 then break;
buf[rlen] := byte($e0 + (code shr 12));
buf[rlen + 1] := byte($80 + ((code shr 6) and $3f));
buf[rlen + 2] := byte($80 + (code and $3f));
inc(rlen, 3);
end else
if (code >= $00010000) and (code < $00200000) then begin
if rlen >= capa - 3 then break;
buf[rlen] := byte($f0 + (code shr 18));
buf[rlen + 1] := byte($80 + ((code shr 12) and $3f));
buf[rlen + 2] := byte($80 + ((code shr 6) and $3f));
buf[rlen + 3] := byte($80 + (code and $3f));
inc(rlen, 4);
end else
if (code >= $00200000) and (code < $04000000) then begin
if rlen >= capa - 4 then break;
buf[rlen] := byte($f8 + (code shr 24));
buf[rlen + 1] := byte($80 + ((code shr 18) and $3f));
buf[rlen + 2] := byte($80 + ((code shr 12) and $3f));
buf[rlen + 3] := byte($80 + ((code shr 6) and $3f));
buf[rlen + 4] := byte($80 + (code and $3f));
inc(rlen, 5);
end else begin
if rlen >= capa - 5 then break;
buf[rlen] := byte($fc + (code shr 30));
buf[rlen + 1] := byte($80 + ((code shr 24) and $3f));
buf[rlen + 2] := byte($80 + ((code shr 18) and $3f));
buf[rlen + 3] := byte($80 + ((code shr 12) and $3f));
buf[rlen + 4] := byte($80 + ((code shr 6) and $3f));
buf[rlen + 5] := byte($80 + (code and $3f));
inc(rlen, 6);
end;
end;
result := AnsiString_create(buf, 0, rlen);
end;
function stringBuildUTF16(const charCodes: int_Array1d; offset, length: int): UnicodeString;
var
i: int;
rlen: int;
capa: int;
code: int;
buf: short_Array1d;
begin
arrayCheckBounds('stringBuildUTF16', system.length(charCodes), offset, length);
rlen := 0;
capa := int(longMin(long(length) shl 1, INT_MAX_VALUE));
buf := short_Array1d_create(capa);
for i := offset to offset + length - 1 do begin
code := charCodes[i];
if (code >= $000000) and (code < $00d800) or (code >= $00e000) and (code < $010000) then begin
if rlen >= capa then break;
buf[rlen] := short(code);
inc(rlen);
end else
if (code >= $010000) and (code < $110000) then begin
if rlen >= capa - 1 then break;
dec(code, $010000);
buf[rlen] := short($d800 + (code shr 10));
buf[rlen + 1] := short($dc00 + (code and $03ff));
inc(rlen, 2);
end;
end;
result := UnicodeString_create(buf, 0, rlen);
end;
function stringToCharCodes(const str: AnsiString): int_Array1d;
var
i: int;
slen: int;
rlen: int;
char1: int;
char2: int;
char3: int;
char4: int;
char5: int;
char6: int;
buf: int_Array1d;
begin
slen := length(str);
if slen <= 0 then begin
result := int_Array1d_create(0);
exit;
end;
rlen := 0;
buf := int_Array1d_create(slen);
i := 0;
while i < slen do begin
char1 := int(str[i + 1]);
inc(i);
if (char1 >= $00) and (char1 < $80) then begin
buf[rlen] := char1;
inc(rlen);
end else
if (char1 >= $c0) and (char1 < $e0) then begin
char2 := 0;
if i < slen then begin
char2 := int(str[i + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(i);
end;
end;
buf[rlen] := ((char1 and $1f) shl 6) or (char2 and $3f);
inc(rlen);
end else
if (char1 >= $e0) and (char1 < $f0) then begin
char2 := 0;
char3 := 0;
if i < slen then begin
char2 := int(str[i + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(i);
end;
end;
if i < slen then begin
char3 := int(str[i + 1]);
if (char3 and $c0) <> $80 then begin
char3 := 0;
end else begin
inc(i);
end;
end;
buf[rlen] := ((char1 and $0f) shl 12) or ((char2 and $3f) shl 6) or (char3 and $3f);
inc(rlen);
end else
if (char1 >= $f0) and (char1 < $f8) then begin
char2 := 0;
char3 := 0;
char4 := 0;
if i < slen then begin
char2 := int(str[i + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(i);
end;
end;
if i < slen then begin
char3 := int(str[i + 1]);
if (char3 and $c0) <> $80 then begin
char3 := 0;
end else begin
inc(i);
end;
end;
if i < slen then begin
char4 := int(str[i + 1]);
if (char4 and $c0) <> $80 then begin
char4 := 0;
end else begin
inc(i);
end;
end;
buf[rlen] := ((char1 and $07) shl 18) or ((char2 and $3f) shl 12) or ((char3 and $3f) shl 6) or (char4 and $3f);
inc(rlen);
end else
if (char1 >= $f8) and (char1 < $fc) then begin
char2 := 0;
char3 := 0;
char4 := 0;
char5 := 0;
if i < slen then begin
char2 := int(str[i + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(i);
end;
end;
if i < slen then begin
char3 := int(str[i + 1]);
if (char3 and $c0) <> $80 then begin
char3 := 0;
end else begin
inc(i);
end;
end;
if i < slen then begin
char4 := int(str[i + 1]);
if (char4 and $c0) <> $80 then begin
char4 := 0;
end else begin
inc(i);
end;
end;
if i < slen then begin
char5 := int(str[i + 1]);
if (char5 and $c0) <> $80 then begin
char5 := 0;
end else begin
inc(i);
end;
end;
buf[rlen] := ((char1 and $03) shl 24) or ((char2 and $3f) shl 18) or ((char3 and $3f) shl 12) or ((char4 and $3f) shl 6) or (char5 and $3f);
inc(rlen);
end else
if char1 >= $fc then begin
char2 := 0;
char3 := 0;
char4 := 0;
char5 := 0;
char6 := 0;
if i < slen then begin
char2 := int(str[i + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(i);
end;
end;
if i < slen then begin
char3 := int(str[i + 1]);
if (char3 and $c0) <> $80 then begin
char3 := 0;
end else begin
inc(i);
end;
end;
if i < slen then begin
char4 := int(str[i + 1]);
if (char4 and $c0) <> $80 then begin
char4 := 0;
end else begin
inc(i);
end;
end;
if i < slen then begin
char5 := int(str[i + 1]);
if (char5 and $c0) <> $80 then begin
char5 := 0;
end else begin
inc(i);
end;
end;
if i < slen then begin
char6 := int(str[i + 1]);
if (char6 and $c0) <> $80 then begin
char6 := 0;
end else begin
inc(i);
end;
end;
buf[rlen] := (char1 shl 30) or ((char2 and $3f) shl 24) or ((char3 and $3f) shl 18) or ((char4 and $3f) shl 12) or ((char5 and $3f) shl 6) or (char6 and $3f);
inc(rlen);
end;
end;
if slen = rlen then begin
result := buf;
exit;
end;
result := int_Array1d_create(rlen);
arraycopyPrimitives(buf, 0, result, 0, rlen);
end;
function stringToCharCodes(const str: UnicodeString): int_Array1d;
var
i: int;
slen: int;
rlen: int;
code: int;
char1: int;
char2: int;
buf: int_Array1d;
begin
slen := length(str);
if slen <= 0 then begin
result := int_Array1d_create(0);
exit;
end;
rlen := 0;
buf := int_Array1d_create(slen);
i := 0;
while i < slen do begin
char1 := int(str[i + 1]);
inc(i);
if (char1 < $d800) or (char1 >= $e000) then begin
code := char1;
end else
if char1 >= $dc00 then begin
code := char1 and $03ff;
end else begin
char2 := 0;
if i < slen then begin
char2 := int(str[i + 1]);
if (char2 < $dc00) or (char2 >= $e000) then begin
char2 := 0;
end else begin
inc(i);
end;
end;
code := ((char1 and $03ff) shl 10) + (char2 and $03ff) + $010000;
end;
buf[rlen] := code;
inc(rlen);
end;
if slen = rlen then begin
result := buf;
exit;
end;
result := int_Array1d_create(rlen);
arraycopyPrimitives(buf, 0, result, 0, rlen);
end;
function stringToCharArray(const str: AnsiString): char_Array1d;
begin
result := char_Array1d_create(length(str));
system.move(str[1], result[0], length(result) * sizeOf(char));
end;
function stringToWCharArray(const str: UnicodeString): wchar_Array1d;
begin
result := wchar_Array1d_create(length(str));
system.move(str[1], result[0], length(result) * sizeOf(wchar));
end;
function stringToByteArray(const str: AnsiString): byte_Array1d;
begin
result := byte_Array1d_create(length(str));
system.move(str[1], result[0], length(result) * sizeOf(byte));
end;
function stringToShortArray(const str: UnicodeString): short_Array1d;
begin
result := short_Array1d_create(length(str));
system.move(str[1], result[0], length(result) * sizeOf(short));
end;
function stringToLowerCase(const str: AnsiString): AnsiString;
label
label0;
var
ci: char;
i: int;
len: int;
buf: char_Array1d;
begin
len := length(str);
i := 0;
begin
while i < len do begin
ci := str[i + 1];
if ci <> charToLowerCase(ci) then goto label0;
inc(i);
end;
result := str;
exit;
end;
label0:
buf := stringToCharArray(str);
while i < len do begin
buf[i] := charToLowerCase(buf[i]);
inc(i);
end;
result := AnsiString_create(buf, 0, len);
end;
function stringToLowerCase(const str: UnicodeString): UnicodeString;
label
label0;
var
ci: wchar;
i: int;
len: int;
buf: wchar_Array1d;
begin
len := length(str);
i := 0;
begin
while i < len do begin
ci := str[i + 1];
if ci <> charToLowerCase(ci) then goto label0;
inc(i);
end;
result := str;
exit;
end;
label0:
buf := stringToWCharArray(str);
while i < len do begin
buf[i] := charToLowerCase(buf[i]);
inc(i);
end;
result := UnicodeString_create(buf, 0, len);
end;
function stringToUpperCase(const str: AnsiString): AnsiString;
label
label0;
var
ci: char;
i: int;
len: int;
buf: char_Array1d;
begin
len := length(str);
i := 0;
begin
while i < len do begin
ci := str[i + 1];
if ci <> charToUpperCase(ci) then goto label0;
inc(i);
end;
result := str;
exit;
end;
label0:
buf := stringToCharArray(str);
while i < len do begin
buf[i] := charToUpperCase(buf[i]);
inc(i);
end;
result := AnsiString_create(buf, 0, len);
end;
function stringToUpperCase(const str: UnicodeString): UnicodeString;
label
label0;
var
ci: wchar;
i: int;
len: int;
buf: wchar_Array1d;
begin
len := length(str);
i := 0;
begin
while i < len do begin
ci := str[i + 1];
if ci <> charToUpperCase(ci) then goto label0;
inc(i);
end;
result := str;
exit;
end;
label0:
buf := stringToWCharArray(str);
while i < len do begin
buf[i] := charToUpperCase(buf[i]);
inc(i);
end;
result := UnicodeString_create(buf, 0, len);
end;
function stringReplace(const str: AnsiString; oldCharacter, newCharacter: char): AnsiString;
var
i: int;
len: int;
buf: char_Array1d;
begin
if oldCharacter = newCharacter then begin
result := str;
exit;
end;
len := length(str);
i := 0;
while (i < len) and (str[i + 1] <> oldCharacter) do begin
inc(i);
end;
if i >= len then begin
result := str;
exit;
end;
buf := stringToCharArray(str);
while i < len do begin
if buf[i] = oldCharacter then buf[i] := newCharacter;
inc(i);
end;
result := AnsiString_create(buf, 0, len);
end;
function stringReplace(const str: UnicodeString; oldCharacter, newCharacter: wchar): UnicodeString;
var
i: int;
len: int;
buf: wchar_Array1d;
begin
if oldCharacter = newCharacter then begin
result := str;
exit;
end;
len := length(str);
i := 0;
while (i < len) and (str[i + 1] <> oldCharacter) do begin
inc(i);
end;
if i >= len then begin
result := str;
exit;
end;
buf := stringToWCharArray(str);
while i < len do begin
if buf[i] = oldCharacter then buf[i] := newCharacter;
inc(i);
end;
result := UnicodeString_create(buf, 0, len);
end;
function stringStartsWith(const prefix, str: AnsiString; position: int): boolean;
var
i: int;
j: int;
len: int;
begin
dec(position);
len := length(prefix);
if (position < 0) or (position > length(str) - len) then begin
result := false;
exit;
end;
i := 0;
j := position;
while i < len do begin
if prefix[i + 1] <> str[j + 1] then begin
result := false;
exit;
end;
inc(i);
inc(j);
end;
result := true;
end;
function stringStartsWith(const prefix, str: UnicodeString; position: int): boolean;
var
i: int;
j: int;
len: int;
begin
dec(position);
len := length(prefix);
if (position < 0) or (position > length(str) - len) then begin
result := false;
exit;
end;
i := 0;
j := position;
while i < len do begin
if prefix[i + 1] <> str[j + 1] then begin
result := false;
exit;
end;
inc(i);
inc(j);
end;
result := true;
end;
function stringEndsWith(const suffix, str: AnsiString): boolean;
begin
result := stringStartsWith(suffix, str, length(str) - length(suffix) + 1);
end;
function stringEndsWith(const suffix, str: UnicodeString): boolean;
begin
result := stringStartsWith(suffix, str, length(str) - length(suffix) + 1);
end;
function stringIndexOf(const prefix, str: AnsiString; startFromIndex: int): int;
label
label0;
var
first: char;
len: int;
lim: int;
i: int;
j: int;
begin
dec(startFromIndex);
len := length(prefix);
lim := length(str) - len;
if startFromIndex < 0 then startFromIndex := 0;
if startFromIndex > lim then begin
result := 0;
exit;
end;
if len <= 0 then begin
result := startFromIndex + 1;
exit;
end;
first := prefix[1];
repeat
if str[startFromIndex + 1] = first then begin
i := 1;
j := startFromIndex + 1;
while i < len do begin
if prefix[i + 1] <> str[j + 1] then goto label0;
inc(i);
inc(j);
end;
result := startFromIndex + 1;
exit;
end;
label0:
inc(startFromIndex);
until startFromIndex > lim;
result := 0;
end;
function stringIndexOf(const prefix, str: UnicodeString; startFromIndex: int): int;
label
label0;
var
first: wchar;
len: int;
lim: int;
i: int;
j: int;
begin
dec(startFromIndex);
len := length(prefix);
lim := length(str) - len;
if startFromIndex < 0 then startFromIndex := 0;
if startFromIndex > lim then begin
result := 0;
exit;
end;
if len <= 0 then begin
result := startFromIndex + 1;
exit;
end;
first := prefix[1];
repeat
if str[startFromIndex + 1] = first then begin
i := 1;
j := startFromIndex + 1;
while i < len do begin
if prefix[i + 1] <> str[j + 1] then goto label0;
inc(i);
inc(j);
end;
result := startFromIndex + 1;
exit;
end;
label0:
inc(startFromIndex);
until startFromIndex > lim;
result := 0;
end;
function stringLastIndexOf(const prefix, str: AnsiString; startFromIndex: int): int;
label
label0;
var
first: char;
len: int;
lim: int;
i: int;
j: int;
begin
dec(startFromIndex);
len := length(prefix);
lim := length(str) - len;
if startFromIndex > lim then startFromIndex := lim;
if startFromIndex < 0 then begin
result := 0;
exit;
end;
if len <= 0 then begin
result := startFromIndex + 1;
exit;
end;
first := prefix[1];
repeat
if str[startFromIndex + 1] = first then begin
i := 1;
j := startFromIndex + 1;
while i < len do begin
if prefix[i + 1] <> str[j + 1] then goto label0;
inc(i);
inc(j);
end;
result := startFromIndex + 1;
exit;
end;
label0:
dec(startFromIndex);
until startFromIndex < 0;
result := 0;
end;
function stringLastIndexOf(const prefix, str: UnicodeString; startFromIndex: int): int;
label
label0;
var
first: wchar;
len: int;
lim: int;
i: int;
j: int;
begin
dec(startFromIndex);
len := length(prefix);
lim := length(str) - len;
if startFromIndex > lim then startFromIndex := lim;
if startFromIndex < 0 then begin
result := 0;
exit;
end;
if len <= 0 then begin
result := startFromIndex + 1;
exit;
end;
first := prefix[1];
repeat
if str[startFromIndex + 1] = first then begin
i := 1;
j := startFromIndex + 1;
while i < len do begin
if prefix[i + 1] <> str[j + 1] then goto label0;
inc(i);
inc(j);
end;
result := startFromIndex + 1;
exit;
end;
label0:
dec(startFromIndex);
until startFromIndex < 0;
result := 0;
end;
function stringTrim(const str: AnsiString): AnsiString;
var
i: int;
j: int;
len: int;
begin
len := length(str);
if len <= 0 then begin
result := '';
exit;
end;
i := 0;
while (i < len) and (str[i + 1] <= #$20) do begin
inc(i);
end;
j := len - 1;
while (j >= i) and (str[j + 1] <= #$20) do begin
dec(j);
end;
if j < i then begin
result := '';
exit;
end;
result := stringCopy(str, i + 1, j + 2);
end;
function stringTrim(const str: UnicodeString): UnicodeString;
var
i: int;
j: int;
len: int;
begin
len := length(str);
if len <= 0 then begin
result := '';
exit;
end;
i := 0;
while (i < len) and (str[i + 1] <= #$0020) do begin
inc(i);
end;
j := len - 1;
while (j >= i) and (str[j + 1] <= #$0020) do begin
dec(j);
end;
if j < i then begin
result := '';
exit;
end;
result := stringCopy(str, i + 1, j + 2);
end;
function stringCopy(const str: AnsiString): AnsiString;
var
len: int;
begin
len := length(str);
result := AnsiString_create(len);
system.move(str[1], result[1], len * sizeOf(char));
end;
function stringCopy(const str: AnsiString; beginIndex: int): AnsiString;
var
len: int;
begin
dec(beginIndex);
len := length(str);
if (beginIndex < 0) or (beginIndex > len) then begin
raise StringIndexOutOfBoundsException.create('stringCopy: ' + msgStringIndexOutOfBounds);
end;
if beginIndex = 0 then begin
result := str;
exit;
end;
if beginIndex = len then begin
result := '';
exit;
end;
dec(len, beginIndex);
result := AnsiString_create(len);
system.move(str[beginIndex + 1], result[1], len * sizeOf(char));
end;
function stringCopy(const str: AnsiString; beginIndex, endIndex: int): AnsiString;
var
len: int;
begin
dec(endIndex);
dec(beginIndex);
len := length(str);
if ((beginIndex or endIndex) < 0) or (beginIndex > len) or (endIndex > len) or (beginIndex > endIndex) then begin
raise StringIndexOutOfBoundsException.create('stringCopy: ' + msgStringIndexOutOfBounds);
end;
if endIndex - beginIndex = len then begin
result := str;
exit;
end;
if beginIndex = endIndex then begin
result := '';
exit;
end;
len := endIndex - beginIndex;
result := AnsiString_create(len);
system.move(str[beginIndex + 1], result[1], len * sizeOf(char));
end;
function stringCopy(const str: UnicodeString): UnicodeString;
var
len: int;
begin
len := length(str);
result := UnicodeString_create(len);
system.move(str[1], result[1], len * sizeOf(wchar));
end;
function stringCopy(const str: UnicodeString; beginIndex: int): UnicodeString;
var
len: int;
begin
dec(beginIndex);
len := length(str);
if (beginIndex < 0) or (beginIndex > len) then begin
raise StringIndexOutOfBoundsException.create('stringCopy: ' + msgStringIndexOutOfBounds);
end;
if beginIndex = 0 then begin
result := str;
exit;
end;
if beginIndex = len then begin
result := '';
exit;
end;
dec(len, beginIndex);
result := UnicodeString_create(len);
system.move(str[beginIndex + 1], result[1], len * sizeOf(wchar));
end;
function stringCopy(const str: UnicodeString; beginIndex, endIndex: int): UnicodeString;
var
len: int;
begin
dec(endIndex);
dec(beginIndex);
len := length(str);
if ((beginIndex or endIndex) < 0) or (beginIndex > len) or (endIndex > len) or (beginIndex > endIndex) then begin
raise StringIndexOutOfBoundsException.create('stringCopy: ' + msgStringIndexOutOfBounds);
end;
if endIndex - beginIndex = len then begin
result := str;
exit;
end;
if beginIndex = endIndex then begin
result := '';
exit;
end;
len := endIndex - beginIndex;
result := UnicodeString_create(len);
system.move(str[beginIndex + 1], result[1], len * sizeOf(wchar));
end;
function stringSplit(const str: AnsiString): AnsiString_Array1d;
var
character: char;
boundsLength: int;
beginIndex: int;
endIndex: int;
thisLength: int;
index: int;
start: int;
length: int;
bounds: long;
thisChars: PChar;
boundsData: long_Array1d;
boundsNew: long_Array1d;
splited: AnsiString_Array1d;
begin
boundsLength := 0;
boundsData := long_Array1d_create(15);
thisLength := system.length(str);
thisChars := PChar(str);
beginIndex := 0;
while beginIndex <= thisLength do begin
character := #0;
endIndex := beginIndex;
while endIndex < thisLength do begin
character := thisChars[endIndex];
if (character = #$0d) or (character = #$0a) then break;
inc(endIndex);
end;
if boundsLength = system.length(boundsData) then begin
boundsNew := long_Array1d_create(int((boundsLength shl 1) + 1));
arraycopyPrimitives(boundsData, 0, boundsNew, 0, boundsLength);
boundsData := boundsNew;
end;
boundsData[boundsLength] := (long(beginIndex) and $00000000ffffffff) + (long(endIndex - beginIndex) shl 32);
inc(boundsLength);
beginIndex := endIndex + 1;
if (character = #$0d) and (beginIndex < thisLength) and (thisChars[beginIndex] = #$0a) then inc(beginIndex);
end;
splited := AnsiString_Array1d_create(boundsLength);
for index := boundsLength - 1 downto 0 do begin
bounds := boundsData[index];
start := int(bounds);
length := int(bounds shr 32);
if length <= 0 then begin
splited[index] := '';
end else begin
splited[index] := stringCopy(str, start + 1, start + length + 1);
end;
end;
result := splited;
end;
function stringSplit(const str: UnicodeString): UnicodeString_Array1d;
var
character: wchar;
boundsLength: int;
beginIndex: int;
endIndex: int;
thisLength: int;
index: int;
start: int;
length: int;
bounds: long;
thisChars: PWideChar;
boundsData: long_Array1d;
boundsNew: long_Array1d;
splited: UnicodeString_Array1d;
begin
boundsLength := 0;
boundsData := long_Array1d_create(15);
thisLength := system.length(str);
thisChars := PWideChar(str);
beginIndex := 0;
while beginIndex <= thisLength do begin
character := #0;
endIndex := beginIndex;
while endIndex < thisLength do begin
character := thisChars[endIndex];
if (character = #$0d) or (character = #$0a) then break;
inc(endIndex);
end;
if boundsLength = system.length(boundsData) then begin
boundsNew := long_Array1d_create(int((boundsLength shl 1) + 1));
arraycopyPrimitives(boundsData, 0, boundsNew, 0, boundsLength);
boundsData := boundsNew;
end;
boundsData[boundsLength] := (long(beginIndex) and $00000000ffffffff) + (long(endIndex - beginIndex) shl 32);
inc(boundsLength);
beginIndex := endIndex + 1;
if (character = #$0d) and (beginIndex < thisLength) and (thisChars[beginIndex] = #$0a) then inc(beginIndex);
end;
splited := UnicodeString_Array1d_create(boundsLength);
for index := boundsLength - 1 downto 0 do begin
bounds := boundsData[index];
start := int(bounds);
length := int(bounds shr 32);
if length <= 0 then begin
splited[index] := '';
end else begin
splited[index] := stringCopy(str, start + 1, start + length + 1);
end;
end;
result := splited;
end;
{$IFDEF WINDOWS}
function systemGetTickCount(): long;
begin
result := long(windows.getTickCount64());
end;
function systemGetCurrentDirectory(): UnicodeString;
var
dir: PWideChar;
begin
dir := getMemory($0400);
try
getCurrentDirectoryW($0200, dir);
result := UnicodeString(dir);
finally
freeMemory(dir);
end;
end;
function systemGetCommandLine(): UnicodeString_Array1d;
var
f: boolean;
i: int;
b: int;
cnt: int;
len: int;
line: UnicodeString;
module: PWideChar;
begin
line := UnicodeString(getCommandLineW());
f := false;
cnt := 0;
len := length(line);
for i := 0 to len - 1 do begin
if line[i + 1] = '"' then begin
f := f = false;
end;
if (f = false) and (i > 0) and (line[i] > #$0020) and (line[i + 1] = #$0020) then begin
inc(cnt);
end;
end;
if (len > 0) and (line[len] > #$0020) then begin
inc(cnt);
end;
result := UnicodeString_Array1d_create(cnt);
f := false;
cnt := 0;
b := 0;
for i := 0 to len - 1 do begin
if (f = false) and (line[i + 1] > #$0020) and ((i > 0) and (line[i] = #$0020) or (i = 0)) then begin
b := i;
end;
if line[i + 1] = '"' then begin
f := f = false;
end;
if (f = false) and (line[i + 1] > #$0020) and ((i < len - 1) and (line[i + 2] = #$0020) or (i = len - 1)) then begin
if line[i + 1] = '"' then begin
result[cnt] := stringCopy(line, b + 2, i + 1);
end else begin
result[cnt] := stringCopy(line, b + 1, i + 2);
end;
inc(cnt);
end;
end;
if cnt > 0 then begin
module := getMemory($0400);
try
getModuleFileNameW(0, module, $0200);
result[0] := UnicodeString(module);
finally
freeMemory(module);
end;
end;
end;
{$ELSE}
function systemGetTickCount(): long;
begin
result := getTickCount64();
end;
function systemGetCurrentDirectory(): UnicodeString;
begin
system.getdir(0, result);
end;
function stringParseCommandLine(): UnicodeString_Array1d;
var
i: int;
cnt: int;
begin
cnt := system.argc;
result := UnicodeString_Array1d_create(cnt);
for i := 0 to cnt - 1 do begin
result[i] := stringToUTF16(AnsiString(argv[i]));
end;
if cnt > 0 then begin
result[0] := stringReplace(result[0], '/', DIRECTORY_SEPARATOR);
end;
end;
{$ENDIF}
function pointerToLongBits(p: Pointer): long; inline;
begin
result := long((@p)^);
end;
function getParentClass(cls: TClass; unamlen, cnamlen: int; const unam, cnam: AnsiString): TClass;
var
currunam: AnsiString;
currcnam: AnsiString;
begin
repeat
currunam := cls.unitName();
currcnam := cls.className();
if (length(currunam) = unamlen) and (length(currcnam) = cnamlen) and (stringToLowerCase(currunam) = unam) and (stringToLowerCase(currcnam) = cnam) then begin
result := cls;
exit;
end;
cls := cls.classParent();
until cls = nil;
result := nil;
end;
function getParentInterface(info: PTypeInfo; data: PTypeData; unamlen, cnamlen: int; const unam, cnam: AnsiString): PTypeInfo; overload;
var
currunam: AnsiString;
currcnam: AnsiString;
begin
repeat
currcnam := info^.name;
currunam := data^.intfUnit;
if (length(currunam) = unamlen) and (length(currcnam) = cnamlen) and (stringToLowerCase(currunam) = unam) and (stringToLowerCase(currcnam) = cnam) then begin
result := info;
exit;
end;
info := data^.intfParent;
if info = nil then break;
data := getTypeData(info);
until false;
result := nil;
end;
function getParentInterface(info: PTypeInfo; const iid: TGuid): PTypeInfo; overload;
var
data: PTypeData;
begin
repeat
data := getTypeData(info);
if isEqualGuid(data^.iid, iid) then begin
result := info;
exit;
end;
info := data^.intfParent;
until info = nil;
result := nil;
end;
function getParentType(typ: _Class; unamlen, cnamlen: int; const unam, cnam: AnsiString): _Class;
var
currunam: AnsiString;
currcnam: AnsiString;
begin
repeat
currunam := typ.getUnitName();
currcnam := typ.getSimpleName();
if (length(currunam) = unamlen) and (length(currcnam) = cnamlen) and (stringToLowerCase(currunam) = unam) and (stringToLowerCase(currcnam) = cnam) then begin
result := typ;
exit;
end;
typ := typ.getSuperclass();
until typ = nil;
result := nil;
end;
function classForType(const info: TGuid): _Class;
var
i: int;
tinfo: PTypeInfo;
begin
for i := typeInfosLength - 1 downto 0 do begin
tinfo := typeInfosData[i];
if tinfo = nil then continue;
case tinfo^.kind of
tkInterface, tkInterfaceRaw: begin
tinfo := getParentInterface(tinfo, info);
if tinfo <> nil then begin
result := InterfaceInformation.create(tinfo);
exit;
end;
end;
end;
end;
result := GuidInformation.create(info);
end;
function classForType(const info: TClass): _Class;
begin
result := ClassInformation.create(info);
end;
function classForType(const info: Pointer): _Class;
var
tinfo: PTypeInfo absolute info;
tkind: int;
begin
tkind := int(tinfo^.kind);
case tkind of
int(TTypeKind.tkClass):
result := ClassInformation.create(getTypeData(tinfo)^.classType);
int(TTypeKind.tkInterface), int(TTypeKind.tkInterfaceRaw):
result := InterfaceInformation.create(tinfo);
else
if (tkind < 0) or (tkind >= 30) then begin
raise IllegalArgumentException.create('classForType: ' + msgIllegalArgument + 'info');
end;
result := PrimitiveInformation.create(ClassInformation.typeInfoToLangType(tinfo), tinfo^.name);
end;
end;
function classForName(const name: AnsiString): _Class;
var
iid: TGuid;
pos: int;
unam: AnsiString;
cnam: AnsiString;
unamlen: int;
cnamlen: int;
found: PTypeInfo;
i: int;
info: PTypeInfo;
data: PTypeData;
kind: TTypeKind;
parentClass: TClass;
parentInterface: PTypeInfo;
currunam: AnsiString;
unitenum: TypeEnumeration;
currtype: _Class;
begin
if tryStringToGUID(name, iid) then begin
result := classForType(iid);
exit;
end;
pos := stringLastIndexOf('.', name);
if pos <= 0 then begin
unam := stringToLowerCase(name);
unamlen := length(unam);
for i := 0 to length(primitivesData) - 1 do begin
currtype := primitivesData[i];
currunam := currtype.getCanonicalName();
if (length(currunam) = unamlen) and (stringToLowerCase(currunam) = unam) then begin
result := currtype;
exit;
end;
end;
result := nil;
exit;
end;
unam := stringToLowerCase(stringCopy(name, 1, pos));
cnam := stringToLowerCase(stringCopy(name, pos + 1));
unamlen := length(unam);
cnamlen := length(cnam);
found := nil;
for i := 0 to typeInfosLength - 1 do begin
info := typeInfosData[i];
if info = nil then continue;
data := getTypeData(info);
kind := info^.kind;
case kind of
tkClass: begin
parentClass := getParentClass(data^.classType, unamlen, cnamlen, unam, cnam);
if parentClass <> nil then begin
result := ClassInformation.create(parentClass);
exit;
end;
currunam := data^.unitName;
end;
tkInterface, tkInterfaceRaw: begin
parentInterface := getParentInterface(info, data, unamlen, cnamlen, unam, cnam);
if parentInterface <> nil then begin
result := InterfaceInformation.create(parentInterface);
exit;
end;
currunam := data^.intfUnit;
end
else
continue;
end;
if (length(currunam) = unamlen) and (stringToLowerCase(currunam) = unam) and ((found = nil) or (long((@info)^) < long((@found)^))) then begin
{ указатели в длинном режиме — целые числа со знаком! }
found := info;
end;
end;
if found <> nil then begin
unitenum := TypeEnumeration.create(found);
try
while unitenum.hasMoreElements() do begin
currtype := getParentType(unitenum.nextElement(), unamlen, cnamlen, unam, cnam);
if currtype <> nil then begin
result := currtype;
exit;
end;
end;
finally
unitenum.free();
end;
end;
result := nil;
end;
function nextAlignedAfter(address: Pointer): Pointer; assembler; nostackframe;
asm
mov rax, rcx
neg rax
and rax, $07
lea rax, [rcx+rax]
end;
function AnsiString_create(length: int): AnsiString;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function AnsiString_create(const src: byte_Array1d; offset, length: int): AnsiString;
begin
arrayCheckBounds('', system.length(src), offset, length);
result := AnsiString_create(length);
system.move(src[offset], result[1], length * sizeOf(char));
end;
function AnsiString_create(const src: char_Array1d; offset, length: int): AnsiString;
begin
arrayCheckBounds('', system.length(src), offset, length);
result := AnsiString_create(length);
system.move(src[offset], result[1], length * sizeOf(char));
end;
function UnicodeString_create(length: int): UnicodeString;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function UnicodeString_create(const src: short_Array1d; offset, length: int): UnicodeString;
begin
arrayCheckBounds('', system.length(src), offset, length);
result := UnicodeString_create(length);
system.move(src[offset], result[1], length * sizeOf(wchar));
end;
function UnicodeString_create(const src: wchar_Array1d; offset, length: int): UnicodeString;
begin
arrayCheckBounds('', system.length(src), offset, length);
result := UnicodeString_create(length);
system.move(src[offset], result[1], length * sizeOf(wchar));
end;
function boolean_Array1d_create(length: int): boolean_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function boolean_Array1d_create(const elements: array of boolean): boolean_Array1d;
begin
system.setLength(result, length(elements));
system.move(elements[0], result[0], length(result) * sizeOf(boolean));
end;
function char_Array1d_create(length: int): char_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function char_Array1d_create(const elements: array of char): char_Array1d;
begin
system.setLength(result, length(elements));
system.move(elements[0], result[0], length(result) * sizeOf(char));
end;
function wchar_Array1d_create(length: int): wchar_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function wchar_Array1d_create(const elements: array of wchar): wchar_Array1d;
begin
system.setLength(result, length(elements));
system.move(elements[0], result[0], length(result) * sizeOf(wchar));
end;
function byte_Array1d_create(length: int): byte_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function byte_Array1d_create(const elements: array of byte): byte_Array1d;
begin
system.setLength(result, length(elements));
system.move(elements[0], result[0], length(result) * sizeOf(byte));
end;
function short_Array1d_create(length: int): short_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function short_Array1d_create(const elements: array of short): short_Array1d;
begin
system.setLength(result, length(elements));
system.move(elements[0], result[0], length(result) * sizeOf(short));
end;
function int_Array1d_create(length: int): int_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function int_Array1d_create(const elements: array of int): int_Array1d;
begin
system.setLength(result, length(elements));
system.move(elements[0], result[0], length(result) * sizeOf(int));
end;
function long_Array1d_create(length: int): long_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function long_Array1d_create(const elements: array of long): long_Array1d;
begin
system.setLength(result, length(elements));
system.move(elements[0], result[0], length(result) * sizeOf(long));
end;
function float_Array1d_create(length: int): float_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function float_Array1d_create(const elements: array of float): float_Array1d;
begin
system.setLength(result, length(elements));
system.move(elements[0], result[0], length(result) * sizeOf(float));
end;
function double_Array1d_create(length: int): double_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function double_Array1d_create(const elements: array of double): double_Array1d;
begin
system.setLength(result, length(elements));
system.move(elements[0], result[0], length(result) * sizeOf(double));
end;
function real_Array1d_create(length: int): real_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function real_Array1d_create(const elements: array of real): real_Array1d;
begin
system.setLength(result, length(elements));
system.move(elements[0], result[0], length(result) * sizeOf(real));
end;
function TObject_Array1d_create(length: int): TObject_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function TObject_Array1d_create(const elements: array of TObject): TObject_Array1d;
begin
system.setLength(result, length(elements));
system.move(elements[0], result[0], length(result) * sizeOf(TObject));
end;
function IUnknown_Array1d_create(length: int): IUnknown_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function IUnknown_Array1d_create(const elements: array of IUnknown): IUnknown_Array1d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function AnsiString_Array1d_create(length: int): AnsiString_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function AnsiString_Array1d_create(const elements: array of AnsiString): AnsiString_Array1d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function UnicodeString_Array1d_create(length: int): UnicodeString_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function UnicodeString_Array1d_create(const elements: array of UnicodeString): UnicodeString_Array1d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function Pointer_Array1d_create(length: int): Pointer_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function boolean_Array2d_create(length: int): boolean_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function boolean_Array2d_create(length1, length2: int): boolean_Array2d;
var
i: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length1);
for i := length1 - 1 downto 0 do begin
system.setLength(result[i], length2);
end;
end;
function boolean_Array2d_create(const elements: array of boolean_Array1d): boolean_Array2d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function char_Array2d_create(length: int): char_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function char_Array2d_create(length1, length2: int): char_Array2d;
var
i: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length1);
for i := length1 - 1 downto 0 do begin
system.setLength(result[i], length2);
end;
end;
function char_Array2d_create(const elements: array of char_Array1d): char_Array2d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function wchar_Array2d_create(length: int): wchar_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function wchar_Array2d_create(length1, length2: int): wchar_Array2d;
var
i: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length1);
for i := length1 - 1 downto 0 do begin
system.setLength(result[i], length2);
end;
end;
function wchar_Array2d_create(const elements: array of wchar_Array1d): wchar_Array2d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function byte_Array2d_create(length: int): byte_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function byte_Array2d_create(length1, length2: int): byte_Array2d;
var
i: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length1);
for i := length1 - 1 downto 0 do begin
system.setLength(result[i], length2);
end;
end;
function byte_Array2d_create(const elements: array of byte_Array1d): byte_Array2d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function short_Array2d_create(length: int): short_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function short_Array2d_create(length1, length2: int): short_Array2d;
var
i: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length1);
for i := length1 - 1 downto 0 do begin
system.setLength(result[i], length2);
end;
end;
function short_Array2d_create(const elements: array of short_Array1d): short_Array2d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function int_Array2d_create(length: int): int_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function int_Array2d_create(length1, length2: int): int_Array2d;
var
i: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length1);
for i := length1 - 1 downto 0 do begin
system.setLength(result[i], length2);
end;
end;
function int_Array2d_create(const elements: array of int_Array1d): int_Array2d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function long_Array2d_create(length: int): long_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function long_Array2d_create(length1, length2: int): long_Array2d;
var
i: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length1);
for i := length1 - 1 downto 0 do begin
system.setLength(result[i], length2);
end;
end;
function long_Array2d_create(const elements: array of long_Array1d): long_Array2d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function float_Array2d_create(length: int): float_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function float_Array2d_create(length1, length2: int): float_Array2d;
var
i: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length1);
for i := length1 - 1 downto 0 do begin
system.setLength(result[i], length2);
end;
end;
function float_Array2d_create(const elements: array of float_Array1d): float_Array2d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function double_Array2d_create(length: int): double_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function double_Array2d_create(length1, length2: int): double_Array2d;
var
i: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length1);
for i := length1 - 1 downto 0 do begin
system.setLength(result[i], length2);
end;
end;
function double_Array2d_create(const elements: array of double_Array1d): double_Array2d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function real_Array2d_create(length: int): real_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function real_Array2d_create(length1, length2: int): real_Array2d;
var
i: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length1);
for i := length1 - 1 downto 0 do begin
system.setLength(result[i], length2);
end;
end;
function real_Array2d_create(const elements: array of real_Array1d): real_Array2d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function TObject_Array2d_create(length: int): TObject_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function TObject_Array2d_create(length1, length2: int): TObject_Array2d;
var
i: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length1);
for i := length1 - 1 downto 0 do begin
system.setLength(result[i], length2);
end;
end;
function TObject_Array2d_create(const elements: array of TObject_Array1d): TObject_Array2d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function IUnknown_Array2d_create(length: int): IUnknown_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function IUnknown_Array2d_create(length1, length2: int): IUnknown_Array2d;
var
i: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length1);
for i := length1 - 1 downto 0 do begin
system.setLength(result[i], length2);
end;
end;
function IUnknown_Array2d_create(const elements: array of IUnknown_Array1d): IUnknown_Array2d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function AnsiString_Array2d_create(length: int): AnsiString_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function AnsiString_Array2d_create(length1, length2: int): AnsiString_Array2d;
var
i: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length1);
for i := length1 - 1 downto 0 do begin
system.setLength(result[i], length2);
end;
end;
function AnsiString_Array2d_create(const elements: array of AnsiString_Array1d): AnsiString_Array2d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function UnicodeString_Array2d_create(length: int): UnicodeString_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length);
end;
function UnicodeString_Array2d_create(length1, length2: int): UnicodeString_Array2d;
var
i: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(msgNegativeArraySize);
end;
system.setLength(result, length1);
for i := length1 - 1 downto 0 do begin
system.setLength(result[i], length2);
end;
end;
function UnicodeString_Array2d_create(const elements: array of UnicodeString_Array1d): UnicodeString_Array2d;
var
i: int;
begin
system.setLength(result, length(elements));
for i := length(result) - 1 downto 0 do begin
result[i] := elements[i];
end;
end;
function arrayequalsf(src, dst: Pointer; size, length: int): int; assembler; nostackframe;
asm
push rsi
push rdi
lea r10, [rip+@1-@0]
@0: movsxd r11, [r10+r8*8+$04] { r8=size }
lea r10, [r10+r11]
jmp r10
align $04
@1: xchg eax, eax
lea r10, [r10+@size0-@1]
xchg eax, eax
lea r10, [r10+@size1-@1]
xchg eax, eax
lea r10, [r10+@size2-@1]
xchg eax, eax
lea r10, [r10+@size3-@1]
@size0: mov rsi, rcx { src }
mov rdi, rdx { dst }
movsxd rcx, r9d { length }
mov r10, rdi
cld
repe cmpsb
je @nf
sub rdi, r10
sar rdi, $00
jmp @exit
align $04
@size1: mov rsi, rcx { src }
mov rdi, rdx { dst }
movsxd rcx, r9d { length }
mov r10, rdi
cld
repe cmpsw
je @nf
sub rdi, r10
sar rdi, $01
jmp @exit
align $04
@size2: mov rsi, rcx { src }
mov rdi, rdx { dst }
movsxd rcx, r9d { length }
mov r10, rdi
cld
repe cmpsd
je @nf
sub rdi, r10
sar rdi, $02
jmp @exit
align $04
@size3: mov rsi, rcx { src }
mov rdi, rdx { dst }
movsxd rcx, r9d { length }
mov r10, rdi
cld
repe cmpsq
je @nf
sub rdi, r10
sar rdi, $03
jmp @exit
align $04
@nf: mov eax, -$01
pop rdi
pop rsi
ret
@exit: lea eax, [edi-$01]
pop rdi
pop rsi
end;
function arrayequalsfPrimitive(const src: boolean_Array1d; srcOffset: int; const dst: boolean_Array1d; dstOffset: int; length: int): int; overload;
begin
arrayCheckBounds('arrayequalsfPrimitive', system.length(src), srcOffset, length);
arrayCheckBounds('arrayequalsfPrimitive', system.length(dst), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsf(@(src[srcOffset]), @(dst[dstOffset]), 0, length);
end;
function arrayequalsfPrimitive(const src: char_Array1d; srcOffset: int; const dst: char_Array1d; dstOffset: int; length: int): int; overload;
begin
arrayCheckBounds('arrayequalsfPrimitive', system.length(src), srcOffset, length);
arrayCheckBounds('arrayequalsfPrimitive', system.length(dst), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsf(@(src[srcOffset]), @(dst[dstOffset]), 0, length);
end;
function arrayequalsfPrimitive(const src: wchar_Array1d; srcOffset: int; const dst: wchar_Array1d; dstOffset: int; length: int): int; overload;
begin
arrayCheckBounds('arrayequalsfPrimitive', system.length(src), srcOffset, length);
arrayCheckBounds('arrayequalsfPrimitive', system.length(dst), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsf(@(src[srcOffset]), @(dst[dstOffset]), 1, length);
end;
function arrayequalsfPrimitive(const src: byte_Array1d; srcOffset: int; const dst: byte_Array1d; dstOffset: int; length: int): int;
begin
arrayCheckBounds('arrayequalsfPrimitive', system.length(src), srcOffset, length);
arrayCheckBounds('arrayequalsfPrimitive', system.length(dst), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsf(@(src[srcOffset]), @(dst[dstOffset]), 0, length);
end;
function arrayequalsfPrimitive(const src: short_Array1d; srcOffset: int; const dst: short_Array1d; dstOffset: int; length: int): int; overload;
begin
arrayCheckBounds('arrayequalsfPrimitive', system.length(src), srcOffset, length);
arrayCheckBounds('arrayequalsfPrimitive', system.length(dst), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsf(@(src[srcOffset]), @(dst[dstOffset]), 1, length);
end;
function arrayequalsfPrimitive(const src: int_Array1d; srcOffset: int; const dst: int_Array1d; dstOffset: int; length: int): int; overload;
begin
arrayCheckBounds('arrayequalsfPrimitive', system.length(src), srcOffset, length);
arrayCheckBounds('arrayequalsfPrimitive', system.length(dst), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsf(@(src[srcOffset]), @(dst[dstOffset]), 2, length);
end;
function arrayequalsfPrimitive(const src: long_Array1d; srcOffset: int; const dst: long_Array1d; dstOffset: int; length: int): int; overload;
begin
arrayCheckBounds('arrayequalsfPrimitive', system.length(src), srcOffset, length);
arrayCheckBounds('arrayequalsfPrimitive', system.length(dst), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsf(@(src[srcOffset]), @(dst[dstOffset]), 3, length);
end;
function arrayequalsfInterface(const src; srcOffset: int; const dst; dstOffset: int; length: int): int;
begin
arrayCheckBounds('arrayequalsfInterface', system.length(Pointer_Array1d(src)), srcOffset, length);
arrayCheckBounds('arrayequalsfInterface', system.length(Pointer_Array1d(dst)), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsf(@(Pointer_Array1d(src)[srcOffset]), @(Pointer_Array1d(dst)[dstOffset]), 3, length);
end;
function arrayequalsfObject(const src; srcOffset: int; const dst; dstOffset: int; length: int): int;
begin
arrayCheckBounds('arrayequalsfObject', system.length(Pointer_Array1d(src)), srcOffset, length);
arrayCheckBounds('arrayequalsfObject', system.length(Pointer_Array1d(dst)), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsf(@(Pointer_Array1d(src)[srcOffset]), @(Pointer_Array1d(dst)[dstOffset]), 3, length);
end;
function arrayequalsfArray(const src; srcOffset: int; const dst; dstOffset: int; length: int): int;
begin
arrayCheckBounds('arrayequalsfArray', system.length(Pointer_Array1d(src)), srcOffset, length);
arrayCheckBounds('arrayequalsfArray', system.length(Pointer_Array1d(dst)), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsf(@(Pointer_Array1d(src)[srcOffset]), @(Pointer_Array1d(dst)[dstOffset]), 3, length);
end;
function arrayequalsb(src, dst: Pointer; size, length: int): int; assembler; nostackframe;
asm
push rsi
push rdi
lea r10, [rip+@1-@0]
@0: movsxd r11, [r10+r8*8+$04] { r8=size }
lea r10, [r10+r11]
jmp r10
align $04
@1: xchg eax, eax
lea r10, [r10+@size0-@1]
xchg eax, eax
lea r10, [r10+@size1-@1]
xchg eax, eax
lea r10, [r10+@size2-@1]
xchg eax, eax
lea r10, [r10+@size3-@1]
@size0: mov rsi, rcx { src }
mov rdi, rdx { dst }
movsxd rcx, r9d { length }
mov r10, rdi
std
repe cmpsb
je @nf
sub rdi, r10
sar rdi, $00
jmp @exit
align $04
@size1: mov rsi, rcx { src }
mov rdi, rdx { dst }
movsxd rcx, r9d { length }
mov r10, rdi
std
repe cmpsw
je @nf
sub rdi, r10
sar rdi, $01
jmp @exit
align $04
@size2: mov rsi, rcx { src }
mov rdi, rdx { dst }
movsxd rcx, r9d { length }
mov r10, rdi
std
repe cmpsd
je @nf
sub rdi, r10
sar rdi, $02
jmp @exit
align $04
@size3: mov rsi, rcx { src }
mov rdi, rdx { dst }
movsxd rcx, r9d { length }
mov r10, rdi
std
repe cmpsq
je @nf
sub rdi, r10
sar rdi, $03
jmp @exit
align $04
@nf: mov eax, -$01
pop rdi
pop rsi
cld { сбрасываем флаг направления, дабы избежать потенциальных проблем с системными библиотеками }
ret
@exit: lea eax, [edi+r9d]
pop rdi
pop rsi
cld { сбрасываем флаг направления, дабы избежать потенциальных проблем с системными библиотеками }
end;
function arrayequalsbPrimitive(const src: boolean_Array1d; srcOffset: int; const dst: boolean_Array1d; dstOffset: int; length: int): int; overload;
begin
arrayCheckBounds('arrayequalsbPrimitive', system.length(src), srcOffset, length);
arrayCheckBounds('arrayequalsbPrimitive', system.length(dst), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsb(@(src[srcOffset + length - 1]), @(dst[dstOffset + length - 1]), 0, length);
end;
function arrayequalsbPrimitive(const src: char_Array1d; srcOffset: int; const dst: char_Array1d; dstOffset: int; length: int): int; overload;
begin
arrayCheckBounds('arrayequalsbPrimitive', system.length(src), srcOffset, length);
arrayCheckBounds('arrayequalsbPrimitive', system.length(dst), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsb(@(src[srcOffset + length - 1]), @(dst[dstOffset + length - 1]), 0, length);
end;
function arrayequalsbPrimitive(const src: wchar_Array1d; srcOffset: int; const dst: wchar_Array1d; dstOffset: int; length: int): int; overload;
begin
arrayCheckBounds('arrayequalsbPrimitive', system.length(src), srcOffset, length);
arrayCheckBounds('arrayequalsbPrimitive', system.length(dst), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsb(@(src[srcOffset + length - 1]), @(dst[dstOffset + length - 1]), 1, length);
end;
function arrayequalsbPrimitive(const src: byte_Array1d; srcOffset: int; const dst: byte_Array1d; dstOffset: int; length: int): int;
begin
arrayCheckBounds('arrayequalsbPrimitive', system.length(src), srcOffset, length);
arrayCheckBounds('arrayequalsbPrimitive', system.length(dst), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsb(@(src[srcOffset + length - 1]), @(dst[dstOffset + length - 1]), 0, length);
end;
function arrayequalsbPrimitive(const src: short_Array1d; srcOffset: int; const dst: short_Array1d; dstOffset: int; length: int): int; overload;
begin
arrayCheckBounds('arrayequalsbPrimitive', system.length(src), srcOffset, length);
arrayCheckBounds('arrayequalsbPrimitive', system.length(dst), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsb(@(src[srcOffset + length - 1]), @(dst[dstOffset + length - 1]), 1, length);
end;
function arrayequalsbPrimitive(const src: int_Array1d; srcOffset: int; const dst: int_Array1d; dstOffset: int; length: int): int; overload;
begin
arrayCheckBounds('arrayequalsbPrimitive', system.length(src), srcOffset, length);
arrayCheckBounds('arrayequalsbPrimitive', system.length(dst), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsb(@(src[srcOffset + length - 1]), @(dst[dstOffset + length - 1]), 2, length);
end;
function arrayequalsbPrimitive(const src: long_Array1d; srcOffset: int; const dst: long_Array1d; dstOffset: int; length: int): int; overload;
begin
arrayCheckBounds('arrayequalsbPrimitive', system.length(src), srcOffset, length);
arrayCheckBounds('arrayequalsbPrimitive', system.length(dst), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsb(@(src[srcOffset + length - 1]), @(dst[dstOffset + length - 1]), 3, length);
end;
function arrayequalsbInterface(const src; srcOffset: int; const dst; dstOffset: int; length: int): int;
begin
arrayCheckBounds('arrayequalsbInterface', system.length(Pointer_Array1d(src)), srcOffset, length);
arrayCheckBounds('arrayequalsbInterface', system.length(Pointer_Array1d(dst)), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsb(@(Pointer_Array1d(src)[srcOffset + length - 1]), @(Pointer_Array1d(dst)[dstOffset + length - 1]), 3, length);
end;
function arrayequalsbObject(const src; srcOffset: int; const dst; dstOffset: int; length: int): int;
begin
arrayCheckBounds('arrayequalsbObject', system.length(Pointer_Array1d(src)), srcOffset, length);
arrayCheckBounds('arrayequalsbObject', system.length(Pointer_Array1d(dst)), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsb(@(Pointer_Array1d(src)[srcOffset + length - 1]), @(Pointer_Array1d(dst)[dstOffset + length - 1]), 3, length);
end;
function arrayequalsbArray(const src; srcOffset: int; const dst; dstOffset: int; length: int): int;
begin
arrayCheckBounds('arrayequalsbArray', system.length(Pointer_Array1d(src)), srcOffset, length);
arrayCheckBounds('arrayequalsbArray', system.length(Pointer_Array1d(dst)), dstOffset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayequalsb(@(Pointer_Array1d(src)[srcOffset + length - 1]), @(Pointer_Array1d(dst)[dstOffset + length - 1]), 3, length);
end;
function arrayfindeqf(src: Pointer; size, length: int; value: long): int; assembler; nostackframe;
asm
push rdi
lea r10, [rip+@1-@0]
@0: movsxd r11, [r10+rdx*8+$04] { rdx=size }
lea r10, [r10+r11]
jmp r10
align $04
@1: xchg eax, eax
lea r10, [r10+@size0-@1]
xchg eax, eax
lea r10, [r10+@size1-@1]
xchg eax, eax
lea r10, [r10+@size2-@1]
xchg eax, eax
lea r10, [r10+@size3-@1]
@size0: mov rdi, rcx { src }
movzx rax, r9b { value }
movsxd rcx, r8d { length }
mov r10, rdi
cld
repne scasb
jne @nf
sub rdi, r10
sar rdi, $00
jmp @exit
align $04
@size1: mov rdi, rcx { src }
movzx rax, r9w { value }
movsxd rcx, r8d { length }
mov r10, rdi
cld
repne scasw
jne @nf
sub rdi, r10
sar rdi, $01
jmp @exit
align $04
@size2: mov rdi, rcx { src }
mov eax, r9d { value }
movsxd rcx, r8d { length }
mov r10, rdi
cld
repne scasd
jne @nf
sub rdi, r10
sar rdi, $02
jmp @exit
align $04
@size3: mov rdi, rcx { src }
mov rax, r9 { value }
movsxd rcx, r8d { length }
mov r10, rdi
cld
repne scasq
jne @nf
sub rdi, r10
sar rdi, $03
jmp @exit
align $04
@nf: mov eax, -$01
pop rdi
ret
@exit: lea eax, [edi-$01]
pop rdi
end;
function arrayfindeqfPrimitive(const src: boolean_Array1d; offset, length: int; value: boolean): int;
var
val: int;
begin
arrayCheckBounds('arrayfindeqfPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
if value then begin
val := 1;
end else begin
val := 0;
end;
result := arrayfindeqf(@(src[offset]), 0, length, val);
end;
function arrayfindeqfPrimitive(const src: char_Array1d; offset, length: int; value: char): int;
begin
arrayCheckBounds('arrayfindeqfPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqf(@(src[offset]), 0, length, long(value));
end;
function arrayfindeqfPrimitive(const src: wchar_Array1d; offset, length: int; value: wchar): int;
begin
arrayCheckBounds('arrayfindeqfPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqf(@(src[offset]), 1, length, long(value));
end;
function arrayfindeqfPrimitive(const src: byte_Array1d; offset, length: int; value: int): int;
begin
arrayCheckBounds('arrayfindeqfPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqf(@(src[offset]), 0, length, value);
end;
function arrayfindeqfPrimitive(const src: short_Array1d; offset, length: int; value: int): int;
begin
arrayCheckBounds('arrayfindeqfPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqf(@(src[offset]), 1, length, value);
end;
function arrayfindeqfPrimitive(const src: int_Array1d; offset, length: int; value: int): int;
begin
arrayCheckBounds('arrayfindeqfPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqf(@(src[offset]), 2, length, value);
end;
function arrayfindeqfPrimitive(const src: long_Array1d; offset, length: int; value: long): int;
begin
arrayCheckBounds('arrayfindeqfPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqf(@(src[offset]), 3, length, value);
end;
function arrayfindeqfInterface(const src; offset, length: int; value: IUnknown): int;
begin
arrayCheckBounds('arrayfindeqfInterface', system.length(Pointer_Array1d(src)), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqf(@(Pointer_Array1d(src)[offset]), 3, length, long(value));
end;
function arrayfindeqfObject(const src; offset, length: int; value: TObject): int;
begin
arrayCheckBounds('arrayfindeqfObject', system.length(Pointer_Array1d(src)), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqf(@(Pointer_Array1d(src)[offset]), 3, length, long(value));
end;
function arrayfindeqfArray(const src; offset, length: int; const value): int;
begin
arrayCheckBounds('arrayfindeqfArray', system.length(Pointer_Array1d(src)), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqf(@(Pointer_Array1d(src)[offset]), 3, length, long(value));
end;
function arrayfindeqb(src: Pointer; size, length: int; value: long): int; assembler; nostackframe;
asm
push rdi
lea r10, [rip+@1-@0]
@0: movsxd r11, [r10+rdx*8+$04] { rdx=size }
lea r10, [r10+r11]
jmp r10
align $04
@1: xchg eax, eax
lea r10, [r10+@size0-@1]
xchg eax, eax
lea r10, [r10+@size1-@1]
xchg eax, eax
lea r10, [r10+@size2-@1]
xchg eax, eax
lea r10, [r10+@size3-@1]
@size0: mov rdi, rcx { src }
movzx rax, r9b { value }
movsxd rcx, r8d { length }
mov r10, rdi
std
repne scasb
jne @nf
sub rdi, r10
sar rdi, $00
jmp @exit
align $04
@size1: mov rdi, rcx { src }
movzx rax, r9w { value }
movsxd rcx, r8d { length }
mov r10, rdi
std
repne scasw
jne @nf
sub rdi, r10
sar rdi, $01
jmp @exit
align $04
@size2: mov rdi, rcx { src }
mov eax, r9d { value }
movsxd rcx, r8d { length }
mov r10, rdi
std
repne scasd
jne @nf
sub rdi, r10
sar rdi, $02
jmp @exit
align $04
@size3: mov rdi, rcx { src }
mov rax, r9 { value }
movsxd rcx, r8d { length }
mov r10, rdi
std
repne scasq
jne @nf
sub rdi, r10
sar rdi, $03
jmp @exit
align $04
@nf: mov eax, -$01
pop rdi
cld { сбрасываем флаг направления, дабы избежать потенциальных проблем с системными библиотеками }
ret
@exit: lea eax, [edi+r8d]
pop rdi
cld { сбрасываем флаг направления, дабы избежать потенциальных проблем с системными библиотеками }
end;
function arrayfindeqbPrimitive(const src: boolean_Array1d; offset, length: int; value: boolean): int;
var
val: int;
begin
arrayCheckBounds('arrayfindeqbPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
if value then begin
val := 1;
end else begin
val := 0;
end;
result := arrayfindeqb(@(src[offset + length - 1]), 0, length, val);
end;
function arrayfindeqbPrimitive(const src: char_Array1d; offset, length: int; value: char): int;
begin
arrayCheckBounds('arrayfindeqbPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqb(@(src[offset + length - 1]), 0, length, long(value));
end;
function arrayfindeqbPrimitive(const src: wchar_Array1d; offset, length: int; value: wchar): int;
begin
arrayCheckBounds('arrayfindeqbPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqb(@(src[offset + length - 1]), 1, length, long(value));
end;
function arrayfindeqbPrimitive(const src: byte_Array1d; offset, length: int; value: int): int;
begin
arrayCheckBounds('arrayfindeqbPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqb(@(src[offset + length - 1]), 0, length, value);
end;
function arrayfindeqbPrimitive(const src: short_Array1d; offset, length: int; value: int): int;
begin
arrayCheckBounds('arrayfindeqbPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqb(@(src[offset + length - 1]), 1, length, value);
end;
function arrayfindeqbPrimitive(const src: int_Array1d; offset, length: int; value: int): int;
begin
arrayCheckBounds('arrayfindeqbPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqb(@(src[offset + length - 1]), 2, length, value);
end;
function arrayfindeqbPrimitive(const src: long_Array1d; offset, length: int; value: long): int;
begin
arrayCheckBounds('arrayfindeqbPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqb(@(src[offset + length - 1]), 3, length, value);
end;
function arrayfindeqbInterface(const src; offset, length: int; value: IUnknown): int;
begin
arrayCheckBounds('arrayfindeqbInterface', system.length(Pointer_Array1d(src)), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqb(@(Pointer_Array1d(src)[offset + length - 1]), 3, length, long(value));
end;
function arrayfindeqbObject(const src; offset, length: int; value: TObject): int;
begin
arrayCheckBounds('arrayfindeqbObject', system.length(Pointer_Array1d(src)), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqb(@(Pointer_Array1d(src)[offset + length - 1]), 3, length, long(value));
end;
function arrayfindeqbArray(const src; offset, length: int; const value): int;
begin
arrayCheckBounds('arrayfindeqbArray', system.length(Pointer_Array1d(src)), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindeqb(@(Pointer_Array1d(src)[offset + length - 1]), 3, length, long(value));
end;
function arrayfindnef(src: Pointer; size, length: int; value: long): int; assembler; nostackframe;
asm
push rdi
lea r10, [rip+@1-@0]
@0: movsxd r11, [r10+rdx*8+$04] { rdx=size }
lea r10, [r10+r11]
jmp r10
align $04
@1: xchg eax, eax
lea r10, [r10+@size0-@1]
xchg eax, eax
lea r10, [r10+@size1-@1]
xchg eax, eax
lea r10, [r10+@size2-@1]
xchg eax, eax
lea r10, [r10+@size3-@1]
@size0: mov rdi, rcx { src }
movzx rax, r9b { value }
movsxd rcx, r8d { length }
mov r10, rdi
cld
repe scasb
je @nf
sub rdi, r10
sar rdi, $00
jmp @exit
align $04
@size1: mov rdi, rcx { src }
movzx rax, r9w { value }
movsxd rcx, r8d { length }
mov r10, rdi
cld
repe scasw
je @nf
sub rdi, r10
sar rdi, $01
jmp @exit
align $04
@size2: mov rdi, rcx { src }
mov eax, r9d { value }
movsxd rcx, r8d { length }
mov r10, rdi
cld
repe scasd
je @nf
sub rdi, r10
sar rdi, $02
jmp @exit
align $04
@size3: mov rdi, rcx { src }
mov rax, r9 { value }
movsxd rcx, r8d { length }
mov r10, rdi
cld
repe scasq
je @nf
sub rdi, r10
sar rdi, $03
jmp @exit
align $04
@nf: mov eax, -$01
pop rdi
ret
@exit: lea eax, [edi-$01]
pop rdi
end;
function arrayfindnefPrimitive(const src: boolean_Array1d; offset, length: int; value: boolean): int;
var
val: int;
begin
arrayCheckBounds('arrayfindnefPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
if value then begin
val := 1;
end else begin
val := 0;
end;
result := arrayfindnef(@(src[offset]), 0, length, val);
end;
function arrayfindnefPrimitive(const src: char_Array1d; offset, length: int; value: char): int;
begin
arrayCheckBounds('arrayfindnefPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindnef(@(src[offset]), 0, length, long(value));
end;
function arrayfindnefPrimitive(const src: wchar_Array1d; offset, length: int; value: wchar): int;
begin
arrayCheckBounds('arrayfindnefPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindnef(@(src[offset]), 1, length, long(value));
end;
function arrayfindnefPrimitive(const src: byte_Array1d; offset, length: int; value: int): int;
begin
arrayCheckBounds('arrayfindnefPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindnef(@(src[offset]), 0, length, value);
end;
function arrayfindnefPrimitive(const src: short_Array1d; offset, length: int; value: int): int;
begin
arrayCheckBounds('arrayfindnefPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindnef(@(src[offset]), 1, length, value);
end;
function arrayfindnefPrimitive(const src: int_Array1d; offset, length: int; value: int): int;
begin
arrayCheckBounds('arrayfindnefPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindnef(@(src[offset]), 2, length, value);
end;
function arrayfindnefPrimitive(const src: long_Array1d; offset, length: int; value: long): int;
begin
arrayCheckBounds('arrayfindnefPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindnef(@(src[offset]), 3, length, value);
end;
function arrayfindnefInterface(const src; offset, length: int; value: IUnknown): int;
begin
arrayCheckBounds('arrayfindnefInterface', system.length(Pointer_Array1d(src)), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindnef(@(Pointer_Array1d(src)[offset]), 3, length, long(value));
end;
function arrayfindnefObject(const src; offset, length: int; value: TObject): int;
begin
arrayCheckBounds('arrayfindnefObject', system.length(Pointer_Array1d(src)), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindnef(@(Pointer_Array1d(src)[offset]), 3, length, long(value));
end;
function arrayfindnefArray(const src; offset, length: int; const value): int;
begin
arrayCheckBounds('arrayfindnefArray', system.length(Pointer_Array1d(src)), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindnef(@(Pointer_Array1d(src)[offset]), 3, length, long(value));
end;
function arrayfindneb(src: Pointer; size, length: int; value: long): int; assembler; nostackframe;
asm
push rdi
lea r10, [rip+@1-@0]
@0: movsxd r11, [r10+rdx*8+$04] { rdx=size }
lea r10, [r10+r11]
jmp r10
align $04
@1: xchg eax, eax
lea r10, [r10+@size0-@1]
xchg eax, eax
lea r10, [r10+@size1-@1]
xchg eax, eax
lea r10, [r10+@size2-@1]
xchg eax, eax
lea r10, [r10+@size3-@1]
@size0: mov rdi, rcx { src }
movzx rax, r9b { value }
movsxd rcx, r8d { length }
mov r10, rdi
std
repe scasb
je @nf
sub rdi, r10
sar rdi, $00
jmp @exit
align $04
@size1: mov rdi, rcx { src }
movzx rax, r9w { value }
movsxd rcx, r8d { length }
mov r10, rdi
std
repe scasw
je @nf
sub rdi, r10
sar rdi, $01
jmp @exit
align $04
@size2: mov rdi, rcx { src }
mov eax, r9d { value }
movsxd rcx, r8d { length }
mov r10, rdi
std
repe scasd
je @nf
sub rdi, r10
sar rdi, $02
jmp @exit
align $04
@size3: mov rdi, rcx { src }
mov rax, r9 { value }
movsxd rcx, r8d { length }
mov r10, rdi
std
repe scasq
je @nf
sub rdi, r10
sar rdi, $03
jmp @exit
align $04
@nf: mov eax, -$01
pop rdi
cld { сбрасываем флаг направления, дабы избежать потенциальных проблем с системными библиотеками }
ret
@exit: lea eax, [edi+r8d]
pop rdi
cld { сбрасываем флаг направления, дабы избежать потенциальных проблем с системными библиотеками }
end;
function arrayfindnebPrimitive(const src: boolean_Array1d; offset, length: int; value: boolean): int;
var
val: int;
begin
arrayCheckBounds('arrayfindnebPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
if value then begin
val := 1;
end else begin
val := 0;
end;
result := arrayfindneb(@(src[offset + length - 1]), 0, length, val);
end;
function arrayfindnebPrimitive(const src: char_Array1d; offset, length: int; value: char): int;
begin
arrayCheckBounds('arrayfindnebPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindneb(@(src[offset + length - 1]), 0, length, long(value));
end;
function arrayfindnebPrimitive(const src: wchar_Array1d; offset, length: int; value: wchar): int;
begin
arrayCheckBounds('arrayfindnebPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindneb(@(src[offset + length - 1]), 1, length, long(value));
end;
function arrayfindnebPrimitive(const src: byte_Array1d; offset, length: int; value: int): int;
begin
arrayCheckBounds('arrayfindnebPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindneb(@(src[offset + length - 1]), 0, length, value);
end;
function arrayfindnebPrimitive(const src: short_Array1d; offset, length: int; value: int): int;
begin
arrayCheckBounds('arrayfindnebPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindneb(@(src[offset + length - 1]), 1, length, value);
end;
function arrayfindnebPrimitive(const src: int_Array1d; offset, length: int; value: int): int;
begin
arrayCheckBounds('arrayfindnebPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindneb(@(src[offset + length - 1]), 2, length, value);
end;
function arrayfindnebPrimitive(const src: long_Array1d; offset, length: int; value: long): int;
begin
arrayCheckBounds('arrayfindnebPrimitive', system.length(src), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindneb(@(src[offset + length - 1]), 3, length, value);
end;
function arrayfindnebInterface(const src; offset, length: int; value: IUnknown): int;
begin
arrayCheckBounds('arrayfindnebInterface', system.length(Pointer_Array1d(src)), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindneb(@(Pointer_Array1d(src)[offset + length - 1]), 3, length, long(value));
end;
function arrayfindnebObject(const src; offset, length: int; value: TObject): int;
begin
arrayCheckBounds('arrayfindnebObject', system.length(Pointer_Array1d(src)), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindneb(@(Pointer_Array1d(src)[offset + length - 1]), 3, length, long(value));
end;
function arrayfindnebArray(const src; offset, length: int; const value): int;
begin
arrayCheckBounds('arrayfindnebArray', system.length(Pointer_Array1d(src)), offset, length);
if length <= 0 then begin
result := -1;
exit;
end;
result := arrayfindneb(@(Pointer_Array1d(src)[offset + length - 1]), 3, length, long(value));
end;
procedure arrayfill(dst: Pointer; size, length: int; value: long); assembler; nostackframe;
asm
push rdi
lea rdi, [rip+@1-@0]
@0: movsxd rdx, [rdi+rdx*8+$04] { rdx=size }
lea rdx, [rdi+rdx]
jmp rdx
align $04
@1: xchg eax, eax
lea r10, [r10+@size0-@1]
xchg eax, eax
lea r10, [r10+@size1-@1]
xchg eax, eax
lea r10, [r10+@size2-@1]
xchg eax, eax
lea r10, [r10+@size3-@1]
@size0: mov rdi, rcx { dst }
movzx rax, r9b { value }
movsxd rcx, r8d { length }
cld
rep stosb
jmp @exit
align $04
@size1: mov rdi, rcx { dst }
movzx rax, r9w { value }
movsxd rcx, r8d { length }
cld
rep stosw
jmp @exit
align $04
@size2: mov rdi, rcx { dst }
mov eax, r9d { value }
movsxd rcx, r8d { length }
cld
rep stosd
jmp @exit
align $04
@size3: mov rdi, rcx { dst }
mov rax, r9 { value }
movsxd rcx, r8d { length }
cld
rep stosq
@exit: pop rdi
end;
procedure arrayfillPrimitives(const dst: boolean_Array1d; offset, length: int; value: boolean);
var
len: int;
val: int;
begin
len := system.length(dst);
if offset < 0 then begin
inc(length, offset);
offset := 0;
end;
if offset + length > len then begin
length := len - offset;
end;
if length > 0 then begin
if value then begin
val := 1;
end else begin
val := 0;
end;
arrayfill(@(dst[offset]), 0, length, val);
end;
end;
procedure arrayfillPrimitives(const dst: char_Array1d; offset, length: int; value: char);
var
len: int;
begin
len := system.length(dst);
if offset < 0 then begin
inc(length, offset);
offset := 0;
end;
if offset + length > len then begin
length := len - offset;
end;
if length > 0 then begin
arrayfill(@(dst[offset]), 0, length, int(value));
end;
end;
procedure arrayfillPrimitives(const dst: wchar_Array1d; offset, length: int; value: wchar);
var
len: int;
begin
len := system.length(dst);
if offset < 0 then begin
inc(length, offset);
offset := 0;
end;
if offset + length > len then begin
length := len - offset;
end;
if length > 0 then begin
arrayfill(@(dst[offset]), 1, length, int(value));
end;
end;
procedure arrayfillPrimitives(const dst: byte_Array1d; offset, length: int; value: int);
var
len: int;
begin
len := system.length(dst);
if offset < 0 then begin
inc(length, offset);
offset := 0;
end;
if offset + length > len then begin
length := len - offset;
end;
if length > 0 then begin
arrayfill(@(dst[offset]), 0, length, value);
end;
end;
procedure arrayfillPrimitives(const dst: short_Array1d; offset, length: int; value: int);
var
len: int;
begin
len := system.length(dst);
if offset < 0 then begin
inc(length, offset);
offset := 0;
end;
if offset + length > len then begin
length := len - offset;
end;
if length > 0 then begin
arrayfill(@(dst[offset]), 1, length, value);
end;
end;
procedure arrayfillPrimitives(const dst: int_Array1d; offset, length: int; value: int);
var
len: int;
begin
len := system.length(dst);
if offset < 0 then begin
inc(length, offset);
offset := 0;
end;
if offset + length > len then begin
length := len - offset;
end;
if length > 0 then begin
arrayfill(@(dst[offset]), 2, length, value);
end;
end;
procedure arrayfillPrimitives(const dst: long_Array1d; offset, length: int; value: long);
var
len: int;
begin
len := system.length(dst);
if offset < 0 then begin
inc(length, offset);
offset := 0;
end;
if offset + length > len then begin
length := len - offset;
end;
if length > 0 then begin
arrayfill(@(dst[offset]), 3, length, value);
end;
end;
procedure arrayfillPrimitives(const dst: float_Array1d; offset, length: int; value: float);
var
len: int;
begin
len := system.length(dst);
if offset < 0 then begin
inc(length, offset);
offset := 0;
end;
if offset + length > len then begin
length := len - offset;
end;
if length > 0 then begin
arrayfill(@(dst[offset]), 2, length, floatToIntBits(value));
end;
end;
procedure arrayfillPrimitives(const dst: double_Array1d; offset, length: int; value: double);
var
len: int;
begin
len := system.length(dst);
if offset < 0 then begin
inc(length, offset);
offset := 0;
end;
if offset + length > len then begin
length := len - offset;
end;
if length > 0 then begin
arrayfill(@(dst[offset]), 3, length, doubleToLongBits(value));
end;
end;
procedure arrayfillPrimitives(const dst: real_Array1d; offset, length: int; const value: real);
var
i: int;
len: int;
begin
len := system.length(dst);
if offset < 0 then begin
inc(length, offset);
offset := 0;
end;
if offset + length > len then begin
length := len - offset;
end;
for i := offset to offset + length - 1 do begin
dst[i] := value;
end;
end;
procedure arrayfillAnsiStrings(const dst: AnsiString_Array1d; offset, length: int; const value: AnsiString);
var
i: int;
len: int;
begin
len := system.length(dst);
if offset < 0 then begin
inc(length, offset);
offset := 0;
end;
if offset + length > len then begin
length := len - offset;
end;
for i := offset to offset + length - 1 do begin
dst[i] := value;
end;
end;
procedure arrayfillUnicodeStrings(const dst: UnicodeString_Array1d; offset, length: int; const value: UnicodeString);
var
i: int;
len: int;
begin
len := system.length(dst);
if offset < 0 then begin
inc(length, offset);
offset := 0;
end;
if offset + length > len then begin
length := len - offset;
end;
for i := offset to offset + length - 1 do begin
dst[i] := value;
end;
end;
procedure arrayfillInterfaces(const dst; offset, length: int; value: IUnknown);
var
i: int;
len: int;
begin
len := system.length(IUnknown_Array1d(dst));
if offset < 0 then begin
inc(length, offset);
offset := 0;
end;
if offset + length > len then begin
length := len - offset;
end;
for i := offset to offset + length - 1 do begin
IUnknown_Array1d(dst)[i] := value;
end;
end;
procedure arrayfillObjects(const dst; offset, length: int; value: TObject);
var
len: int;
begin
len := system.length(TObject_Array1d(dst));
if offset < 0 then begin
inc(length, offset);
offset := 0;
end;
if offset + length > len then begin
length := len - offset;
end;
if length > 0 then begin
arrayfill(@(TObject_Array1d(dst)[offset]), 3, length, long(value));
end;
end;
procedure arrayfillArrays(const dst; offset, length: int; const value);
var
i: int;
len: int;
begin
len := system.length(boolean_Array2d(dst));
if offset < 0 then begin
inc(length, offset);
offset := 0;
end;
if offset + length > len then begin
length := len - offset;
end;
for i := offset to offset + length - 1 do begin
boolean_Array2d(dst)[i] := boolean_Array1d(value);
end;
end;
procedure arraycopyPrimitives(const src: boolean_Array1d; srcOffset: int; const dst: boolean_Array1d; dstOffset: int; length: int);
begin
arrayCheckBounds('arraycopyPrimitives', system.length(src), srcOffset, length);
arrayCheckBounds('arraycopyPrimitives', system.length(dst), dstOffset, length);
system.move(src[srcOffset], dst[dstOffset], length * sizeOf(boolean));
end;
procedure arraycopyPrimitives(const src: char_Array1d; srcOffset: int; const dst: char_Array1d; dstOffset: int; length: int);
begin
arrayCheckBounds('arraycopyPrimitives', system.length(src), srcOffset, length);
arrayCheckBounds('arraycopyPrimitives', system.length(dst), dstOffset, length);
system.move(src[srcOffset], dst[dstOffset], length * sizeOf(char));
end;
procedure arraycopyPrimitives(const src: wchar_Array1d; srcOffset: int; const dst: wchar_Array1d; dstOffset: int; length: int);
begin
arrayCheckBounds('arraycopyPrimitives', system.length(src), srcOffset, length);
arrayCheckBounds('arraycopyPrimitives', system.length(dst), dstOffset, length);
system.move(src[srcOffset], dst[dstOffset], length * sizeOf(wchar));
end;
procedure arraycopyPrimitives(const src: byte_Array1d; srcOffset: int; const dst: byte_Array1d; dstOffset: int; length: int);
begin
arrayCheckBounds('arraycopyPrimitives', system.length(src), srcOffset, length);
arrayCheckBounds('arraycopyPrimitives', system.length(dst), dstOffset, length);
system.move(src[srcOffset], dst[dstOffset], length * sizeOf(byte));
end;
procedure arraycopyPrimitives(const src: short_Array1d; srcOffset: int; const dst: short_Array1d; dstOffset: int; length: int);
begin
arrayCheckBounds('arraycopyPrimitives', system.length(src), srcOffset, length);
arrayCheckBounds('arraycopyPrimitives', system.length(dst), dstOffset, length);
system.move(src[srcOffset], dst[dstOffset], length * sizeOf(short));
end;
procedure arraycopyPrimitives(const src: int_Array1d; srcOffset: int; const dst: int_Array1d; dstOffset: int; length: int);
begin
arrayCheckBounds('arraycopyPrimitives', system.length(src), srcOffset, length);
arrayCheckBounds('arraycopyPrimitives', system.length(dst), dstOffset, length);
system.move(src[srcOffset], dst[dstOffset], length * sizeOf(int));
end;
procedure arraycopyPrimitives(const src: long_Array1d; srcOffset: int; const dst: long_Array1d; dstOffset: int; length: int);
begin
arrayCheckBounds('arraycopyPrimitives', system.length(src), srcOffset, length);
arrayCheckBounds('arraycopyPrimitives', system.length(dst), dstOffset, length);
system.move(src[srcOffset], dst[dstOffset], length * sizeOf(long));
end;
procedure arraycopyPrimitives(const src: float_Array1d; srcOffset: int; const dst: float_Array1d; dstOffset: int; length: int);
begin
arrayCheckBounds('arraycopyPrimitives', system.length(src), srcOffset, length);
arrayCheckBounds('arraycopyPrimitives', system.length(dst), dstOffset, length);
system.move(src[srcOffset], dst[dstOffset], length * sizeOf(float));
end;
procedure arraycopyPrimitives(const src: double_Array1d; srcOffset: int; const dst: double_Array1d; dstOffset: int; length: int);
begin
arrayCheckBounds('arraycopyPrimitives', system.length(src), srcOffset, length);
arrayCheckBounds('arraycopyPrimitives', system.length(dst), dstOffset, length);
system.move(src[srcOffset], dst[dstOffset], length * sizeOf(double));
end;
procedure arraycopyPrimitives(const src: real_Array1d; srcOffset: int; const dst: real_Array1d; dstOffset: int; length: int);
begin
arrayCheckBounds('arraycopyPrimitives', system.length(src), srcOffset, length);
arrayCheckBounds('arraycopyPrimitives', system.length(dst), dstOffset, length);
system.move(src[srcOffset], dst[dstOffset], length * sizeOf(real));
end;
procedure arraycopyAnsiStrings(const src: AnsiString_Array1d; srcOffset: int; const dst: AnsiString_Array1d; dstOffset: int; length: int);
var
i: int;
begin
arrayCheckBounds('arraycopyAnsiStrings', system.length(src), srcOffset, length);
arrayCheckBounds('arraycopyAnsiStrings', system.length(dst), dstOffset, length);
if (src = dst) and (srcOffset < dstOffset) then begin
inc(srcOffset, length);
inc(dstOffset, length);
for i := length - 1 downto 0 do begin
dec(srcOffset);
dec(dstOffset);
dst[dstOffset] := src[srcOffset];
end;
end else begin
for i := 0 to length - 1 do begin
dst[dstOffset] := src[srcOffset];
inc(srcOffset);
inc(dstOffset);
end;
end;
end;
procedure arraycopyUnicodeStrings(const src: UnicodeString_Array1d; srcOffset: int; const dst: UnicodeString_Array1d; dstOffset: int; length: int);
var
i: int;
begin
arrayCheckBounds('arraycopyUnicodeStrings', system.length(src), srcOffset, length);
arrayCheckBounds('arraycopyUnicodeStrings', system.length(dst), dstOffset, length);
if (src = dst) and (srcOffset < dstOffset) then begin
inc(srcOffset, length);
inc(dstOffset, length);
for i := length - 1 downto 0 do begin
dec(srcOffset);
dec(dstOffset);
dst[dstOffset] := src[srcOffset];
end;
end else begin
for i := 0 to length - 1 do begin
dst[dstOffset] := src[srcOffset];
inc(srcOffset);
inc(dstOffset);
end;
end;
end;
procedure arraycopyInterfaces(const src; srcOffset: int; const dst; dstOffset: int; length: int);
var
i: int;
begin
arrayCheckBounds('arraycopyInterfaces', system.length(IUnknown_Array1d(src)), srcOffset, length);
arrayCheckBounds('arraycopyInterfaces', system.length(IUnknown_Array1d(dst)), dstOffset, length);
if (IUnknown_Array1d(src) = IUnknown_Array1d(dst)) and (srcOffset < dstOffset) then begin
inc(srcOffset, length);
inc(dstOffset, length);
for i := length - 1 downto 0 do begin
dec(srcOffset);
dec(dstOffset);
IUnknown_Array1d(dst)[dstOffset] := IUnknown_Array1d(src)[srcOffset];
end;
end else begin
for i := 0 to length - 1 do begin
IUnknown_Array1d(dst)[dstOffset] := IUnknown_Array1d(src)[srcOffset];
inc(srcOffset);
inc(dstOffset);
end;
end;
end;
procedure arraycopyObjects(const src; srcOffset: int; const dst; dstOffset: int; length: int);
begin
arrayCheckBounds('arraycopyObjects', system.length(TObject_Array1d(src)), srcOffset, length);
arrayCheckBounds('arraycopyObjects', system.length(TObject_Array1d(dst)), dstOffset, length);
system.move(TObject_Array1d(src)[srcOffset], TObject_Array1d(dst)[dstOffset], length * sizeOf(TObject));
end;
procedure arraycopyArrays(const src; srcOffset: int; const dst; dstOffset: int; length: int);
var
i: int;
begin
arrayCheckBounds('arraycopyArrays', system.length(boolean_Array2d(src)), srcOffset, length);
arrayCheckBounds('arraycopyArrays', system.length(boolean_Array2d(dst)), dstOffset, length);
if (boolean_Array2d(src) = boolean_Array2d(dst)) and (srcOffset < dstOffset) then begin
inc(srcOffset, length);
inc(dstOffset, length);
for i := length - 1 downto 0 do begin
dec(srcOffset);
dec(dstOffset);
boolean_Array2d(dst)[dstOffset] := boolean_Array2d(src)[srcOffset];
end;
end else begin
for i := 0 to length - 1 do begin
boolean_Array2d(dst)[dstOffset] := boolean_Array2d(src)[srcOffset];
inc(srcOffset);
inc(dstOffset);
end;
end;
end;
procedure arraycopyPointers(const src; srcOffset: int; const dst; dstOffset: int; length: int);
begin
arrayCheckBounds('arraycopyPointers', system.length(Pointer_Array1d(src)), srcOffset, length);
arrayCheckBounds('arraycopyPointers', system.length(Pointer_Array1d(dst)), dstOffset, length);
system.move(Pointer_Array1d(src)[srcOffset], Pointer_Array1d(dst)[dstOffset], length * sizeOf(Pointer));
end;
procedure arrayCheckBounds(const method: AnsiString; arrayLength, offset, length: int);
var
lim: int;
begin
lim := offset + length;
if (lim > arrayLength) or (lim < offset) or (offset > arrayLength) or (offset < 0) then begin
if system.length(method) <= 0 then begin
raise ArrayIndexOutOfBoundsException.create(msgArrayIndexOutOfBounds);
end;
raise ArrayIndexOutOfBoundsException.create(method + ': ' + msgArrayIndexOutOfBounds);
end;
end;
procedure synchronized(m: Monitor);
var
needRaise: boolean;
needSuspend: boolean;
lOwningEntry: Monitor.ThreadEntry;
currentThread: TThread;
begin
if m = nil then begin
raise NullPointerException.create(msgNullPointer);
end;
needRaise := false;
needSuspend := false;
system.enterCriticalSection(m.fMonitorSynchronize);
try
lOwningEntry := m.fOwningEntry;
currentThread := Thread.currentThread;
if lOwningEntry = nil then begin
if m.fWaitingCount >= INT_MAX_VALUE then begin
needRaise := true;
end else begin
m.fOwningEntry := Monitor.ThreadEntry.create(m, currentThread, RUNNING);
end;
end else
if lOwningEntry.fMonitorThread = currentThread then begin
inc(lOwningEntry.fEntryCount);
end else begin
if m.fWaitingCount >= INT_MAX_VALUE - 1 then begin
needRaise := true;
end else begin
needSuspend := true;
lOwningEntry := Monitor.ThreadEntry.create(m, currentThread, SUSPENDED);
m.push(lOwningEntry);
end;
end;
finally
system.leaveCriticalSection(m.fMonitorSynchronize);
end;
if needRaise then begin
raise IllegalMonitorStateException.create(msgIllegalMonitorState);
end;
if needSuspend then begin
lOwningEntry.suspend();
end;
end;
procedure synchronizedEnd(m: Monitor);
var
needRaise: boolean;
lEntryCount: long;
lOwningEntry: Monitor.ThreadEntry;
begin
if m = nil then begin
raise NullPointerException.create(msgNullPointer);
end;
needRaise := false;
system.enterCriticalSection(m.fMonitorSynchronize);
try
lOwningEntry := m.fOwningEntry;
if (lOwningEntry = nil) or (lOwningEntry.fMonitorThread <> Thread.currentThread) then begin
needRaise := true;
end else begin
lEntryCount := lOwningEntry.fEntryCount - 1;
lOwningEntry.fEntryCount := lEntryCount;
if lEntryCount = 0 then begin
lOwningEntry.free();
m.fOwningEntry := nil;
m.pop();
end;
end;
finally
system.leaveCriticalSection(m.fMonitorSynchronize);
end;
if needRaise then begin
raise IllegalMonitorStateException.create(msgIllegalMonitorState);
end;
end;
procedure classInfoAdd(const typeInfos: array of Pointer);
var
curlen: int;
curcap: int;
addlen: int;
newlen: int;
newcap: int;
newdata: PTypeInfo_Array1d;
begin
curlen := typeInfosLength;
curcap := length(typeInfosData);
addlen := length(typeInfos);
newlen := curlen + addlen;
if newlen > curcap then begin
newcap := (curcap shl 1) + 1;
if newcap < newlen then newcap := newlen;
newdata := PTypeInfo_Array1d(Pointer_Array1d_create(newcap));
system.move(typeInfosData[0], newdata[0], curlen * sizeOf(PTypeInfo));
typeInfosData := newdata;
end;
system.move(typeInfos[0], typeInfosData[curlen], addlen * sizeOf(PTypeInfo));
typeInfosLength := newlen;
end;
{$IFDEF WINDOWS}
function getExceptionObject(errorNumber: int; const rec: Windows.TExceptionRecord): TObject;
var
e: TObject;
begin
e := nil;
case errorNumber of
1,
203: e := outOfMemory;
204: e := invalidPointer;
200,
205,
206,
207,
215: e := ArithmeticException.create(msgArithmeticError);
202: e := StackOverflowError.create(msgStackOverflow);
211: e := AbstractMethodError.create(msgAbstractMethod);
216: e := NullPointerException.create(msgNullPointer);
219: e := ClassCastException.create(msgClassCast);
else e := previousGetExceptionObject(errorNumber, rec);
end;
if e = nil then begin
e := NullPointerException.create(msgNullPointer);
end;
result := e;
end;
function getExceptionClass(errorNumber: int): TClass;
var
c: TClass;
begin
c := nil;
case errorNumber of
1,
203: c := OutOfMemoryError;
204: c := InvalidPointerError;
200,
205,
206,
207,
215: c := ArithmeticException;
202: c := StackOverflowError;
211: c := AbstractMethodError;
216: c := NullPointerException;
219: c := ClassCastException;
else c := previousGetExceptionClass(errorNumber);
end;
if c = nil then begin
c := NullPointerException;
end;
result := c;
end;
{$ENDIF}
procedure exceptionHandler(errorNumber: int; address: CodePointer; frame: Pointer);
var
e: TObject;
begin
e := nil;
case errorNumber of
1,
203: e := outOfMemory;
204: e := invalidPointer;
200,
205,
206,
207,
215: e := ArithmeticException.create(msgArithmeticError);
202: e := StackOverflowError.create(msgStackOverflow);
211: e := AbstractMethodError.create(msgAbstractMethod);
216: e := NullPointerException.create(msgNullPointer);
219: e := ClassCastException.create(msgClassCast);
else previousExceptionHandler(errorNumber, address, frame);
end;
if e = nil then begin
e := NullPointerException.create(msgNullPointer);
end;
raise e at address, frame;
end;
procedure exceptionHandlerInitialize();
begin
{$IFDEF WINDOWS}
previousGetExceptionObject := FunctionGetExceptionObject(exceptObjProc);
previousGetExceptionClass := FunctionGetExceptionClass(exceptClsProc);
{$ENDIF}
previousExceptionHandler := errorProc;
outOfMemory := OutOfMemoryError.create(msgOutOfMemory);
outOfMemory.disallowFree := true;
invalidPointer := InvalidPointerError.create(msgInvalidPointer);
invalidPointer.disallowFree := true;
{$IFDEF WINDOWS}
exceptObjProc := @getExceptionObject;
exceptClsProc := @getExceptionClass;
{$ENDIF}
errorProc := @exceptionHandler;
end;
procedure exceptionHandlerFinalize();
begin
{$IFDEF WINDOWS}
exceptObjProc := previousGetExceptionObject;
exceptClsProc := previousGetExceptionClass;
{$ENDIF}
errorProc := previousExceptionHandler;
invalidPointer.disallowFree := false;
invalidPointer.free();
outOfMemory.disallowFree := false;
outOfMemory.free();
end;
{%endregion}
{%region operator }
operator :=(value: byte): real; assembler; nostackframe;
asm
movsx edx, dl
push rdx
fild dword[rsp]
fstp tbyte[rcx]
lea rsp, [rsp+$08]
end;
operator :=(value: short): real; assembler; nostackframe;
asm
movsx edx, dx
push rdx
fild dword[rsp]
fstp tbyte[rcx]
lea rsp, [rsp+$08]
end;
operator :=(value: int): real; assembler; nostackframe;
asm
push rdx
fild dword[rsp]
fstp tbyte[rcx]
lea rsp, [rsp+$08]
end;
operator :=(value: long): real; assembler; nostackframe;
asm
push rdx
fild qword[rsp]
fstp tbyte[rcx]
lea rsp, [rsp+$08]
end;
operator :=(value: float): real; assembler; nostackframe;
asm
lea rsp, [rsp-$08]
movss [rsp], xmm1
fld dword[rsp]
fstp tbyte[rcx]
lea rsp, [rsp+$08]
end;
operator :=(value: double): real; assembler; nostackframe;
asm
lea rsp, [rsp-$08]
movsd [rsp], xmm1
fld qword[rsp]
fstp tbyte[rcx]
lea rsp, [rsp+$08]
end;
operator =(const value1, value2: real): boolean; assembler; nostackframe;
asm
fld tbyte[rdx]
fld tbyte[rcx]
fcomip st, st(1)
ffree st
fincstp
jnp @0
mov al, $ff
or eax, eax
stc
@0: sete al
movzx eax, al
end;
operator <(const value1, value2: real): boolean; assembler; nostackframe;
asm
fld tbyte[rdx]
fld tbyte[rcx]
fcomip st, st(1)
ffree st
fincstp
jnp @0
mov al, $ff
or eax, eax
@0: setb al
movzx eax, al
end;
operator >(const value1, value2: real): boolean; assembler; nostackframe;
asm
fld tbyte[rdx]
fld tbyte[rcx]
fcomip st, st(1)
ffree st
fincstp
jnp @0
mov al, $ff
or eax, eax
stc
@0: seta al
movzx eax, al
end;
operator <=(const value1, value2: real): boolean; assembler; nostackframe;
asm
fld tbyte[rdx]
fld tbyte[rcx]
fcomip st, st(1)
ffree st
fincstp
jnp @0
mov al, $ff
or eax, eax
@0: setbe al
movzx eax, al
end;
operator >=(const value1, value2: real): boolean; assembler; nostackframe;
asm
fld tbyte[rdx]
fld tbyte[rcx]
fcomip st, st(1)
ffree st
fincstp
jnp @0
mov al, $ff
or eax, eax
stc
@0: setae al
movzx eax, al
end;
operator <>(const value1, value2: real): boolean; assembler; nostackframe;
asm
fld tbyte[rdx]
fld tbyte[rcx]
fcomip st, st(1)
ffree st
fincstp
jnp @0
mov al, $ff
or eax, eax
stc
@0: setne al
movzx eax, al
end;
operator +(const value1, value2: real): real; assembler; nostackframe;
asm
fld tbyte[rdx]
fld tbyte[r8]
faddp st(1), st
fstp tbyte[rcx]
end;
operator -(const value1, value2: real): real; assembler; nostackframe;
asm
fld tbyte[rdx]
fld tbyte[r8]
fsubp st(1), st
fstp tbyte[rcx]
end;
operator *(const value1, value2: real): real; assembler; nostackframe;
asm
fld tbyte[rdx]
fld tbyte[r8]
fmulp st(1), st
fstp tbyte[rcx]
end;
operator /(const value1, value2: real): real; assembler; nostackframe;
asm
fld tbyte[rdx]
fld tbyte[r8]
fdivp st(1), st
fstp tbyte[rcx]
end;
operator +(const value: real): real; assembler; nostackframe;
asm
fld tbyte[rdx]
fstp tbyte[rcx]
end;
operator -(const value: real): real; assembler; nostackframe;
asm
fld tbyte[rdx]
fchs
fstp tbyte[rcx]
end;
{%endregion}
{%region TObjectExtended }
class function TObjectExtended.getPropertyInfo(const name: AnsiString): PPropInfo;
var
i: int;
count: int;
lnlen: int;
pinfo: PPropInfo;
tinfo: PTypeInfo;
tdata: PTypeData;
lname: AnsiString;
pname: AnsiString;
begin
lname := stringToLowerCase(name);
lnlen := length(lname);
tinfo := PTypeInfo(self.classInfo());
while tinfo <> nil do begin
tdata := getTypeData(tinfo);
pinfo := PPropInfo(Pointer(@(tdata^.unitName[1])) + int(tdata^.unitName[0]));
count := system.PUInt16(pinfo)^;
pinfo := Pointer(pinfo) + 2;
for i := 0 to count - 1 do begin
pname := pinfo^.name;
if (length(pname) = lnlen) and (stringToLowerCase(pname) = lname) then begin
result := pinfo;
exit;
end;
pinfo := PPropInfo(Pointer(@(pinfo^.name[1])) + int(pinfo^.name[0]));
end;
tinfo := tdata^.parentInfo;
end;
result := nil;
end;
function TObjectExtended.getClass(): _Class;
begin
result := ClassInformation.create(classType());
end;
function TObjectExtended.getIdentityHashCode(): long;
begin
result := long(self);
end;
function TObjectExtended.isStoredProperty(const name: AnsiString): boolean;
type
FunctionIsStoredIndex = function(index: int): boolean of object;
FunctionIsStoredNorm = function(): boolean of object;
var
isIndexed: boolean;
transferMethod: int;
access: CodePointer;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create('TObjectExtended.isStoredProperty: ' + msgPropertyNotFound + getClass().getCanonicalName() + '.' + name);
end;
transferMethod := pinfo^.propProcs;
isIndexed := (transferMethod and $40) <> 0;
transferMethod := (transferMethod shr 4) and $03;
case transferMethod of
TM_FIELD: begin
access := pinfo^.storedProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.isStoredProperty: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
address := Pointer(self) + long((@access)^);
end;
TM_CONST:
address := @(pinfo^.storedProc);
else
access := pinfo^.storedProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.isStoredProperty: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
if transferMethod = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(self.classType()) + long((@access)^))^);
end;
method.data := self;
if isIndexed then begin
result := FunctionIsStoredIndex(method)(pinfo^.index);
exit;
end;
result := FunctionIsStoredNorm(method)();
exit;
end;
result := byte(address^) <> 0;
end;
function TObjectExtended.readPropertyOfBoolean(const name: AnsiString): boolean;
type
FunctionReadBooleanIndex = function(index: int): boolean of object;
FunctionReadBooleanNorm = function(): boolean of object;
var
isIndexed: boolean;
transferMethod: int;
propertyType: int;
access: CodePointer;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create('TObjectExtended.readPropertyOfBoolean: ' + msgPropertyNotFound + getClass().getCanonicalName() + '.' + name);
end;
propertyType := ClassInformation.typeInfoToLangType(pinfo^.propType);
case propertyType of
TYPE_BOOLEAN: begin
transferMethod := pinfo^.propProcs;
isIndexed := (transferMethod and $40) <> 0;
transferMethod := transferMethod and $03;
case transferMethod of
TM_FIELD: begin
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.readPropertyOfBoolean: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
address := Pointer(self) + long((@access)^);
end;
TM_CONST:
address := @(pinfo^.getProc);
else
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.readPropertyOfBoolean: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
if transferMethod = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(self.classType()) + long((@access)^))^);
end;
method.data := self;
if isIndexed then begin
result := FunctionReadBooleanIndex(method)(pinfo^.index);
exit;
end;
result := FunctionReadBooleanNorm(method)();
exit;
end;
result := byte(address^) <> 0;
end
else
raise IllegalPropertyTypeException.create('TObjectExtended.readPropertyOfBoolean: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
end;
function TObjectExtended.readPropertyOfLong(const name: AnsiString): long;
type
FunctionReadUByteIndex = function(index: int): system.UInt8 of object;
FunctionReadUShortIndex = function(index: int): system.UInt16 of object;
FunctionReadUIntIndex = function(index: int): system.UInt32 of object;
FunctionReadByteIndex = function(index: int): byte of object;
FunctionReadShortIndex = function(index: int): short of object;
FunctionReadIntIndex = function(index: int): int of object;
FunctionReadLongIndex = function(index: int): long of object;
FunctionReadUByteNorm = function(): system.UInt8 of object;
FunctionReadUShortNorm = function(): system.UInt16 of object;
FunctionReadUIntNorm = function(): system.UInt32 of object;
FunctionReadByteNorm = function(): byte of object;
FunctionReadShortNorm = function(): short of object;
FunctionReadIntNorm = function(): int of object;
FunctionReadLongNorm = function(): long of object;
var
isIndexed: boolean;
transferMethod: int;
propertyType: int;
access: CodePointer;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create('TObjectExtended.readPropertyOfLong: ' + msgPropertyNotFound + getClass().getCanonicalName() + '.' + name);
end;
propertyType := ClassInformation.typeInfoToLangType(pinfo^.propType);
case propertyType of
TYPE_CHAR, TYPE_WCHAR, TYPE_BYTE, TYPE_SHORT, TYPE_INT, TYPE_LONG, TYPE_UBYTE, TYPE_USHORT, TYPE_UINT, TYPE_ULONG: begin
transferMethod := pinfo^.propProcs;
isIndexed := (transferMethod and $40) <> 0;
transferMethod := transferMethod and $03;
case transferMethod of
TM_FIELD: begin
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.readPropertyOfLong: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
address := Pointer(self) + long((@access)^);
end;
TM_CONST:
address := @(pinfo^.getProc);
else
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.readPropertyOfLong: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
if transferMethod = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(self.classType()) + long((@access)^))^);
end;
method.data := self;
if isIndexed then begin
case propertyType of
TYPE_UBYTE, TYPE_CHAR:
result := FunctionReadUByteIndex(method)(pinfo^.index);
TYPE_USHORT, TYPE_WCHAR:
result := FunctionReadUShortIndex(method)(pinfo^.index);
TYPE_UINT:
result := FunctionReadUIntIndex(method)(pinfo^.index);
TYPE_BYTE:
result := FunctionReadByteIndex(method)(pinfo^.index);
TYPE_SHORT:
result := FunctionReadShortIndex(method)(pinfo^.index);
TYPE_INT:
result := FunctionReadIntIndex(method)(pinfo^.index);
else
result := FunctionReadLongIndex(method)(pinfo^.index);
end;
exit;
end;
case propertyType of
TYPE_UBYTE, TYPE_CHAR:
result := FunctionReadUByteNorm(method)();
TYPE_USHORT, TYPE_WCHAR:
result := FunctionReadUShortNorm(method)();
TYPE_UINT:
result := FunctionReadUIntNorm(method)();
TYPE_BYTE:
result := FunctionReadByteNorm(method)();
TYPE_SHORT:
result := FunctionReadShortNorm(method)();
TYPE_INT:
result := FunctionReadIntNorm(method)();
else
result := FunctionReadLongNorm(method)();
end;
exit;
end;
case propertyType of
TYPE_UBYTE, TYPE_CHAR:
result := system.UInt8(address^);
TYPE_USHORT, TYPE_WCHAR:
result := system.UInt16(address^);
TYPE_UINT:
result := system.UInt32(address^);
TYPE_BYTE:
result := byte(address^);
TYPE_SHORT:
result := short(address^);
TYPE_INT:
result := int(address^);
else
result := long(address^);
end;
end
else
raise IllegalPropertyTypeException.create('TObjectExtended.readPropertyOfLong: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
end;
function TObjectExtended.readPropertyOfDouble(const name: AnsiString): double;
type
FunctionReadFloatIndex = function(index: int): float of object;
FunctionReadDoubleIndex = function(index: int): double of object;
FunctionReadFloatNorm = function(): float of object;
FunctionReadDoubleNorm = function(): double of object;
var
isIndexed: boolean;
transferMethod: int;
propertyType: int;
access: CodePointer;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create('TObjectExtended.readPropertyOfDouble: ' + msgPropertyNotFound + getClass().getCanonicalName() + '.' + name);
end;
propertyType := ClassInformation.typeInfoToLangType(pinfo^.propType);
case propertyType of
TYPE_FLOAT, TYPE_DOUBLE: begin
transferMethod := pinfo^.propProcs;
isIndexed := (transferMethod and $40) <> 0;
transferMethod := transferMethod and $03;
case transferMethod of
TM_FIELD: begin
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.readPropertyOfDouble: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
address := Pointer(self) + long((@access)^);
end;
TM_CONST:
address := @(pinfo^.getProc);
else
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.readPropertyOfDouble: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
if transferMethod = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(self.classType()) + long((@access)^))^);
end;
method.data := self;
if isIndexed then begin
case propertyType of
TYPE_FLOAT:
result := FunctionReadFloatIndex(method)(pinfo^.index);
else
result := FunctionReadDoubleIndex(method)(pinfo^.index);
end;
exit;
end;
case propertyType of
TYPE_FLOAT:
result := FunctionReadFloatNorm(method)();
else
result := FunctionReadDoubleNorm(method)();
end;
exit;
end;
case propertyType of
TYPE_FLOAT:
result := float(address^);
else
result := double(address^);
end;
end
else
raise IllegalPropertyTypeException.create('TObjectExtended.readPropertyOfDouble: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
end;
function TObjectExtended.readPropertyOfObject(const name: AnsiString): TObject;
type
FunctionReadObjectIndex = function(index: int): TObject of object;
FunctionReadObjectNorm = function(): TObject of object;
var
isIndexed: boolean;
transferMethod: int;
propertyType: int;
access: CodePointer;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create('TObjectExtended.readPropertyOfObject: ' + msgPropertyNotFound + getClass().getCanonicalName() + '.' + name);
end;
propertyType := ClassInformation.typeInfoToLangType(pinfo^.propType);
case propertyType of
TYPE_CLASS: begin
transferMethod := pinfo^.propProcs;
isIndexed := (transferMethod and $40) <> 0;
transferMethod := transferMethod and $03;
case transferMethod of
TM_FIELD: begin
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.readPropertyOfObject: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
address := Pointer(self) + long((@access)^);
end;
TM_CONST:
address := @(pinfo^.getProc);
else
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.readPropertyOfObject: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
if transferMethod = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(self.classType()) + long((@access)^))^);
end;
method.data := self;
if isIndexed then begin
result := FunctionReadObjectIndex(method)(pinfo^.index);
exit;
end;
result := FunctionReadObjectNorm(method)();
exit;
end;
result := TObject(address^);
end
else
raise IllegalPropertyTypeException.create('TObjectExtended.readPropertyOfObject: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
end;
function TObjectExtended.readPropertyOfInterface(const name: AnsiString): IUnknown;
type
FunctionReadInterfaceIndex = function(index: int): IUnknown of object;
FunctionReadInterfaceNorm = function(): IUnknown of object;
var
isIndexed: boolean;
transferMethod: int;
propertyType: int;
access: CodePointer;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create('TObjectExtended.readPropertyOfInterface: ' + msgPropertyNotFound + getClass().getCanonicalName() + '.' + name);
end;
propertyType := ClassInformation.typeInfoToLangType(pinfo^.propType);
case propertyType of
TYPE_INTERFACE: begin
transferMethod := pinfo^.propProcs;
isIndexed := (transferMethod and $40) <> 0;
transferMethod := transferMethod and $03;
case transferMethod of
TM_FIELD: begin
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.readPropertyOfInterface: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
address := Pointer(self) + long((@access)^);
end;
TM_CONST:
address := @(pinfo^.getProc);
else
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.readPropertyOfInterface: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
if transferMethod = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(self.classType()) + long((@access)^))^);
end;
method.data := self;
if isIndexed then begin
result := FunctionReadInterfaceIndex(method)(pinfo^.index);
exit;
end;
result := FunctionReadInterfaceNorm(method)();
exit;
end;
result := IUnknown(address^);
end
else
raise IllegalPropertyTypeException.create('TObjectExtended.readPropertyOfInterface: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
end;
function TObjectExtended.readPropertyOfAnsiString(const name: AnsiString): AnsiString;
type
FunctionReadAnsiStringIndex = function(index: int): AnsiString of object;
FunctionReadAnsiStringNorm = function(): AnsiString of object;
var
isIndexed: boolean;
transferMethod: int;
propertyType: int;
access: CodePointer;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create('TObjectExtended.readPropertyOfAnsiString: ' + msgPropertyNotFound + getClass().getCanonicalName() + '.' + name);
end;
propertyType := ClassInformation.typeInfoToLangType(pinfo^.propType);
case propertyType of
TYPE_ANSISTRING: begin
transferMethod := pinfo^.propProcs;
isIndexed := (transferMethod and $40) <> 0;
transferMethod := transferMethod and $03;
case transferMethod of
TM_FIELD: begin
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.readPropertyOfAnsiString: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
address := Pointer(self) + long((@access)^);
end;
TM_CONST:
address := @(pinfo^.getProc);
else
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.readPropertyOfAnsiString: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
if transferMethod = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(self.classType()) + long((@access)^))^);
end;
method.data := self;
if isIndexed then begin
result := FunctionReadAnsiStringIndex(method)(pinfo^.index);
exit;
end;
result := FunctionReadAnsiStringNorm(method)();
exit;
end;
result := AnsiString(address^);
end
else
raise IllegalPropertyTypeException.create('TObjectExtended.readPropertyOfAnsiString: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
end;
function TObjectExtended.readPropertyOfUnicodeString(const name: AnsiString): UnicodeString;
type
FunctionReadUnicodeStringIndex = function(index: int): UnicodeString of object;
FunctionReadUnicodeStringNorm = function(): UnicodeString of object;
var
isIndexed: boolean;
transferMethod: int;
propertyType: int;
access: CodePointer;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create('TObjectExtended.readPropertyOfUnicodeString: ' + msgPropertyNotFound + getClass().getCanonicalName() + '.' + name);
end;
propertyType := ClassInformation.typeInfoToLangType(pinfo^.propType);
case propertyType of
TYPE_UNICODESTRING: begin
transferMethod := pinfo^.propProcs;
isIndexed := (transferMethod and $40) <> 0;
transferMethod := transferMethod and $03;
case transferMethod of
TM_FIELD: begin
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.readPropertyOfUnicodeString: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
address := Pointer(self) + long((@access)^);
end;
TM_CONST:
address := @(pinfo^.getProc);
else
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.readPropertyOfUnicodeString: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
if transferMethod = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(self.classType()) + long((@access)^))^);
end;
method.data := self;
if isIndexed then begin
result := FunctionReadUnicodeStringIndex(method)(pinfo^.index);
exit;
end;
result := FunctionReadUnicodeStringNorm(method)();
exit;
end;
result := UnicodeString(address^);
end
else
raise IllegalPropertyTypeException.create('TObjectExtended.readPropertyOfUnicodeString: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
end;
procedure TObjectExtended.writePropertyOfBoolean(const name: AnsiString; value: boolean);
type
ProcedureWriteBooleanIndex = procedure(index: int; value: boolean) of object;
ProcedureWriteBooleanNorm = procedure(value: boolean) of object;
var
isIndexed: boolean;
transferMethod: int;
propertyType: int;
access: CodePointer;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create('TObjectExtended.writePropertyOfBoolean: ' + msgPropertyNotFound + getClass().getCanonicalName() + '.' + name);
end;
access := pinfo^.setProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.writePropertyOfBoolean: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
propertyType := ClassInformation.typeInfoToLangType(pinfo^.propType);
case propertyType of
TYPE_BOOLEAN: begin
transferMethod := pinfo^.propProcs;
isIndexed := (transferMethod and $40) <> 0;
transferMethod := (transferMethod shr 2) and $03;
case transferMethod of
TM_FIELD: begin
address := Pointer(self) + long((@access)^);
boolean(address^) := value;
end;
TM_SPECIAL, TM_VIRTUAL: begin
if transferMethod = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(self.classType()) + long((@access)^))^);
end;
method.data := self;
if isIndexed then begin
ProcedureWriteBooleanIndex(method)(pinfo^.index, value);
exit;
end;
ProcedureWriteBooleanNorm(method)(value);
end;
end;
end
else
raise IllegalPropertyTypeException.create('TObjectExtended.writePropertyOfBoolean: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
end;
procedure TObjectExtended.writePropertyOfLong(const name: AnsiString; value: long);
type
ProcedureWriteUByteIndex = procedure(index: int; value: system.UInt8) of object;
ProcedureWriteUShortIndex = procedure(index: int; value: system.UInt16) of object;
ProcedureWriteUIntIndex = procedure(index: int; value: system.UInt32) of object;
ProcedureWriteByteIndex = procedure(index: int; value: byte) of object;
ProcedureWriteShortIndex = procedure(index: int; value: short) of object;
ProcedureWriteIntIndex = procedure(index: int; value: int) of object;
ProcedureWriteLongIndex = procedure(index: int; value: long) of object;
ProcedureWriteUByteNorm = procedure(value: system.UInt8) of object;
ProcedureWriteUShortNorm = procedure(value: system.UInt16) of object;
ProcedureWriteUIntNorm = procedure(value: system.UInt32) of object;
ProcedureWriteByteNorm = procedure(value: byte) of object;
ProcedureWriteShortNorm = procedure(value: short) of object;
ProcedureWriteIntNorm = procedure(value: int) of object;
ProcedureWriteLongNorm = procedure(value: long) of object;
var
isIndexed: boolean;
transferMethod: int;
propertyType: int;
access: CodePointer;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create('TObjectExtended.writePropertyOfLong: ' + msgPropertyNotFound + getClass().getCanonicalName() + '.' + name);
end;
access := pinfo^.setProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.writePropertyOfLong: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
propertyType := ClassInformation.typeInfoToLangType(pinfo^.propType);
case propertyType of
TYPE_CHAR, TYPE_WCHAR, TYPE_BYTE, TYPE_SHORT, TYPE_INT, TYPE_LONG, TYPE_UBYTE, TYPE_USHORT, TYPE_UINT, TYPE_ULONG: begin
transferMethod := pinfo^.propProcs;
isIndexed := (transferMethod and $40) <> 0;
transferMethod := (transferMethod shr 2) and $03;
case transferMethod of
TM_FIELD: begin
address := Pointer(self) + long((@access)^);
case propertyType of
TYPE_BYTE, TYPE_UBYTE, TYPE_CHAR:
byte(address^) := byte(value);
TYPE_SHORT, TYPE_USHORT, TYPE_WCHAR:
short(address^) := short(value);
TYPE_INT, TYPE_UINT:
int(address^) := int(value);
else
long(address^) := value;
end;
end;
TM_SPECIAL, TM_VIRTUAL: begin
if transferMethod = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(self.classType()) + long((@access)^))^);
end;
method.data := self;
if isIndexed then begin
case propertyType of
TYPE_UBYTE, TYPE_CHAR:
ProcedureWriteUByteIndex(method)(pinfo^.index, system.UInt8(value));
TYPE_USHORT, TYPE_WCHAR:
ProcedureWriteUShortIndex(method)(pinfo^.index, system.UInt16(value));
TYPE_UINT:
ProcedureWriteUIntIndex(method)(pinfo^.index, system.UInt32(value));
TYPE_BYTE:
ProcedureWriteByteIndex(method)(pinfo^.index, byte(value));
TYPE_SHORT:
ProcedureWriteShortIndex(method)(pinfo^.index, short(value));
TYPE_INT:
ProcedureWriteIntIndex(method)(pinfo^.index, int(value));
else
ProcedureWriteLongIndex(method)(pinfo^.index, value);
end;
exit;
end;
case propertyType of
TYPE_UBYTE, TYPE_CHAR:
ProcedureWriteUByteNorm(method)(system.UInt8(value));
TYPE_USHORT, TYPE_WCHAR:
ProcedureWriteUShortNorm(method)(system.UInt16(value));
TYPE_UINT:
ProcedureWriteUIntNorm(method)(system.UInt32(value));
TYPE_BYTE:
ProcedureWriteByteNorm(method)(byte(value));
TYPE_SHORT:
ProcedureWriteShortNorm(method)(short(value));
TYPE_INT:
ProcedureWriteIntNorm(method)(int(value));
else
ProcedureWriteLongNorm(method)(value);
end;
end;
end;
end
else
raise IllegalPropertyTypeException.create('TObjectExtended.writePropertyOfLong: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
end;
procedure TObjectExtended.writePropertyOfDouble(const name: AnsiString; value: double);
type
ProcedureWriteFloatIndex = procedure(index: int; value: float) of object;
ProcedureWriteDoubleIndex = procedure(index: int; value: double) of object;
ProcedureWriteFloatNorm = procedure(value: float) of object;
ProcedureWriteDoubleNorm = procedure(value: double) of object;
var
isIndexed: boolean;
transferMethod: int;
propertyType: int;
access: CodePointer;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create('TObjectExtended.writePropertyOfDouble: ' + msgPropertyNotFound + getClass().getCanonicalName() + '.' + name);
end;
access := pinfo^.setProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.writePropertyOfDouble: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
propertyType := ClassInformation.typeInfoToLangType(pinfo^.propType);
case propertyType of
TYPE_FLOAT, TYPE_DOUBLE: begin
transferMethod := pinfo^.propProcs;
isIndexed := (transferMethod and $40) <> 0;
transferMethod := (transferMethod shr 2) and $03;
case transferMethod of
TM_FIELD: begin
address := Pointer(self) + long((@access)^);
case propertyType of
TYPE_FLOAT:
float(address^) := doubleToFloat(value);
else
double(address^) := value;
end;
end;
TM_SPECIAL, TM_VIRTUAL: begin
if transferMethod = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(self.classType()) + long((@access)^))^);
end;
method.data := self;
if isIndexed then begin
case propertyType of
TYPE_FLOAT:
ProcedureWriteFloatIndex(method)(pinfo^.index, doubleToFloat(value));
else
ProcedureWriteDoubleIndex(method)(pinfo^.index, value);
end;
exit;
end;
case propertyType of
TYPE_FLOAT:
ProcedureWriteFloatNorm(method)(doubleToFloat(value));
else
ProcedureWriteDoubleNorm(method)(value);
end;
end;
end;
end
else
raise IllegalPropertyTypeException.create('TObjectExtended.writePropertyOfDouble: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
end;
procedure TObjectExtended.writePropertyOfObject(const name: AnsiString; value: TObject);
type
ProcedureWriteObjectIndex = procedure(index: int; value: TObject) of object;
ProcedureWriteObjectNorm = procedure(value: TObject) of object;
var
isIndexed: boolean;
transferMethod: int;
propertyType: int;
propertyTypeExt: PTypeInfo;
access: CodePointer;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create('TObjectExtended.writePropertyOfObject: ' + msgPropertyNotFound + getClass().getCanonicalName() + '.' + name);
end;
access := pinfo^.setProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.writePropertyOfObject: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
propertyTypeExt := pinfo^.propType;
propertyType := ClassInformation.typeInfoToLangType(propertyTypeExt);
case propertyType of
TYPE_CLASS: begin
if (value <> nil) and not (ClassInformation.create(getTypeData(propertyTypeExt)^.classType) as _Class).isAssignableFrom(value.getClass()) then begin
raise IllegalPropertyTypeException.create('TObjectExtended.writePropertyOfObject: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
transferMethod := pinfo^.propProcs;
isIndexed := (transferMethod and $40) <> 0;
transferMethod := (transferMethod shr 2) and $03;
case transferMethod of
TM_FIELD: begin
address := Pointer(self) + long((@access)^);
TObject(address^) := value;
end;
TM_SPECIAL, TM_VIRTUAL: begin
if transferMethod = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(self.classType()) + long((@access)^))^);
end;
method.data := self;
if isIndexed then begin
ProcedureWriteObjectIndex(method)(pinfo^.index, value);
exit;
end;
ProcedureWriteObjectNorm(method)(value);
end;
end;
end
else
raise IllegalPropertyTypeException.create('TObjectExtended.writePropertyOfObject: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
end;
procedure TObjectExtended.writePropertyOfInterface(const name: AnsiString; value: IUnknown);
type
ProcedureWriteInterfaceIndex = procedure(index: int; value: IUnknown) of object;
ProcedureWriteInterfaceNorm = procedure(value: IUnknown) of object;
var
isIndexed: boolean;
transferMethod: int;
propertyType: int;
propertyTypeExt: PTypeInfo;
access: CodePointer;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
newvalue: IUnknown;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create('TObjectExtended.writePropertyOfInterface: ' + msgPropertyNotFound + getClass().getCanonicalName() + '.' + name);
end;
access := pinfo^.setProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.writePropertyOfInterface: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
propertyTypeExt := pinfo^.propType;
propertyType := ClassInformation.typeInfoToLangType(propertyTypeExt);
case propertyType of
TYPE_INTERFACE: begin
newvalue := nil;
if (value <> nil) and (value.queryInterface(getTypeData(propertyTypeExt)^.guid, newvalue) <> S_OK) then begin
raise IllegalPropertyTypeException.create('TObjectExtended.writePropertyOfInterface: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
transferMethod := pinfo^.propProcs;
isIndexed := (transferMethod and $40) <> 0;
transferMethod := (transferMethod shr 2) and $03;
case transferMethod of
TM_FIELD: begin
address := Pointer(self) + long((@access)^);
IUnknown(address^) := newvalue;
end;
TM_SPECIAL, TM_VIRTUAL: begin
if transferMethod = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(self.classType()) + long((@access)^))^);
end;
method.data := self;
if isIndexed then begin
ProcedureWriteInterfaceIndex(method)(pinfo^.index, newvalue);
exit;
end;
ProcedureWriteInterfaceNorm(method)(newvalue);
end;
end;
end
else
raise IllegalPropertyTypeException.create('TObjectExtended.writePropertyOfInterface: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
end;
procedure TObjectExtended.writePropertyOfAnsiString(const name: AnsiString; const value: AnsiString);
type
ProcedureWriteAnsiStringIndex = procedure(index: int; value: AnsiString) of object;
ProcedureWriteAnsiStringNorm = procedure(value: AnsiString) of object;
var
isIndexed: boolean;
transferMethod: int;
propertyType: int;
access: CodePointer;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create('TObjectExtended.writePropertyOfAnsiString: ' + msgPropertyNotFound + getClass().getCanonicalName() + '.' + name);
end;
access := pinfo^.setProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.writePropertyOfAnsiString: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
propertyType := ClassInformation.typeInfoToLangType(pinfo^.propType);
case propertyType of
TYPE_ANSISTRING: begin
transferMethod := pinfo^.propProcs;
isIndexed := (transferMethod and $40) <> 0;
transferMethod := (transferMethod shr 2) and $03;
case transferMethod of
TM_FIELD: begin
address := Pointer(self) + long((@access)^);
AnsiString(address^) := value;
end;
TM_SPECIAL, TM_VIRTUAL: begin
if transferMethod = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(self.classType()) + long((@access)^))^);
end;
method.data := self;
if isIndexed then begin
ProcedureWriteAnsiStringIndex(method)(pinfo^.index, value);
exit;
end;
ProcedureWriteAnsiStringNorm(method)(value);
end;
end;
end
else
raise IllegalPropertyTypeException.create('TObjectExtended.writePropertyOfAnsiString: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
end;
procedure TObjectExtended.writePropertyOfUnicodeString(const name: AnsiString; const value: UnicodeString);
type
ProcedureWriteUnicodeStringIndex = procedure(index: int; value: UnicodeString) of object;
ProcedureWriteUnicodeStringNorm = procedure(value: UnicodeString) of object;
var
isIndexed: boolean;
transferMethod: int;
propertyType: int;
access: CodePointer;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create('TObjectExtended.writePropertyOfUnicodeString: ' + msgPropertyNotFound + getClass().getCanonicalName() + '.' + name);
end;
access := pinfo^.setProc;
if access = nil then begin
raise IllegalPropertyAccessException.create('TObjectExtended.writePropertyOfUnicodeString: ' + msgIllegalPropertyAccess + getClass().getCanonicalName() + '.' + name);
end;
propertyType := ClassInformation.typeInfoToLangType(pinfo^.propType);
case propertyType of
TYPE_UNICODESTRING: begin
transferMethod := pinfo^.propProcs;
isIndexed := (transferMethod and $40) <> 0;
transferMethod := (transferMethod shr 2) and $03;
case transferMethod of
TM_FIELD: begin
address := Pointer(self) + long((@access)^);
UnicodeString(address^) := value;
end;
TM_SPECIAL, TM_VIRTUAL: begin
if transferMethod = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(self.classType()) + long((@access)^))^);
end;
method.data := self;
if isIndexed then begin
ProcedureWriteUnicodeStringIndex(method)(pinfo^.index, value);
exit;
end;
ProcedureWriteUnicodeStringNorm(method)(value);
end;
end;
end
else
raise IllegalPropertyTypeException.create('TObjectExtended.writePropertyOfUnicodeString: ' + msgIllegalPropertyType + getClass().getCanonicalName() + '.' + name);
end;
end;
{%endregion}
{%region _Object }
constructor _Object.create();
begin
inherited create();
end;
destructor _Object.destroy;
begin
inherited destroy;
end;
function _Object.equals(anot: TObject): boolean;
begin
result := anot = self;
end;
function _Object.getHashCode(): long;
begin
result := long(self);
end;
function _Object.toString(): AnsiString;
begin
result := getClass().getCanonicalName() + '@' + longToHexString(getHashCode());
end;
function _Object.queryInterface({$IFDEF FPC_HAS_CONSTREF} constref {$ELSE} const {$ENDIF} iid: TGuid; out obj): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF};
begin
if getInterface(iid, obj) then begin
result := S_OK;
end else begin
result := E_NOINTERFACE;
end;
end;
function _Object._addref(): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF};
begin
result := -1;
end;
function _Object._release(): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF};
begin
result := -1;
end;
procedure _Object.afterConstruction();
begin
end;
procedure _Object.beforeDestruction();
begin
end;
{%endregion}
{%region RefCountInterfacedObject }
class function RefCountInterfacedObject.newInstance(): TObject;
begin
result := inherited newInstance();
if result <> nil then begin
RefCountInterfacedObject(result).refcount := 1;
end;
end;
function RefCountInterfacedObject._addref(): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF};
begin
result := interlockedIncrement(@refcount);
end;
function RefCountInterfacedObject._release(): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF};
begin
result := interlockedDecrement(@refcount);
if result = 0 then destroy;
end;
procedure RefCountInterfacedObject.afterConstruction(); assembler; nostackframe;
asm
lock dec dword[rcx+offset refcount]
end;
procedure RefCountInterfacedObject.beforeDestruction();
begin
if refcount <> 0 then begin
raise RuntimeException.create('Error 204 (refcount != 0)');
end;
end;
{%endregion}
{%region DynamicalyAllocatedObject }
constructor DynamicalyAllocatedObject.create();
begin
inherited create();
end;
{%endregion}
{%region ValueOfBoolean }
constructor ValueOfBoolean.create(value: boolean);
begin
inherited create();
if value then begin
self.value := -1;
end else begin
self.value := 0;
end;
end;
function ValueOfBoolean.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is ValueOfBoolean) and (ValueOfBoolean(anot).value = value);
end;
function ValueOfBoolean.getHashCode(): long;
begin
if value = 0 then begin
result := 1237;
exit;
end;
result := 1231;
end;
function ValueOfBoolean.toString(): AnsiString;
begin
if value = 0 then begin
result := 'false';
exit;
end;
result := 'true';
end;
function ValueOfBoolean.getType(): int;
begin
result := TYPE_BOOLEAN;
end;
function ValueOfBoolean.booleanValue(): boolean;
begin
result := value <> 0;
end;
function ValueOfBoolean.intValue(): int;
begin
result := value;
end;
function ValueOfBoolean.longValue(): long;
begin
result := value;
end;
function ValueOfBoolean.floatValue(): float;
begin
result := intToFloat(value);
end;
function ValueOfBoolean.doubleValue(): double;
begin
result := intToDouble(value);
end;
function ValueOfBoolean.realValue(): real;
begin
result := value;
end;
function ValueOfBoolean.ansiStringValue(): AnsiString;
begin
if value = 0 then begin
result := 'false';
exit;
end;
result := 'true';
end;
function ValueOfBoolean.unicodeStringValue(): UnicodeString;
begin
if value = 0 then begin
result := 'false';
exit;
end;
result := 'true';
end;
function ValueOfBoolean.objectValue(): TObject;
begin
result := self;
end;
function ValueOfBoolean.interfaceValue(): IUnknown;
begin
result := self;
end;
function ValueOfBoolean.getSize(): int;
begin
result := 1;
end;
procedure ValueOfBoolean.writeToByteArray(const dst: byte_Array1d; offset: int);
begin
arrayCheckBounds('ValueOfBoolean.writeToByteArray', system.length(dst), offset, 1);
dst[offset] := value;
end;
procedure ValueOfBoolean.writeToByteArrayLE(const dst: byte_Array1d; offset: int);
begin
arrayCheckBounds('ValueOfBoolean.writeToByteArrayLE', system.length(dst), offset, 1);
dst[offset] := value;
end;
{%endregion}
{%region ValueOfLong }
constructor ValueOfLong.create(value: long; &type: int);
begin
inherited create();
if (value >= BYTE_MIN_VALUE) and (value <= BYTE_MAX_VALUE) then begin
if (&type <> TYPE_SHORT) and (&type <> TYPE_INT) and (&type <> TYPE_LONG) then &type := TYPE_BYTE;
end else
if (value >= SHORT_MIN_VALUE) and (value <= SHORT_MAX_VALUE) then begin
if (&type <> TYPE_INT) and (&type <> TYPE_LONG) then &type := TYPE_SHORT;
end else
if (value >= INT_MIN_VALUE) and (value <= INT_MAX_VALUE) then begin
if &type <> TYPE_LONG then &type := TYPE_INT;
end else begin
&type := TYPE_LONG;
end;
self.value := value;
self.&type := &type;
end;
function ValueOfLong.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is ValueOfLong) and (ValueOfLong(anot).value = value);
end;
function ValueOfLong.getHashCode(): long;
begin
result := value;
end;
function ValueOfLong.toString(): AnsiString;
begin
result := longToString(value);
end;
function ValueOfLong.getType(): int;
begin
result := &type;
end;
function ValueOfLong.booleanValue(): boolean;
begin
result := value <> 0;
end;
function ValueOfLong.intValue(): int;
begin
result := int(value);
end;
function ValueOfLong.longValue(): long;
begin
result := value;
end;
function ValueOfLong.floatValue(): float;
begin
result := longToFloat(value);
end;
function ValueOfLong.doubleValue(): double;
begin
result := longToDouble(value);
end;
function ValueOfLong.realValue(): real;
begin
result := value;
end;
function ValueOfLong.ansiStringValue(): AnsiString;
begin
result := longToString(value);
end;
function ValueOfLong.unicodeStringValue(): UnicodeString;
begin
result := stringToUTF16(longToString(value));
end;
function ValueOfLong.objectValue(): TObject;
begin
result := self;
end;
function ValueOfLong.interfaceValue(): IUnknown;
begin
result := self;
end;
function ValueOfLong.getSize(): int;
begin
case &type of
TYPE_BYTE:
result := 1;
TYPE_SHORT:
result := 2;
TYPE_INT:
result := 4;
else
result := 8;
end;
end;
procedure ValueOfLong.writeToByteArray(const dst: byte_Array1d; offset: int);
begin
case &type of
TYPE_BYTE: begin
arrayCheckBounds('ValueOfLong.writeToByteArray', system.length(dst), offset, 1);
dst[offset] := byte(value);
end;
TYPE_SHORT: begin
arrayCheckBounds('ValueOfLong.writeToByteArray', system.length(dst), offset, 2);
short((@(dst[offset]))^) := shortByteSwap(short(value));
end;
TYPE_INT: begin
arrayCheckBounds('ValueOfLong.writeToByteArray', system.length(dst), offset, 4);
int((@(dst[offset]))^) := intByteSwap(int(value));
end
else
arrayCheckBounds('ValueOfLong.writeToByteArray', system.length(dst), offset, 8);
long((@(dst[offset]))^) := longByteSwap(value);
end;
end;
procedure ValueOfLong.writeToByteArrayLE(const dst: byte_Array1d; offset: int);
begin
case &type of
TYPE_BYTE: begin
arrayCheckBounds('ValueOfLong.writeToByteArrayLE', system.length(dst), offset, 1);
dst[offset] := byte(value);
end;
TYPE_SHORT: begin
arrayCheckBounds('ValueOfLong.writeToByteArrayLE', system.length(dst), offset, 2);
short((@(dst[offset]))^) := short(value);
end;
TYPE_INT: begin
arrayCheckBounds('ValueOfLong.writeToByteArrayLE', system.length(dst), offset, 4);
int((@(dst[offset]))^) := int(value);
end
else
arrayCheckBounds('ValueOfLong.writeToByteArrayLE', system.length(dst), offset, 8);
long((@(dst[offset]))^) := value;
end;
end;
{%endregion}
{%region ValueOfFloat }
constructor ValueOfFloat.create(value: float);
begin
inherited create();
self.value := value;
end;
function ValueOfFloat.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is ValueOfFloat) and (floatToIntBits(ValueOfFloat(anot).value) = floatToIntBits(value));
end;
function ValueOfFloat.getHashCode(): long;
begin
result := floatToIntBits(value);
end;
function ValueOfFloat.toString(): AnsiString;
begin
result := floatRepresenter.toString(value);
end;
function ValueOfFloat.getType(): int;
begin
result := TYPE_FLOAT;
end;
function ValueOfFloat.booleanValue(): boolean;
begin
result := value <> 0.0;
end;
function ValueOfFloat.intValue(): int;
begin
result := floatToInt(value);
end;
function ValueOfFloat.longValue(): long;
begin
result := floatToLong(value);
end;
function ValueOfFloat.floatValue(): float;
begin
result := value;
end;
function ValueOfFloat.doubleValue(): double;
begin
result := value;
end;
function ValueOfFloat.realValue(): real;
begin
result := value;
end;
function ValueOfFloat.ansiStringValue(): AnsiString;
begin
result := floatRepresenter.toString(value);
end;
function ValueOfFloat.unicodeStringValue(): UnicodeString;
begin
result := stringToUTF16(floatRepresenter.toString(value));
end;
function ValueOfFloat.objectValue(): TObject;
begin
result := self;
end;
function ValueOfFloat.interfaceValue(): IUnknown;
begin
result := self;
end;
function ValueOfFloat.getSize(): int;
begin
result := 4;
end;
procedure ValueOfFloat.writeToByteArray(const dst: byte_Array1d; offset: int);
begin
arrayCheckBounds('ValueOfFloat.writeToByteArray', system.length(dst), offset, 4);
int((@(dst[offset]))^) := intByteSwap(floatToIntBits(value));
end;
procedure ValueOfFloat.writeToByteArrayLE(const dst: byte_Array1d; offset: int);
begin
arrayCheckBounds('ValueOfFloat.writeToByteArrayLE', system.length(dst), offset, 4);
int((@(dst[offset]))^) := floatToIntBits(value);
end;
{%endregion}
{%region ValueOfDouble }
constructor ValueOfDouble.create(value: double);
begin
inherited create();
self.value := value;
end;
function ValueOfDouble.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is ValueOfDouble) and (doubleToLongBits(ValueOfDouble(anot).value) = doubleToLongBits(value));
end;
function ValueOfDouble.getHashCode(): long;
begin
result := doubleToLongBits(value);
end;
function ValueOfDouble.toString(): AnsiString;
begin
result := doubleRepresenter.toString(value);
end;
function ValueOfDouble.getType(): int;
begin
result := TYPE_DOUBLE;
end;
function ValueOfDouble.booleanValue(): boolean;
begin
result := value <> 0.0;
end;
function ValueOfDouble.intValue(): int;
begin
result := doubleToInt(value);
end;
function ValueOfDouble.longValue(): long;
begin
result := doubleToLong(value);
end;
function ValueOfDouble.floatValue(): float;
begin
result := doubleToFloat(value);
end;
function ValueOfDouble.doubleValue(): double;
begin
result := value;
end;
function ValueOfDouble.realValue(): real;
begin
result := value;
end;
function ValueOfDouble.ansiStringValue(): AnsiString;
begin
result := doubleRepresenter.toString(value);
end;
function ValueOfDouble.unicodeStringValue(): UnicodeString;
begin
result := stringToUTF16(doubleRepresenter.toString(value));
end;
function ValueOfDouble.objectValue(): TObject;
begin
result := self;
end;
function ValueOfDouble.interfaceValue(): IUnknown;
begin
result := self;
end;
function ValueOfDouble.getSize(): int;
begin
result := 8;
end;
procedure ValueOfDouble.writeToByteArray(const dst: byte_Array1d; offset: int);
begin
arrayCheckBounds('ValueOfDouble.writeToByteArray', system.length(dst), offset, 8);
long((@(dst[offset]))^) := longByteSwap(doubleToLongBits(value));
end;
procedure ValueOfDouble.writeToByteArrayLE(const dst: byte_Array1d; offset: int);
begin
arrayCheckBounds('ValueOfDouble.writeToByteArrayLE', system.length(dst), offset, 8);
long((@(dst[offset]))^) := doubleToLongBits(value);
end;
{%endregion}
{%region ValueOfReal }
class function ValueOfReal.realIsEquals(const value1, value2: real): boolean;
begin
result := arrayequalsf(@value1, @value2, 1, 5) = -1;
end;
constructor ValueOfReal.create(const value: real);
begin
inherited create();
self.value := value;
end;
function ValueOfReal.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is ValueOfReal) and realIsEquals(ValueOfReal(anot).value, value);
end;
function ValueOfReal.getHashCode(): long;
begin
result := realSignificand(value) xor not realExponent(value);
end;
function ValueOfReal.toString(): AnsiString;
begin
result := realRepresenter.toString(value);
end;
function ValueOfReal.getType(): int;
begin
result := TYPE_REAL;
end;
function ValueOfReal.booleanValue(): boolean;
begin
result := value <> realBuild(0, 0);
end;
function ValueOfReal.intValue(): int;
begin
result := realToInt(value);
end;
function ValueOfReal.longValue(): long;
begin
result := realToLong(value);
end;
function ValueOfReal.floatValue(): float;
begin
result := realToFloat(value);
end;
function ValueOfReal.doubleValue(): double;
begin
result := realToDouble(value);
end;
function ValueOfReal.realValue(): real;
begin
result := value;
end;
function ValueOfReal.ansiStringValue(): AnsiString;
begin
result := realRepresenter.toString(value);
end;
function ValueOfReal.unicodeStringValue(): UnicodeString;
begin
result := stringToUTF16(realRepresenter.toString(value));
end;
function ValueOfReal.objectValue(): TObject;
begin
result := self;
end;
function ValueOfReal.interfaceValue(): IUnknown;
begin
result := self;
end;
function ValueOfReal.getSize(): int;
begin
result := 10;
end;
procedure ValueOfReal.writeToByteArray(const dst: byte_Array1d; offset: int);
var
i: int;
j: int;
begin
arrayCheckBounds('ValueOfReal.writeToByteArray', system.length(dst), offset, 10);
i := offset + 9;
j := 0;
while j < 10 do begin
dst[i] := value[j];
dec(i);
inc(j);
end;
end;
procedure ValueOfReal.writeToByteArrayLE(const dst: byte_Array1d; offset: int);
var
i: int;
j: int;
begin
arrayCheckBounds('ValueOfReal.writeToByteArrayLE', system.length(dst), offset, 10);
i := offset;
j := 0;
while j < 10 do begin
dst[i] := value[j];
inc(i);
inc(j);
end;
end;
{%endregion}
{%region ValueOfAnsiString }
constructor ValueOfAnsiString.create(const value: AnsiString);
begin
inherited create();
self.value := value;
end;
function ValueOfAnsiString.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is ValueOfAnsiString) and (ValueOfAnsiString(anot).value = value);
end;
function ValueOfAnsiString.getHashCode(): long;
var
i: int;
e: long;
c: AnsiString;
begin
result := 0;
c := value;
e := 1;
for i := length(c) - 1 downto 0 do begin
inc(result, e * int(c[i + 1]));
e := 31 * e;
end;
end;
function ValueOfAnsiString.toString(): AnsiString;
begin
result := value;
end;
function ValueOfAnsiString.getType(): int;
begin
result := TYPE_ANSISTRING;
end;
function ValueOfAnsiString.booleanValue(): boolean;
begin
result := stringToLowerCase(value) = 'true';
end;
function ValueOfAnsiString.intValue(): int;
begin
try
result := intParse(value);
except
result := 0;
end;
end;
function ValueOfAnsiString.longValue(): long;
begin
try
result := longParse(value);
except
result := 0;
end;
end;
function ValueOfAnsiString.floatValue(): float;
begin
try
result := floatParse(value);
except
result := 0.0;
end;
end;
function ValueOfAnsiString.doubleValue(): double;
begin
try
result := doubleParse(value);
except
result := 0.0;
end;
end;
function ValueOfAnsiString.realValue(): real;
begin
try
result := realParse(value);
except
result := realBuild(0, 0);
end;
end;
function ValueOfAnsiString.ansiStringValue(): AnsiString;
begin
result := value;
end;
function ValueOfAnsiString.unicodeStringValue(): UnicodeString;
begin
result := stringToUTF16(value);
end;
function ValueOfAnsiString.objectValue(): TObject;
begin
result := self;
end;
function ValueOfAnsiString.interfaceValue(): IUnknown;
begin
result := self;
end;
{%endregion}
{%region ValueOfUnicodeString }
constructor ValueOfUnicodeString.create(const value: UnicodeString);
begin
inherited create();
self.value := value;
end;
function ValueOfUnicodeString.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is ValueOfUnicodeString) and (ValueOfUnicodeString(anot).value = value);
end;
function ValueOfUnicodeString.getHashCode(): long;
var
i: int;
e: long;
c: UnicodeString;
begin
result := 0;
c := value;
e := 1;
for i := length(c) - 1 downto 0 do begin
inc(result, e * int(c[i + 1]));
e := 31 * e;
end;
end;
function ValueOfUnicodeString.toString(): AnsiString;
begin
result := stringToUTF8(value);
end;
function ValueOfUnicodeString.getType(): int;
begin
result := TYPE_UNICODESTRING;
end;
function ValueOfUnicodeString.booleanValue(): boolean;
begin
result := stringToLowerCase(value) = 'true';
end;
function ValueOfUnicodeString.intValue(): int;
begin
try
result := intParse(stringToUTF8(value));
except
result := 0;
end;
end;
function ValueOfUnicodeString.longValue(): long;
begin
try
result := longParse(stringToUTF8(value));
except
result := 0;
end;
end;
function ValueOfUnicodeString.floatValue(): float;
begin
try
result := floatParse(stringToUTF8(value));
except
result := 0.0;
end;
end;
function ValueOfUnicodeString.doubleValue(): double;
begin
try
result := doubleParse(stringToUTF8(value));
except
result := 0.0;
end;
end;
function ValueOfUnicodeString.realValue(): real;
begin
try
result := realParse(stringToUTF8(value));
except
result := realBuild(0, 0);
end;
end;
function ValueOfUnicodeString.ansiStringValue(): AnsiString;
begin
result := stringToUTF8(value);
end;
function ValueOfUnicodeString.unicodeStringValue(): UnicodeString;
begin
result := value;
end;
function ValueOfUnicodeString.objectValue(): TObject;
begin
result := self;
end;
function ValueOfUnicodeString.interfaceValue(): IUnknown;
begin
result := self;
end;
{%endregion}
{%region ValueOfObject }
constructor ValueOfObject.create(value: TObject; owned: boolean);
begin
inherited create();
self.value := value;
self.owned := owned;
end;
destructor ValueOfObject.destroy;
begin
if owned then value.free();
value := nil;
inherited destroy;
end;
function ValueOfObject.equals(anot: TObject): boolean;
var
lValue: TObject;
begin
lValue := self.value;
result := (anot = self) or (anot is ValueOfObject) and ((lValue = nil) and (ValueOfObject(anot).value = nil) or (lValue <> nil) and (lValue.equals(ValueOfObject(anot).value)));
end;
function ValueOfObject.getHashCode(): long;
var
lValue: TObject;
begin
lValue := self.value;
if lValue = nil then begin
result := 0;
exit;
end;
result := lValue.getHashCode();
end;
function ValueOfObject.toString(): AnsiString;
var
lValue: TObject;
begin
lValue := self.value;
if lValue = nil then begin
result := 'null';
exit;
end;
result := lValue.toString();
end;
function ValueOfObject.getType(): int;
begin
result := TYPE_CLASS;
end;
function ValueOfObject.booleanValue(): boolean;
begin
result := false;
end;
function ValueOfObject.intValue(): int;
begin
result := 0;
end;
function ValueOfObject.longValue(): long;
begin
result := 0;
end;
function ValueOfObject.floatValue(): float;
begin
result := 0.0;
end;
function ValueOfObject.doubleValue(): double;
begin
result := 0.0;
end;
function ValueOfObject.realValue(): real;
begin
result := realBuild(0, 0);
end;
function ValueOfObject.ansiStringValue(): AnsiString;
begin
result := '';
end;
function ValueOfObject.unicodeStringValue(): UnicodeString;
begin
result := '';
end;
function ValueOfObject.objectValue(): TObject;
begin
result := value;
end;
function ValueOfObject.interfaceValue(): IUnknown;
var
ival: IUnknown;
oval: TObject;
begin
ival := nil;
oval := value;
if oval <> nil then begin
oval.getInterface(IUnknown, ival);
end;
result := ival;
end;
{%endregion}
{%region ValueOfInterface }
constructor ValueOfInterface.create(value: IUnknown);
begin
inherited create();
self.value := value as IUnknown;
end;
function ValueOfInterface.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is ValueOfInterface) and (ValueOfInterface(anot).value = value);
end;
function ValueOfInterface.getHashCode(): long;
begin
result := long(value);
end;
function ValueOfInterface.toString(): AnsiString;
var
lValue: IUnknown;
begin
lValue := self.value;
if lValue = nil then begin
result := 'null';
exit;
end;
result := classForName('system.IUnknown').getCanonicalName() + '@' + longToHexString(long(lValue));
end;
function ValueOfInterface.getType(): int;
begin
result := TYPE_INTERFACE;
end;
function ValueOfInterface.booleanValue(): boolean;
begin
result := false;
end;
function ValueOfInterface.intValue(): int;
begin
result := 0;
end;
function ValueOfInterface.longValue(): long;
begin
result := 0;
end;
function ValueOfInterface.floatValue(): float;
begin
result := 0.0;
end;
function ValueOfInterface.doubleValue(): double;
begin
result := 0.0;
end;
function ValueOfInterface.realValue(): real;
begin
result := realBuild(0, 0);
end;
function ValueOfInterface.ansiStringValue(): AnsiString;
begin
result := '';
end;
function ValueOfInterface.unicodeStringValue(): UnicodeString;
begin
result := '';
end;
function ValueOfInterface.objectValue(): TObject;
var
ival: IUnknown;
oval: TObject;
begin
ival := value;
oval := nil;
if ival is TObject then begin
oval := ival as TObject;
end;
result := oval;
end;
function ValueOfInterface.interfaceValue(): IUnknown;
begin
result := value;
end;
{%endregion}
{%region RealValueRepresenter }
class function RealValueRepresenter.pow10(const value: real; power: int): real;
begin
if power = INT_MIN_VALUE then begin
result := value * realBuild(0, 0);
exit;
end;
if power > 0 then begin
if power >= $2000 then begin
result := value * tab_04_00(power) * tab_08_05(power) * tab_12_09(power) * REAL_POSITIVE_INFINITY;
exit;
end;
result := value * tab_04_00(power) * tab_08_05(power) * tab_12_09(power);
exit;
end;
if power < 0 then begin
power := -power;
if power >= $2000 then begin
result := value / tab_04_00(power) / tab_08_05(power) / tab_12_09(power) * realBuild(0, 0);
exit;
end;
result := value / tab_04_00(power) / tab_08_05(power) / tab_12_09(power);
exit;
end;
result := value;
end;
class function RealValueRepresenter.tab_04_00(power: int): real;
begin
case power and $1f of
0: result := realBuild($3fff, $8000000000000000); { 1.e+0000 }
1: result := realBuild($4002, $a000000000000000); { 1.e+0001 }
2: result := realBuild($4005, $c800000000000000); { 1.e+0002 }
3: result := realBuild($4008, $fa00000000000000); { 1.e+0003 }
4: result := realBuild($400c, $9c40000000000000); { 1.e+0004 }
5: result := realBuild($400f, $c350000000000000); { 1.e+0005 }
6: result := realBuild($4012, $f424000000000000); { 1.e+0006 }
7: result := realBuild($4016, $9896800000000000); { 1.e+0007 }
8: result := realBuild($4019, $bebc200000000000); { 1.e+0008 }
9: result := realBuild($401c, $ee6b280000000000); { 1.e+0009 }
10: result := realBuild($4020, $9502f90000000000); { 1.e+0010 }
11: result := realBuild($4023, $ba43b74000000000); { 1.e+0011 }
12: result := realBuild($4026, $e8d4a51000000000); { 1.e+0012 }
13: result := realBuild($402a, $9184e72a00000000); { 1.e+0013 }
14: result := realBuild($402d, $b5e620f480000000); { 1.e+0014 }
15: result := realBuild($4030, $e35fa931a0000000); { 1.e+0015 }
16: result := realBuild($4034, $8e1bc9bf04000000); { 1.e+0016 }
17: result := realBuild($4037, $b1a2bc2ec5000000); { 1.e+0017 }
18: result := realBuild($403a, $de0b6b3a76400000); { 1.e+0018 }
19: result := realBuild($403e, $8ac7230489e80000); { 1.e+0019 }
20: result := realBuild($4041, $ad78ebc5ac620000); { 1.e+0020 }
21: result := realBuild($4044, $d8d726b7177a8000); { 1.e+0021 }
22: result := realBuild($4048, $878678326eac9000); { 1.e+0022 }
23: result := realBuild($404b, $a968163f0a57b400); { 1.e+0023 }
24: result := realBuild($404e, $d3c21bcecceda100); { 1.e+0024 }
25: result := realBuild($4052, $84595161401484a0); { 1.e+0025 }
26: result := realBuild($4055, $a56fa5b99019a5c8); { 1.e+0026 }
27: result := realBuild($4058, $cecb8f27f4200f3a); { 1.e+0027 }
28: result := realBuild($405c, $813f3978f8940984); { 1.e+0028 }
29: result := realBuild($405f, $a18f07d736b90be5); { 1.e+0029 }
30: result := realBuild($4062, $c9f2c9cd04674edf); { 1.e+0030 }
31: result := realBuild($4065, $fc6f7c4045812296); { 1.e+0031 }
else result := realBuild($0000, $0000000000000000); { 0.0 }
end;
end;
class function RealValueRepresenter.tab_08_05(power: int): real;
begin
case (power shr 5) and $0f of
0: result := realBuild($3fff, $8000000000000000); { 1.e+0000 }
1: result := realBuild($4069, $9dc5ada82b70b59e); { 1.e+0032 }
2: result := realBuild($40d3, $c2781f49ffcfa6d5); { 1.e+0064 }
3: result := realBuild($413d, $efb3ab16c59b14a3); { 1.e+0096 }
4: result := realBuild($41a8, $93ba47c980e98ce0); { 1.e+0128 }
5: result := realBuild($4212, $b616a12b7fe617aa); { 1.e+0160 }
6: result := realBuild($427c, $e070f78d3927556b); { 1.e+0192 }
7: result := realBuild($42e7, $8a5296ffe33cc930); { 1.e+0224 }
8: result := realBuild($4351, $aa7eebfb9df9de8e); { 1.e+0256 }
9: result := realBuild($43bb, $d226fc195c6a2f8c); { 1.e+0288 }
10: result := realBuild($4426, $81842f29f2cce376); { 1.e+0320 }
11: result := realBuild($4490, $9fa42700db900ad2); { 1.e+0352 }
12: result := realBuild($44fa, $c4c5e310aef8aa17); { 1.e+0384 }
13: result := realBuild($4564, $f28a9c07e9b09c59); { 1.e+0416 }
14: result := realBuild($45cf, $957a4ae1ebf7f3d4); { 1.e+0448 }
15: result := realBuild($4639, $b83ed8dc0795a262); { 1.e+0480 }
else result := realBuild($0000, $0000000000000000); { 0.0 }
end;
end;
class function RealValueRepresenter.tab_12_09(power: int): real;
begin
case (power shr 9) and $0f of
0: result := realBuild($3fff, $8000000000000000); { 1.e+0000 }
1: result := realBuild($46a3, $e319a0aea60e91c7); { 1.e+0512 }
2: result := realBuild($4d48, $c976758681750c17); { 1.e+1024 }
3: result := realBuild($53ed, $b2b8353b3993a7e4); { 1.e+1536 }
4: result := realBuild($5a92, $9e8b3b5dc53d5de5); { 1.e+2048 }
5: result := realBuild($6137, $8ca554c020a1f0a6); { 1.e+2560 }
6: result := realBuild($67db, $f9895d25d88b5a8b); { 1.e+3072 }
7: result := realBuild($6e80, $dd5dc8a2bf27f3f8); { 1.e+3584 }
8: result := realBuild($7525, $c46052028a20979b); { 1.e+4096 }
9: result := realBuild($7bca, $ae3511626ed559f0); { 1.e+4608 }
else result := REAL_POSITIVE_INFINITY;
end;
end;
constructor RealValueRepresenter.create(significandDigits, orderDigits: int; orderRequired: boolean);
var
i: int;
maxValue: long;
begin
inherited create();
if significandDigits < MIN_SIGNIFICAND_DIGITS then significandDigits := MIN_SIGNIFICAND_DIGITS;
if significandDigits > MAX_SIGNIFICAND_DIGITS then significandDigits := MAX_SIGNIFICAND_DIGITS;
if orderDigits < MIN_ORDER_DIGITS then orderDigits := MIN_ORDER_DIGITS;
if orderDigits > MAX_ORDER_DIGITS then orderDigits := MAX_ORDER_DIGITS;
maxValue := 1;
for i := significandDigits downto 1 do maxValue := maxValue * 10;
self.limitValueWithFractialPart := pow10(1.0, significandDigits - 1);
self.limitValueWithoutExponent := pow10(1.0, significandDigits);
self.minRepresentValue := maxValue div 10;
self.maxRepresentValue := maxValue - 1;
self.significandDigits := significandDigits;
self.orderDigits := orderDigits;
self.orderRequired := orderRequired;
end;
function RealValueRepresenter.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is RealValueRepresenter) and (RealValueRepresenter(anot).orderDigits = orderDigits) and (RealValueRepresenter(anot).significandDigits = significandDigits);
end;
function RealValueRepresenter.getHashCode(): long;
begin
result := (orderDigits shl 8) or significandDigits;
end;
function RealValueRepresenter.parseReal(const str: AnsiString): real;
begin
if (str = '+Infinity') or (str = 'Infinity') then begin
result := REAL_POSITIVE_INFINITY;
exit;
end;
if str = '-Infinity' then begin
result := REAL_NEGATIVE_INFINITY;
exit;
end;
if str = 'NaN' then begin
result := REAL_NAN;
exit;
end;
result := parse(str);
if (result < -REAL_MAX_VALUE) or (result > REAL_MAX_VALUE) then begin
raise NumberFormatException.create('RealValueRepresenter.parse: ' + msgIllegalNumberFormat);
end;
end;
function RealValueRepresenter.parseFloat(const str: AnsiString): float;
var
value: real;
begin
if (str = '+Infinity') or (str = 'Infinity') then begin
result := FLOAT_POSITIVE_INFINITY;
exit;
end;
if str = '-Infinity' then begin
result := FLOAT_NEGATIVE_INFINITY;
exit;
end;
if str = 'NaN' then begin
result := FLOAT_NAN;
exit;
end;
value := parse(str);
if (value < -FLOAT_MAX_VALUE) or (value > FLOAT_MAX_VALUE) then begin
raise NumberFormatException.create('RealValueRepresenter.parse: ' + msgIllegalNumberFormat);
end;
result := realToFloat(value);
end;
function RealValueRepresenter.parseDouble(const str: AnsiString): double;
var
value: real;
begin
if (str = '+Infinity') or (str = 'Infinity') then begin
result := DOUBLE_POSITIVE_INFINITY;
exit;
end;
if str = '-Infinity' then begin
result := DOUBLE_NEGATIVE_INFINITY;
exit;
end;
if str = 'NaN' then begin
result := DOUBLE_NAN;
exit;
end;
value := parse(str);
if (value < -DOUBLE_MAX_VALUE) or (value > DOUBLE_MAX_VALUE) then begin
raise NumberFormatException.create('RealValueRepresenter.parse: ' + msgIllegalNumberFormat);
end;
result := realToDouble(value);
end;
function RealValueRepresenter.getOrderDigits(): int;
begin
result := orderDigits;
end;
function RealValueRepresenter.getSignificandDigits(): int;
begin
result := significandDigits;
end;
function RealValueRepresenter.toString(const value: real): AnsiString;
var
expform: boolean;
c: char;
i: int;
j: int;
len: int;
order: int;
orddig: int;
sigdig: int;
dotpos: int;
tmp: long;
intval: long;
lvalue: real;
minvalue: real;
buf: char_Array1d;
begin
if realIsNaN(value) then begin
result := 'NaN';
exit;
end;
if value = REAL_POSITIVE_INFINITY then begin
result := 'Infinity';
exit;
end;
if value = REAL_NEGATIVE_INFINITY then begin
result := '-Infinity';
exit;
end;
buf := stringToCharArray('00000000000000000000000000000000');
len := 0;
order := realExponent(value);
tmp := realSignificand(value);
if order < 0 then begin
buf[len] := '-';
inc(len);
lvalue := -value;
end else begin
lvalue := value;
end;
if (tmp <> 0) or (order <> +$0000) and (order <> -$8000) then begin
order := realToInt(realBuild($3ffd, $9a209a84fbcff798) { 3.01029995663981195214e-0001 } * log2(lvalue));
sigdig := self.significandDigits;
if sigdig < 6 then begin
minvalue := 1.0 / tab_04_00(sigdig);
end else begin
minvalue := 1.0 / tab_04_00(6);
end;
{ significandDigits }
{ limitValueWithoutExponent = 10 }
{ -significandDigits -6 }
{ minvalue = 10 , но не меньше 10 }
expform := self.orderRequired or (lvalue < minvalue) or (lvalue >= self.limitValueWithoutExponent);
if expform then begin
if lvalue < 1.0 then dec(order);
intval := round(pow10(lvalue, sigdig - order - 1));
if intval < self.minRepresentValue then begin
intval := intval * 10;
dec(order);
end;
if intval > self.maxRepresentValue then begin
intval := intval div 10;
inc(order);
end;
dotpos := len + 1;
end else
if lvalue < 1.0 then begin
{ minvalue ≤ lvalue < 1 }
intval := round(pow10(lvalue, sigdig - 1));
dotpos := len + 1;
end else
if lvalue < self.limitValueWithFractialPart then begin
{ significandDigits-1 }
{ 1 ≤ lvalue < 10 }
intval := round(pow10(lvalue, sigdig - order - 1));
if intval < self.minRepresentValue then begin
intval := intval * 10;
dec(order);
end;
if intval > self.maxRepresentValue then begin
intval := intval div 10;
inc(order);
end;
dotpos := len + order + 1;
end else begin
{ significandDigits-1 significandDigits }
{ 10 ≤ lvalue < 10 }
intval := round(lvalue);
tmp := self.maxRepresentValue;
if intval > tmp then intval := tmp;
dotpos := len + sigdig;
end;
buf[dotpos] := '.';
for i := len + sigdig - 1 downto len do begin
if i >= dotpos then begin
buf[i + 1] := char(int(intval mod 10) + int('0'));
end else begin
buf[i] := char(int(intval mod 10) + int('0'));
end;
intval := intval div 10;
end;
inc(len, sigdig + 2);
repeat
c := buf[len - 1];
if (c <> '0') and (c <> '.') then break;
dec(len);
if c = '.' then begin
inc(len, 2);
break;
end;
until false;
if expform then begin
buf[len] := 'E';
inc(len);
if order < 0 then begin
buf[len] := '-';
order := -order;
end else begin
buf[len] := '+';
end;
inc(len);
orddig := self.orderDigits;
if (orddig = 1) and (order >= 10) then begin
inc(orddig);
end;
if (orddig = 2) and (order >= 100) then begin
inc(orddig);
end;
if (orddig = 3) and (order >= 1000) then begin
inc(orddig);
end;
j := len + orddig;
for i := j - 1 downto len do begin
buf[i] := char((order mod 10) + int('0'));
order := order div 10;
end;
len := j;
end;
end else begin
inc(len, 3);
buf[len - 2] := '.';
end;
result := AnsiString_create(buf, 0, len);
end;
function RealValueRepresenter.parse(const str: AnsiString): real;
const
ULIMIT = long($1999999999999999);
var
negative: boolean;
c: char;
i: int;
len: int;
frac: int;
order: int;
digit: int;
unsres: long;
begin
len := length(str);
if len <= 0 then begin
raise NumberFormatException.create('RealValueRepresenter.parse: ' + msgIllegalNumberFormat);
end;
negative := false;
i := 0;
frac := 0;
order := 0;
unsres := 0;
case str[1] of
'-': begin
negative := true;
inc(i);
end;
'+', #$20:
inc(i);
end;
if i >= len then begin
raise NumberFormatException.create('RealValueRepresenter.parse: ' + msgIllegalNumberFormat);
end;
c := str[i + 1];
if ((c < '0') or (c > '9')) and (c <> '.') then begin
raise NumberFormatException.create('RealValueRepresenter.parse: ' + msgIllegalNumberFormat);
end;
if c <> '.' then begin
unsres := int(c) - int('0');
inc(i);
while i < len do begin
c := str[i + 1];
if (c < '0') or (c > '9') then break;
digit := int(c) - int('0');
if (unsres >= 0) and (unsres < ULIMIT) or (unsres = ULIMIT) and (digit < 6) then begin
unsres := 10 * unsres + digit;
end else begin
dec(frac);
end;
inc(i);
end;
end;
if (i < len) and (str[i + 1] = '.') then begin
inc(i);
while i < len do begin
c := str[i + 1];
if (c < '0') or (c > '9') then break;
digit := int(c) - int('0');
if (unsres >= 0) and (unsres < ULIMIT) or (unsres = ULIMIT) and (digit < 6) then begin
unsres := 10 * unsres + digit;
inc(frac);
end;
inc(i);
end;
end;
if unsres <> 0 then begin
while (frac > 0) and (ulongRem(unsres, 10) = 0) do begin
unsres := ulongDiv(unsres, 10);
dec(frac);
end;
end;
if negative then begin
negative := false;
result := -ulongToReal(unsres);
end else begin
result := ulongToReal(unsres);
end;
if i < len then begin
c := str[i + 1];
if (c = 'E') or (c = 'e') then begin
inc(i);
if i >= len then begin
raise NumberFormatException.create('RealValueRepresenter.parse: ' + msgIllegalNumberFormat);
end;
case str[i + 1] of
'-': begin
negative := true;
inc(i);
end;
'+':
inc(i);
end;
if i >= len then begin
raise NumberFormatException.create('RealValueRepresenter.parse: ' + msgIllegalNumberFormat);
end;
repeat
c := str[i + 1];
if (c < '0') or (c > '9') then break;
order := order * 10 + int(c) - int('0');
if order > 9999 then begin
raise NumberFormatException.create('RealValueRepresenter.parse: ' + msgIllegalNumberFormat);
end;
inc(i);
until i >= len;
if negative then begin
order := -order;
end;
end;
end;
if i < len then begin
raise NumberFormatException.create('RealValueRepresenter.parse: ' + msgIllegalNumberFormat);
end;
dec(order, frac);
while order >= 4932 do begin
result := pow10(result, 4932);
dec(order, 4932);
end;
while order <= -4931 do begin
result := pow10(result, -4931);
dec(order, -4931);
end;
result := pow10(result, order);
end;
{%endregion}
{%region Task }
constructor Task.create();
begin
inherited create();
self.scheduledTime := LONG_MIN_VALUE;
end;
destructor Task.destroy;
begin
system.enterCriticalSection(schedulerInstance.fSynchronize);
try
schedulerInstance.cancel(self);
finally
system.leaveCriticalSection(schedulerInstance.fSynchronize);
end;
inherited destroy;
end;
function Task.getScheduledTime(): long;
begin
result := scheduledTime;
end;
procedure Task.cancel();
var
succes: boolean;
begin
system.enterCriticalSection(schedulerInstance.fSynchronize);
try
succes := schedulerInstance.cancel(self);
finally
system.leaveCriticalSection(schedulerInstance.fSynchronize);
end;
if succes then Thread.queue(nil, @self.cancelled);
end;
procedure Task.schedule(delay: int);
begin
if delay <= 0 then begin
raise IllegalArgumentException.create('Task.schedule: ' + msgIllegalArgument + 'delay');
end;
system.enterCriticalSection(schedulerInstance.fSynchronize);
try
if schedulerInstance.indexOf(self) < 0 then begin
self.periodic := false;
self.runningTime := long(Thread.getTickCount64()) + long(delay);
schedulerInstance.push(self);
end;
finally
system.leaveCriticalSection(schedulerInstance.fSynchronize);
end;
end;
procedure Task.schedule(delay, period: int);
begin
if delay <= 0 then begin
raise IllegalArgumentException.create('Task.schedule: ' + msgIllegalArgument + 'delay');
end;
if period <= 0 then begin
raise IllegalArgumentException.create('Task.schedule: ' + msgIllegalArgument + 'period');
end;
system.enterCriticalSection(schedulerInstance.fSynchronize);
try
if schedulerInstance.indexOf(self) < 0 then begin
self.periodic := true;
self.period := period;
self.runningTime := long(Thread.getTickCount64()) + long(delay);
schedulerInstance.push(self);
end;
finally
system.leaveCriticalSection(schedulerInstance.fSynchronize);
end;
end;
procedure Task.cancelled();
begin
end;
{%endregion}
{%region Thread }
class function Thread.nextThreadNumber(): int;
begin
result := interlockedIncrement(@threadNumber);
end;
constructor Thread.create();
begin
create(nil, '');
end;
constructor Thread.create(const name: AnsiString);
begin
create(nil, name);
end;
constructor Thread.create(target: Runnable);
begin
create(target, '');
end;
constructor Thread.create(target: Runnable; const name: AnsiString);
var
thrdName: AnsiString;
begin
inherited create(true);
freeOnTerminate := true;
if length(name) = 0 then begin
thrdName := 'Thread ' + intToString(nextThreadNumber());
end else begin
thrdName := name;
end;
self.fTarget := target;
self.fName := thrdName;
end;
function Thread.toString(): AnsiString;
begin
result := 'thread ' + fName;
end;
function Thread.queryInterface({$IFDEF FPC_HAS_CONSTREF} constref {$ELSE} const {$ENDIF} iid: TGuid; out obj): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF};
begin
if getInterface(iid, obj) then begin
result := S_OK;
end else begin
result := E_NOINTERFACE;
end;
end;
function Thread._addref(): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF};
begin
result := -1;
end;
function Thread._release(): int; {$IFNDEF WINDOWS} cdecl {$ELSE} stdcall {$ENDIF};
begin
result := -1;
end;
function Thread.getName(): AnsiString;
begin
result := fName;
end;
procedure Thread.run();
begin
end;
procedure Thread.execute();
var
lTarget: Runnable;
begin
fxcontextLoadFrom(@defaultContext);
lTarget := self.fTarget;
if lTarget <> nil then begin
lTarget.run();
exit;
end;
run();
end;
{%endregion}
{%region Monitor.ThreadEntry }
constructor Monitor.ThreadEntry.create(owner: Monitor; monitorThread: TThread; state: int);
begin
inherited create();
self.fState := state;
self.fEntryCount := 1;
self.fMonitorEvent := rtlEventCreate();
self.fMonitorThread := monitorThread;
self.fOwner := owner;
end;
destructor Monitor.ThreadEntry.destroy;
begin
rtlEventDestroy(fMonitorEvent);
fSuspendTask.free();
inherited destroy;
end;
procedure Monitor.ThreadEntry.suspend();
var
event: PRTLEvent;
begin
event := fMonitorEvent;
repeat
rtlEventWaitFor(event);
until fState = RUNNING;
end;
procedure Monitor.ThreadEntry.resume();
begin
fState := RUNNING;
rtlEventSetEvent(fMonitorEvent);
end;
{%endregion}
{%region Monitor.SuspendTask }
constructor Monitor.SuspendTask.create(owner: Monitor; entry: ThreadEntry);
begin
inherited create();
self.fEntry := entry;
self.fOwner := owner;
end;
procedure Monitor.SuspendTask.run();
var
lOwner: Monitor;
lEntry: ThreadEntry;
begin
lOwner := self.fOwner;
lEntry := self.fEntry;
system.enterCriticalSection(lOwner.fMonitorSynchronize);
try
lEntry.fState := SUSPENDED;
lEntry.fSuspendTask := nil;
if lOwner.fOwningEntry = nil then begin
lOwner.pop();
end;
finally
system.leaveCriticalSection(lOwner.fMonitorSynchronize);
end;
free();
end;
{%endregion}
{%region Monitor }
procedure Monitor.afterConstruction();
begin
self.fWaitingEntries := ThreadEntry_Array1d(TObject_Array1d_create(7));
system.initCriticalSection(self.fMonitorSynchronize);
end;
procedure Monitor.beforeDestruction();
var
needRaise: boolean;
begin
system.enterCriticalSection(fMonitorSynchronize);
try
needRaise := (fWaitingCount > 0) or (fOwningEntry <> nil);
finally
system.leaveCriticalSection(fMonitorSynchronize);
end;
if needRaise then begin
raise IllegalMonitorStateException.create(msgIllegalMonitorState);
end;
system.doneCriticalSection(fMonitorSynchronize);
end;
procedure Monitor.notify();
label
label0;
var
needRaise: boolean;
i: int;
currentEntry: ThreadEntry;
lOwningEntry: ThreadEntry;
lWaitingEntries: ThreadEntry_Array1d;
begin
if self = nil then begin
raise NullPointerException.create(msgNullPointer);
end;
needRaise := false;
system.enterCriticalSection(fMonitorSynchronize);
try
lOwningEntry := self.fOwningEntry;
if (lOwningEntry = nil) or (lOwningEntry.fMonitorThread <> Thread.currentThread) then begin
needRaise := true;
end else begin
lWaitingEntries := self.fWaitingEntries;
for i := 0 to fWaitingCount - 1 do begin
currentEntry := lWaitingEntries[i];
if currentEntry.fState <> WAITING then continue;
currentEntry.fState := SUSPENDED;
currentEntry.fSuspendTask.free();
currentEntry.fSuspendTask := nil;
goto label0;
end;
inc(fNotifiesCount);
end;
label0:
finally
system.leaveCriticalSection(fMonitorSynchronize);
end;
if needRaise then begin
raise IllegalMonitorStateException.create('Monitor.notify: ' + msgIllegalMonitorState);
end;
end;
procedure Monitor.notifyAll();
var
needRaise: boolean;
notifying: boolean;
i: int;
currentEntry: ThreadEntry;
lOwningEntry: ThreadEntry;
lWaitingEntries: ThreadEntry_Array1d;
begin
if self = nil then begin
raise NullPointerException.create(msgNullPointer);
end;
needRaise := false;
system.enterCriticalSection(fMonitorSynchronize);
try
lOwningEntry := self.fOwningEntry;
if (lOwningEntry = nil) or (lOwningEntry.fMonitorThread <> Thread.currentThread) then begin
needRaise := true;
end else begin
notifying := false;
lWaitingEntries := self.fWaitingEntries;
for i := 0 to fWaitingCount - 1 do begin
currentEntry := lWaitingEntries[i];
if currentEntry.fState <> WAITING then continue;
currentEntry.fState := SUSPENDED;
currentEntry.fSuspendTask.free();
currentEntry.fSuspendTask := nil;
notifying := true;
end;
if not notifying then begin
inc(fNotifiesCount);
end;
end;
finally
system.leaveCriticalSection(fMonitorSynchronize);
end;
if needRaise then begin
raise IllegalMonitorStateException.create('Monitor.notifyAll: ' + msgIllegalMonitorState);
end;
end;
procedure Monitor.wait(millis: int);
var
needRaise: boolean;
needSuspend: boolean;
lNotifiesCount: long;
lOwningEntry: ThreadEntry;
lSuspendTask: Task;
begin
if self = nil then begin
raise NullPointerException.create(msgNullPointer);
end;
needRaise := false;
needSuspend := false;
system.enterCriticalSection(fMonitorSynchronize);
try
lOwningEntry := self.fOwningEntry;
lNotifiesCount := self.fNotifiesCount;
if (lOwningEntry = nil) or (lOwningEntry.fMonitorThread <> Thread.currentThread) then begin
needRaise := true;
end else
if lNotifiesCount <> 0 then begin
self.fNotifiesCount := lNotifiesCount - 1;
end else begin
needSuspend := true;
if millis > 0 then begin
lSuspendTask := SuspendTask.create(self, lOwningEntry);
lSuspendTask.schedule(millis);
lOwningEntry.fSuspendTask := lSuspendTask;
end;
lOwningEntry.fState := WAITING;
self.fOwningEntry := nil;
pop();
push(lOwningEntry);
end;
finally
system.leaveCriticalSection(fMonitorSynchronize);
end;
if needRaise then begin
raise IllegalMonitorStateException.create('Monitor.wait: ' + msgIllegalMonitorState);
end;
if needSuspend then begin
lOwningEntry.suspend();
end;
end;
procedure Monitor.push(entry: ThreadEntry);
var
count: int;
entries: ThreadEntry_Array1d;
newentries: ThreadEntry_Array1d;
begin
count := fWaitingCount;
entries := fWaitingEntries;
if count = length(entries) then begin
newentries := ThreadEntry_Array1d(TObject_Array1d_create((count shl 1) + 1));
arraycopyObjects(entries, 0, newentries, 0, count);
fWaitingEntries := newentries;
entries := newentries;
end;
entries[count] := entry;
fWaitingCount := count + 1;
end;
procedure Monitor.pop();
label
label0;
var
i: int;
index: int;
count: int;
lOwningEntry: ThreadEntry;
lWaitingEntries: ThreadEntry_Array1d;
begin
index := -1;
count := self.fWaitingCount;
lWaitingEntries := self.fWaitingEntries;
begin
for i := 0 to count - 1 do begin
if lWaitingEntries[i].fState = SUSPENDED then begin
index := i;
goto label0;
end;
end;
exit;
end;
label0:
lOwningEntry := lWaitingEntries[index];
if index < count - 1 then begin
arraycopyObjects(lWaitingEntries, index + 1, lWaitingEntries, index, count - index - 1);
end;
dec(count);
lWaitingEntries[count] := nil;
self.fWaitingCount := count;
self.fOwningEntry := lOwningEntry;
lOwningEntry.resume();
end;
{%endregion}
{%region Throwable }
constructor Throwable.create(const message: AnsiString; helpContext: int);
begin
inherited create();
self.fMessage := message;
self.fHelpContext := helpContext;
end;
function Throwable.toString(): AnsiString;
var
lMessage: AnsiString;
begin
lMessage := self.fMessage;
if length(lMessage) > 0 then begin
result := getClass().getCanonicalName() + ': ' + lMessage;
end else begin
result := getClass().getCanonicalName();
end;
end;
procedure Throwable.printStackTrace();
begin
if isConsole then begin
writeln(toString() + LINE_ENDING);
end;
end;
{%endregion}
{%region MemoryError }
procedure MemoryError.freeInstance();
begin
if not disallowFree then begin
inherited freeInstance();
end;
end;
{%endregion}
{%region Scheduler }
constructor Scheduler.create();
begin
inherited create();
self.fQueue := Task_Array1d(TObject_Array1d_create($1f));
self.fTimer := THandle(-1);
system.initCriticalSection(self.fSynchronize);
end;
destructor Scheduler.destroy;
begin
system.doneCriticalSection(fSynchronize);
freeTimer();
inherited destroy;
end;
function Scheduler.indexOf(t: Task): int;
begin
result := arrayfindeqfObject(fQueue, 0, fCount, t);
end;
function Scheduler.cancel(t: Task): boolean;
var
index: int;
lCount: int;
lQueue: Task_Array1d;
begin
index := indexOf(t);
if index < 0 then begin
result := false;
exit;
end;
lCount := self.fCount;
lQueue := self.fQueue;
if index < lCount - 1 then begin
arraycopyObjects(lQueue, index + 1, lQueue, index, lCount - index - 1);
end;
dec(lCount);
self.fCount := lCount;
lQueue[lCount] := nil;
if index = lCount then updateTimer();
result := true;
end;
function Scheduler.pop(): Task;
var
remainingTime: long;
lCount: int;
lQueue: Task_Array1d;
begin
lCount := self.fCount;
lQueue := self.fQueue;
if lCount <= 0 then begin
result := nil;
exit;
end;
dec(lCount);
result := lQueue[lCount];
remainingTime := result.runningTime - long(Thread.getTickCount64());
if remainingTime > 0 then begin
freeTimer();
fTimer := widgetSet.createTimer(int(remainingTime), @self.run);
result := nil;
exit;
end;
self.fCount := lCount;
lQueue[lCount] := nil;
updateTimer();
end;
procedure Scheduler.push(t: Task);
var
runningTime: long;
i: int;
index: int;
lCount: int;
lQueue: Task_Array1d;
newQueue: Task_Array1d;
begin
lCount := self.fCount;
lQueue := self.fQueue;
if lCount = length(lQueue) then begin
newQueue := Task_Array1d(TObject_Array1d_create((lCount shl 1) + 1));
arraycopyObjects(lQueue, 0, newQueue, 0, lCount);
self.fQueue := newQueue;
lQueue := newQueue;
end;
runningTime := t.runningTime;
index := lCount;
i := 0;
while i < index do begin
if lQueue[i].runningTime <= runningTime then begin
index := i;
arraycopyObjects(lQueue, index, lQueue, index + 1, lCount - index);
break;
end;
inc(i);
end;
inc(lCount);
self.fCount := lCount;
lQueue[index] := t;
if index = lCount - 1 then updateTimer();
end;
procedure Scheduler.updateTimer();
var
remainingTime: long;
lCount: int;
begin
freeTimer();
lCount := self.fCount;
if lCount <= 0 then exit;
remainingTime := fQueue[lCount - 1].runningTime - long(Thread.getTickCount64());
if remainingTime <= 0 then remainingTime := 1;
fTimer := widgetSet.createTimer(int(remainingTime), @self.run);
end;
procedure Scheduler.freeTimer();
var
lTimer: THandle;
begin
lTimer := self.fTimer;
if lTimer <> THandle(-1) then begin
widgetSet.destroyTimer(lTimer);
self.fTimer := THandle(-1);
end;
end;
procedure Scheduler.run();
var
tsk: Task;
begin
system.enterCriticalSection(fSynchronize);
try
tsk := pop();
if tsk <> nil then begin
tsk.scheduledTime := tsk.runningTime;
if tsk.periodic then begin
tsk.runningTime := long(Thread.getTickCount64()) + long(tsk.period);
push(tsk);
end;
end;
finally
system.leaveCriticalSection(fSynchronize);
end;
if tsk <> nil then tsk.run();
end;
{%endregion}
{%region Information }
function Information.isPrimitive(): boolean;
begin
result := false;
end;
function Information.isInstance(ref: TObject): boolean;
begin
result := not isPrimitive() and (ref <> nil) and isAssignableFrom(ref.getClass());
end;
function Information.isAssignableFrom(cls: _Class): boolean;
var
info: Information;
begin
if cls = nil then begin
raise NullPointerException.create('_Class.isAssignableFrom: ' + msgNullPointerArgument + 'cls');
end;
if not(cls is Information) then begin
raise IllegalArgumentException.create('_Class.isAssignableFrom: ' + msgIllegalArgument + 'cls');
end;
info := cls as Information;
if isPrimitive() then begin
result := info.getPrimitiveType() = self.getPrimitiveType();
exit;
end;
if isInterface() then begin
result := info.isInterfaceImplements(self);
exit;
end;
result := info.isInheritedFrom(self);
end;
function Information.getPrimitiveType(): int;
begin
result := -1;
end;
function Information.getProperty(const name: AnsiString): _Property;
begin
result := nil;
end;
function Information.getSuperclass(): _Class;
begin
result := nil;
end;
function Information.getInterfaces(): _Class_Array1d;
begin
result := nil;
end;
function Information.getProperties(): _Property_Array1d;
begin
result := nil;
end;
function Information.getUnitName(): AnsiString;
begin
result := '';
end;
function Information.createInstance(): DynamicalyAllocatedObject;
begin
raise UnsupportedOperationException.create('_Class.createInstance: ' + msgUnsupportedOperation);
end;
function Information.isInheritedFrom(const cls: Information): boolean;
begin
result := false;
end;
function Information.isInterfaceImplements(const cls: Information): boolean;
begin
result := false;
end;
{%endregion}
{%region PrimitiveInformation }
constructor PrimitiveInformation.create(info: int; const name: AnsiString);
var
lCustom: boolean;
lName: AnsiString;
begin
inherited create();
lCustom := false;
case info of
TYPE_BOOLEAN:
lName := 'boolean';
TYPE_CHAR:
lName := 'char';
TYPE_WCHAR:
lName := 'wchar';
TYPE_BYTE:
lName := 'byte';
TYPE_SHORT:
lName := 'short';
TYPE_INT:
lName := 'int';
TYPE_LONG:
lName := 'long';
TYPE_FLOAT:
lName := 'float';
TYPE_DOUBLE:
lName := 'double';
TYPE_UBYTE:
lName := 'ubyte';
TYPE_USHORT:
lName := 'ushort';
TYPE_UINT:
lName := 'uint';
TYPE_ULONG:
lName := 'ulong';
TYPE_ANSISTRING:
lName := 'AnsiString';
TYPE_UNICODESTRING:
lName := 'UnicodeString';
else
lName := name;
lCustom := true;
end;
self.custom := lCustom;
self.info := info;
self.name := lName;
end;
function PrimitiveInformation.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is PrimitiveInformation) and (PrimitiveInformation(anot).info = info);
end;
function PrimitiveInformation.getHashCode(): long;
begin
result := info;
end;
function PrimitiveInformation.toString(): AnsiString;
begin
if custom then begin
result := 'type ' + name;
exit;
end;
result := name;
end;
function PrimitiveInformation.isPrimitive(): boolean;
begin
result := true;
end;
function PrimitiveInformation.isInterface(): boolean;
begin
result := false;
end;
function PrimitiveInformation.getPrimitiveType(): int;
begin
result := info;
end;
function PrimitiveInformation.getCanonicalName(): AnsiString;
begin
result := name;
end;
function PrimitiveInformation.getSimpleName(): AnsiString;
begin
result := name;
end;
{%endregion}
{%region GuidInformation }
constructor GuidInformation.create(const info: TGuid);
begin
inherited create();
self.info := info;
end;
function GuidInformation.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is GuidInformation) and isEqualGuid(GuidInformation(anot).info, info);
end;
function GuidInformation.getHashCode(): long;
var
value: long2;
begin
value := long2(info);
result := value[0] xor value[1];
end;
function GuidInformation.toString(): AnsiString;
begin
result := 'interface ' + guidToString(info);
end;
function GuidInformation.isInterface(): boolean;
begin
result := true;
end;
function GuidInformation.getCanonicalName(): AnsiString;
begin
result := guidToString(info);
end;
function GuidInformation.getSimpleName(): AnsiString;
begin
result := guidToString(info);
end;
{%endregion}
{%region ClassInformation }
class function ClassInformation.typeInfoToLangType(tinfo: PTypeInfo): int;
label
label0;
var
tdata: PTypeData;
tkind: TTypeKind;
begin
tdata := getTypeData(tinfo);
tkind := tinfo^.kind;
begin
if tkind = tkInteger then begin
case tdata^.ordType of
otSByte:
result := TYPE_BYTE;
otSWord:
result := TYPE_SHORT;
otUByte:
result := TYPE_UBYTE;
otUWord:
result := TYPE_USHORT;
otULong:
result := TYPE_UINT;
else
goto label0;
end;
exit;
end;
if (tkind = tkFloat) and (tdata^.floatType = ftDouble) then begin
result := TYPE_DOUBLE;
exit;
end;
if tkind = tkInterfaceRaw then begin
result := TYPE_INTERFACE;
exit;
end;
end;
label0:
result := int(tkind);
end;
class function ClassInformation.propInfoToProperty(pinfo: PPropInfo): _Property;
var
tm: int;
r: boolean;
w: boolean;
s: boolean;
t: _Class;
n: AnsiString;
begin
tm := pinfo^.propProcs;
r := ((tm and $03) = TM_CONST) or (pinfo^.getProc <> nil);
w := pinfo^.setProc <> nil;
s := (((tm shr 4) and $03) = TM_CONST) or (pinfo^.storedProc <> nil);
t := classForType(Pointer(pinfo^.propType));
n := pinfo^.name;
result := PropertyInformation.create(r, w, s, t, n);
end;
constructor ClassInformation.create(info: TClass);
begin
inherited create();
self.info := info;
end;
function ClassInformation.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is ClassInformation) and (ClassInformation(anot).info = info);
end;
function ClassInformation.getHashCode(): long;
begin
result := long((@info)^);
end;
function ClassInformation.toString(): AnsiString;
var
cls: TClass;
begin
cls := info;
result := 'class ' + cls.unitName() + '.' + cls.className();
end;
function ClassInformation.isInterface(): boolean;
begin
result := false;
end;
function ClassInformation.getProperty(const name: AnsiString): _Property;
var
pinfo: PPropInfo;
begin
pinfo := info.getPropertyInfo(name);
if pinfo = nil then begin
result := nil;
exit;
end;
result := propInfoToProperty(pinfo);
end;
function ClassInformation.getSuperclass(): _Class;
var
parent: TClass;
begin
parent := info.classParent();
if parent = nil then begin
result := nil;
exit;
end;
result := ClassInformation.create(parent);
end;
function ClassInformation.getInterfaces(): _Class_Array1d;
var
i: int;
len: int;
gid: TGuid;
pgid: PGuid;
psid: PShortString;
table: PInterfaceTable;
begin
table := info.getInterfaceTable();
if table = nil then begin
result := nil;
exit;
end;
with table^ do begin
len := int(entryCount);
result := _Class_Array1d(IUnknown_Array1d_create(len));
for i := len - 1 downto 0 do begin
with entries[i] do begin
pgid := iid;
psid := iidstr;
end;
if pgid <> nil then begin
result[i] := classForType(pgid^);
continue;
end;
if (psid <> nil) and tryStringToGuid(psid^, gid) then begin
result[i] := classForType(gid);
continue;
end;
result[i] := InterfaceInformation.create(PTypeInfo(typeInfo(IUnknown)));
end;
end;
end;
function ClassInformation.getProperties(): _Property_Array1d;
var
i: int;
count: int;
pinfo: PPropInfo;
tinfo: PTypeInfo;
tdata: PTypeData;
begin
tinfo := PTypeInfo(info.classInfo());
if tinfo = nil then begin
result := nil;
exit;
end;
tdata := getTypeData(tinfo);
pinfo := PPropInfo(Pointer(@(tdata^.unitName[1])) + int(tdata^.unitName[0]));
count := system.PUInt16(pinfo)^;
pinfo := Pointer(pinfo) + 2;
result := _Property_Array1d(IUnknown_Array1d_create(count));
for i := 0 to count - 1 do begin
result[i] := propInfoToProperty(pinfo);
pinfo := PPropInfo(Pointer(@(pinfo^.name[1])) + int(pinfo^.name[0]));
end;
end;
function ClassInformation.getCanonicalName(): AnsiString;
var
c: TClass;
begin
c := info;
result := c.unitName() + '.' + c.className();
end;
function ClassInformation.getSimpleName(): AnsiString;
begin
result := info.className();
end;
function ClassInformation.getUnitName(): AnsiString;
begin
result := info.unitName();
end;
function ClassInformation.createInstance(): DynamicalyAllocatedObject;
type
DynamicalyAllocatedObjectClass = class of DynamicalyAllocatedObject;
var
c: TClass;
begin
c := info;
if not c.inheritsFrom(DynamicalyAllocatedObject) then begin
raise UnsupportedOperationException.create('_Class.createInstance: ' + msgUnsupportedOperation);
end;
result := DynamicalyAllocatedObjectClass(c).create();
end;
function ClassInformation.isInheritedFrom(const cls: Information): boolean;
var
c: TClass;
cid: TClass;
begin
if not(cls is ClassInformation) then begin
result := false;
exit;
end;
cid := ClassInformation(cls).info;
c := self.info;
repeat
if cid = c then begin
result := true;
exit;
end;
c := c.classParent();
until c = nil;
result := false;
end;
function ClassInformation.isInterfaceImplements(const cls: Information): boolean;
var
i: int;
c: TClass;
iid: TGuid;
gid: TGuid;
pgid: PGuid;
psid: PShortString;
table: PInterfaceTable;
begin
if cls is InterfaceInformation then begin
iid := getTypeData(InterfaceInformation(cls).info)^.iid;
end else
if cls is GuidInformation then begin
iid := GuidInformation(cls).info;
end else begin
result := false;
exit;
end;
c := self.info;
repeat
table := c.getInterfaceTable();
if table <> nil then begin
with table^ do begin
for i := int(entryCount) - 1 downto 0 do begin
with entries[i] do begin
pgid := iid;
psid := iidstr;
end;
if (pgid <> nil) and isEqualGuid(pgid^, iid) or (psid <> nil) and tryStringToGuid(psid^, gid) and isEqualGUID(gid, iid) then begin
result := true;
exit;
end;
end;
end;
end;
c := c.classParent();
until c = nil;
result := false;
end;
{%endregion}
{%region InterfaceInformation }
constructor InterfaceInformation.create(info: PTypeInfo);
begin
inherited create();
self.info := info;
end;
function InterfaceInformation.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is InterfaceInformation) and (InterfaceInformation(anot).info = info);
end;
function InterfaceInformation.getHashCode(): long;
begin
result := long((@info)^);
end;
function InterfaceInformation.toString(): AnsiString;
var
cls: PTypeInfo;
begin
cls := info;
result := 'interface ' + getTypeData(cls)^.intfUnit + '.' + cls^.name;
end;
function InterfaceInformation.isInterface(): boolean;
begin
result := true;
end;
function InterfaceInformation.getSuperclass(): _Class;
var
parent: PTypeInfo;
begin
parent := getTypeData(info)^.intfParent;
if parent = nil then begin
result := nil;
exit;
end;
result := InterfaceInformation.create(parent);
end;
function InterfaceInformation.getInterfaces(): _Class_Array1d;
var
parent: _Class;
begin
parent := getSuperclass();
if parent = nil then begin
result := nil;
exit;
end;
result := _Class_Array1d(IUnknown_Array1d_create([ parent ]));
end;
function InterfaceInformation.getCanonicalName(): AnsiString;
var
c: PTypeInfo;
begin
c := info;
result := getTypeData(c)^.intfUnit + '.' + c^.name;
end;
function InterfaceInformation.getSimpleName(): AnsiString;
begin
result := info^.name;
end;
function InterfaceInformation.getUnitName(): AnsiString;
begin
result := getTypeData(info)^.intfUnit;
end;
function InterfaceInformation.isInheritedFrom(const cls: Information): boolean;
var
c: PTypeInfo;
d: PTypeData;
iid: TGuid;
begin
if cls is InterfaceInformation then begin
iid := getTypeData(InterfaceInformation(cls).info)^.iid;
end else
if cls is GuidInformation then begin
iid := GuidInformation(cls).info;
end else begin
result := false;
exit;
end;
c := self.info;
repeat
d := getTypeData(c);
if isEqualGuid(d^.iid, iid) then begin
result := true;
exit;
end;
c := d^.intfParent;
until c = nil;
result := false;
end;
function InterfaceInformation.isInterfaceImplements(const cls: Information): boolean;
begin
result := isInheritedFrom(cls);
end;
{%endregion}
{%region PropertyInformation }
constructor PropertyInformation.create(readable, writeable, storeable: boolean; &type: _Class; const name: AnsiString);
var
lFlags: int;
begin
inherited create();
lFlags := 0;
if readable then lFlags := lFlags or $01;
if writeable then lFlags := lFlags or $02;
if storeable then lFlags := lFlags or $04;
self.flags := lFlags;
self.&type := &type;
self.name := name;
end;
function PropertyInformation.isReadable(): boolean;
begin
result := (flags and $01) <> 0;
end;
function PropertyInformation.isWriteable(): boolean;
begin
result := (flags and $02) <> 0;
end;
function PropertyInformation.isStoreable(): boolean;
begin
result := (flags and $04) <> 0;
end;
function PropertyInformation.getType(): _Class;
begin
result := &type;
end;
function PropertyInformation.getName(): AnsiString;
begin
result := name;
end;
{%endregion}
{%region TypeEnumeration }
constructor TypeEnumeration.create(info: PTypeInfo);
begin
inherited create();
self.info := info;
end;
function TypeEnumeration.hasMoreElements(): boolean;
var
k: TTypeKind;
begin
k := info^.kind;
result := (k = tkClass) or (k = tkInterface) or (k = tkInterfaceRaw);
end;
function TypeEnumeration.nextElement(): _Class;
var
i: int;
len: int;
pstrg: Pointer;
tinfo: PTypeInfo;
tdata: PTypeData;
pprop: PPropInfo;
ppcnt: system.PUInt16;
begin
tinfo := info;
tdata := getTypeData(tinfo);
case tinfo^.kind of
tkClass: begin
if int(tdata^.unitName[0]) = 0 then begin
tdata := getTypeData(PTypeInfo(nextAlignedAfter(Pointer(tdata) + $18)));
end;
ppcnt := system.PUInt16(Pointer(@(tdata^.unitName[1])) + system.UInt8(tdata^.unitName[0]));
pprop := PPropInfo(Pointer(ppcnt) + 2);
len := ppcnt^;
for i := 0 to len - 1 do begin
pprop := PPropInfo(Pointer(@(pprop^.name[1])) + system.UInt8(pprop^.name[0]));
end;
info := PTypeInfo(nextAlignedAfter(pprop));
result := ClassInformation.create(tdata^.classType);
end;
tkInterface, tkInterfaceRaw: begin
pstrg := @(tdata^.intfUnit);
len := system.UInt8(pstrg^);
info := PTypeInfo(nextAlignedAfter(pstrg + len + system.UInt8((pstrg + len + 1)^) + 2));
result := InterfaceInformation.create(tinfo);
end;
else
result := nil;
end;
end;
{%endregion}
initialization
exceptionHandlerInitialize();
default8087CW := $037f;
defaultMXCSR := $1f80;
defaultContext.fcw := $037f;
defaultContext.mxcsr := $1f80;
{$IFNDEF LIBRARY}
fxcontextLoadFrom(@defaultContext);
{$ENDIF}
typeInfosData := PTypeInfo_Array1d(Pointer_Array1d_create(31));
primitivesData := _Class_Array1d(IUnknown_Array1d_create([
PrimitiveInformation.create(TYPE_BOOLEAN) as _Class,
PrimitiveInformation.create(TYPE_CHAR) as _Class,
PrimitiveInformation.create(TYPE_WCHAR) as _Class,
PrimitiveInformation.create(TYPE_BYTE) as _Class,
PrimitiveInformation.create(TYPE_SHORT) as _Class,
PrimitiveInformation.create(TYPE_INT) as _Class,
PrimitiveInformation.create(TYPE_LONG) as _Class,
PrimitiveInformation.create(TYPE_FLOAT) as _Class,
PrimitiveInformation.create(TYPE_DOUBLE) as _Class,
PrimitiveInformation.create(TYPE_UBYTE) as _Class,
PrimitiveInformation.create(TYPE_USHORT) as _Class,
PrimitiveInformation.create(TYPE_UINT) as _Class,
PrimitiveInformation.create(TYPE_ULONG) as _Class,
PrimitiveInformation.create(TYPE_ANSISTRING) as _Class,
PrimitiveInformation.create(TYPE_UNICODESTRING) as _Class
]));
realRepresenter := RealValueRepresenter.create(REAL_SIGNIFICAND_DIGITS, REAL_ORDER_DIGITS);
floatRepresenter := RealValueRepresenter.create(FLOAT_SIGNIFICAND_DIGITS, FLOAT_ORDER_DIGITS);
doubleRepresenter := RealValueRepresenter.create(DOUBLE_SIGNIFICAND_DIGITS, DOUBLE_ORDER_DIGITS);
schedulerInstance := Scheduler.create();
classInfoAdd([
typeInfo(TObject),
typeInfo(TInterfacedObject),
typeInfo(TAggregatedObject),
typeInfo(TContainedObject),
typeInfo(IUnknown),
typeInfo(IInvokable),
typeInfo(IDispatch),
typeInfo(_Interface),
typeInfo(_Property),
typeInfo(_Class),
typeInfo(Runnable),
typeInfo(Value),
typeInfo(ValueExtended)
]);
finalization
realRepresenter.free();
floatRepresenter.free();
doubleRepresenter.free();
schedulerInstance.free();
exceptionHandlerFinalize();
end.