{
pascalx.lang — основной модуль для разработки программ и библиотек
(только для архитектуры x86-64).
Copyright © 2021, 2026 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или изменять
её на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
}
unit pascalx.lang;
{$MODE OBJFPC}
{$MODESWITCH TYPEHELPERS}
interface
{$IFNDEF CPUX86_64}
{$ERROR this unit is for x86-64 architecture only.}
{$ENDIF}
{$IFNDEF FPC_HAS_FEATURE_RTTI}
{$ERROR this unit requires RTTI support.}
{$ENDIF}
{$IFNDEF FPC_HAS_FEATURE_DYNARRAYS}
{$ERROR this unit requires dynamic array type support.}
{$ENDIF}
{$IFNDEF FPC_HAS_FEATURE_CLASSES}
{$ERROR this unit requires class type support.}
{$ENDIF}
{$IFNDEF FPC_HAS_FEATURE_ANSISTRINGS}
{$ERROR this unit requires AnsiString support.}
{$ENDIF}
{$IFNDEF FPC_HAS_FEATURE_UNICODESTRINGS}
{$ERROR this unit requires UnicodeString support.}
{$ENDIF}
{$IFNDEF FPC_HAS_FEATURE_EXCEPTIONS}
{$ERROR this unit requires exceptions support.}
{$ENDIF}
{$IFNDEF FPC_HAS_FEATURE_RESOURCES}
{$ERROR this unit requires resources support.}
{$ENDIF}
{%region} uses
{$IFDEF WINDOWS}
windows
{$ELSE}
unixtype,
baseunix,
pthreads,
cthreads
{$ENDIF},
typinfo;
{%endregion}
{$WARN 3018 OFF} { позволить конструкторы с любой видимостью }
{$TYPEINFO ON}
{$CALLING REGISTER}
const UNIT_NAME = 'pascalx.lang';
{%region} type
boolean = system.Boolean;
char = system.AnsiChar;
uchar = system.UnicodeChar;
byte = system.Int8;
short = system.Int16;
int = system.Int32;
long = system.Int64;
float = system.Single;
double = system.Double;
real = {$IFDEF WINDOWS}packed array [0..9] of system.UInt8{$ELSE}system.Extended{$ENDIF};
{$TYPEINFO OFF}
{$INTERFACES CORBA}
ISimple = interface;
RawInterface = interface;
{$INTERFACES COM}
RefCountInterface = interface;
{$INTERFACES DEFAULT}
{$TYPEINFO ON}
&Property = interface;
&Class = interface;
Runnable = interface;
Value = interface;
Serializable = interface;
&Object = class;
RefCountObject = class;
DynamicObject = class;
CoBoolean = class;
CoChar = class;
CoUChar = class;
CoByte = class;
CoShort = class;
CoInt = class;
CoLong = class;
CoFloat = class;
CoDouble = class;
CoReal = class;
CoAnsiString = class;
CoUnicodeString = class;
CoObject = class;
CoSimple = class;
CoUnknown = class;
RealRepresenter = class;
Mutex = class;
Monitor = class;
Thread = class;
Throwable = class;
Exception = class;
PropertyException = class;
PropertyNotFoundException = class;
IllegalPropertyTypeException = class;
IllegalPropertyAccessException = class;
RuntimeException = class;
ArithmeticException = class;
ClassCastException = class;
IllegalStateException = class;
IllegalMonitorStateException = class;
IllegalThreadStateException = class;
IllegalArgumentException = class;
IllegalPropertyValueException = class;
NumberFormatException = class;
IndexOutOfBoundsException = class;
ArrayIndexOutOfBoundsException = class;
StringIndexOutOfBoundsException = class;
NegativeArraySizeException = class;
NullPointerException = class;
SecurityException = class;
SafecallException = class;
UnsupportedOperationException = class;
ReadOnlyPropertyException = class;
WriteOnlyPropertyException = class;
Error = class;
ClassContentError = class;
AbstractMethodError = class;
BufferTooLargeError = class;
MachineError = class;
StackOverflowError = class;
MemoryError = class;
OutOfMemoryError = class;
InvalidPointerError = class;
AResource = class;
Lang = class;
Math = class;
&Array = class;
generic DynamicArray<ComponentType> = packed array of ComponentType;
{ boolean[] } boolean_Array1d = specialize DynamicArray<boolean>;
{ char[] } char_Array1d = specialize DynamicArray<char>;
{ uchar[] } uchar_Array1d = specialize DynamicArray<uchar>;
{ byte[] } byte_Array1d = specialize DynamicArray<byte>;
{ short[] } short_Array1d = specialize DynamicArray<short>;
{ int[] } int_Array1d = specialize DynamicArray<int>;
{ long[] } long_Array1d = specialize DynamicArray<long>;
{ float[] } float_Array1d = specialize DynamicArray<float>;
{ double[] } double_Array1d = specialize DynamicArray<double>;
{ real[] } real_Array1d = specialize DynamicArray<real>;
{ AnsiString[] } AnsiString_Array1d = specialize DynamicArray<AnsiString>;
{ UnicodeString[] } UnicodeString_Array1d = specialize DynamicArray<UnicodeString>;
{ Pointer[] } Pointer_Array1d = specialize DynamicArray<Pointer>;
{ TObject[] } TObject_Array1d = specialize DynamicArray<TObject>;
{ Thread[] } Thread_Array1d = specialize DynamicArray<Thread>;
{ ISimple[] } ISimple_Array1d = specialize DynamicArray<ISimple>;
{ IUnknown[] } IUnknown_Array1d = specialize DynamicArray<IUnknown>;
{ &Property[] } Property_Array1d = specialize DynamicArray<&Property>;
{ &Class[] } Class_Array1d = specialize DynamicArray<&Class>;
{ boolean[][] } boolean_Array2d = specialize DynamicArray<boolean_Array1d>;
{ char[][] } char_Array2d = specialize DynamicArray<char_Array1d>;
{ uchar[][] } uchar_Array2d = specialize DynamicArray<uchar_Array1d>;
{ byte[][] } byte_Array2d = specialize DynamicArray<byte_Array1d>;
{ short[][] } short_Array2d = specialize DynamicArray<short_Array1d>;
{ int[][] } int_Array2d = specialize DynamicArray<int_Array1d>;
{ long[][] } long_Array2d = specialize DynamicArray<long_Array1d>;
{ float[][] } float_Array2d = specialize DynamicArray<float_Array1d>;
{ double[][] } double_Array2d = specialize DynamicArray<double_Array1d>;
{ real[][] } real_Array2d = specialize DynamicArray<real_Array1d>;
{ AnsiString[][] } AnsiString_Array2d = specialize DynamicArray<AnsiString_Array1d>;
{ UnicodeString[][] } UnicodeString_Array2d = specialize DynamicArray<UnicodeString_Array1d>;
{ Pointer[][] } Pointer_Array2d = specialize DynamicArray<Pointer_Array1d>;
{ TObject[][] } TObject_Array2d = specialize DynamicArray<TObject_Array1d>;
{ Thread[][] } Thread_Array2d = specialize DynamicArray<Thread_Array1d>;
{ ISimple[][] } ISimple_Array2d = specialize DynamicArray<ISimple_Array1d>;
{ IUnknown[][] } IUnknown_Array2d = specialize DynamicArray<IUnknown_Array1d>;
{ &Property[][] } Property_Array2d = specialize DynamicArray<Property_Array1d>;
{ &Class[][] } Class_Array2d = specialize DynamicArray<Class_Array1d>;
{$TYPEINFO OFF}
{$INTERFACES CORBA}
ISimple = interface ['{00000000-0000-0000-C000-000000000047}']
function queryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid: system.TGuid; out obj): int; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
end;
RawInterface = interface(ISimple) ['{F5377D1E-7AF2-4BBA-822E-778B4F7D652E}']
procedure dispatch(var message);
procedure dispatchStr(var message);
procedure defaultHandler(var message);
procedure defaultHandlerStr(var message);
function getInterface(const iid: system.TGuid; out obj): boolean;
function getInterface(const iid: ShortString; out obj): boolean;
function getInterfaceWeak(const iid: system.TGuid; out obj): boolean;
function getInterfaceByStr(const iid: ShortString; out obj): boolean;
function equals(anot: TObject): boolean;
function getHashCode(): long;
function toString(): AnsiString;
function fieldAddress(const name: ShortString): Pointer;
function safeCallException(exceptObject: TObject; exceptAddress: Pointer): system.HResult;
end;
{$INTERFACES COM}
RefCountInterface = interface(IUnknown) ['{F5377D1E-7AF2-4BBA-822E-778B4F7D652F}']
procedure dispatch(var message);
procedure dispatchStr(var message);
procedure defaultHandler(var message);
procedure defaultHandlerStr(var message);
function getInterface(const iid: system.TGuid; out obj): boolean;
function getInterface(const iid: ShortString; out obj): boolean;
function getInterfaceWeak(const iid: system.TGuid; out obj): boolean;
function getInterfaceByStr(const iid: ShortString; out obj): boolean;
function equals(anot: TObject): boolean;
function getHashCode(): long;
function toString(): AnsiString;
function fieldAddress(const name: ShortString): Pointer;
function safeCallException(exceptObject: TObject; exceptAddress: Pointer): system.HResult;
end;
{$INTERFACES DEFAULT}
{$TYPEINFO ON}
&Property = interface(RefCountInterface) ['{F5377D1E-7AF2-4BBA-822E-778B4F7D6530}']
function isReadable(): boolean;
function isWriteable(): boolean;
function isStoreable(): boolean;
function getName(): AnsiString;
function getType(): &Class;
end;
&Class = interface(RefCountInterface) ['{F5377D1E-7AF2-4BBA-822E-778B4F7D6531}']
function isPointer(): boolean;
function isPrimitive(): boolean;
function isInstance(ref: TObject): boolean;
function isInstance(ref: ISimple): boolean;
function isInstance(ref: IUnknown): boolean;
function isAssignableFrom(cls: &Class): boolean;
function getTypeKind(): int;
function getUnitName(): AnsiString;
function getSimpleName(): AnsiString;
function getOriginalUnit(): AnsiString;
function getOriginalName(): AnsiString;
function getCanonicalName(): AnsiString;
function getProperties(): Property_Array1d;
function getInterfaces(): Class_Array1d;
function getProperty(const name: AnsiString): &Property;
function getSuperclass(): &Class;
function getReference(): &Class;
function getComponentType(): &Class;
function createInstance(): DynamicObject;
end;
Runnable = interface(RawInterface) ['{5BF760E3-0DD8-49EE-AEB9-F3A7978E21CD}']
procedure run();
end;
Value = interface(RefCountInterface) ['{A3919068-04E5-47B0-A10D-591E2A664127}']
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
Serializable = interface(Value) ['{A3919068-04E5-47B0-A10D-591E2A664128}']
procedure writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
function getSize(): int;
end;
{$TYPEINFO OFF}
generic Collection<ComponentType> = interface(RefCountInterface)
procedure copyInto(const dstArray; dstOffset: int = 0);
function getLength(): int;
function componentAt(index: int): ComponentType;
function toArray(): specialize DynamicArray<ComponentType>;
property length: int read getLength;
property component[index: int]: ComponentType read componentAt; default;
end;
{$TYPEINFO ON}
Thread_Collection1d = specialize Collection<Thread>;
&Object = class(TObject, ISimple, RawInterface, IUnknown, RefCountInterface)
public
constructor create();
destructor destroy; override;
procedure afterConstruction(); override;
procedure beforeDestruction(); override;
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
{$IFDEF WINDOWS}{$CALLING STDCALL}{$ELSE}{$CALLING CDECL}{$ENDIF}
function queryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid: system.TGuid; out obj): int; virtual;
function _addref(): int; virtual;
function _release(): int; virtual;
{$CALLING REGISTER}
end;
RefCountObject = class(&Object)
public
class function newInstance(): TObject; override; final;
private
fldRefCount: int;
public
procedure afterConstruction(); override;
procedure beforeDestruction(); override;
{$IFDEF WINDOWS}{$CALLING STDCALL}{$ELSE}{$CALLING CDECL}{$ENDIF}
function _addref(): int; override; final;
function _release(): int; override; final;
{$CALLING REGISTER}
end;
DynamicObject = class(RefCountObject)
public
constructor create(); virtual;
end;
CoBoolean = class sealed(RefCountObject, Serializable, Value)
private
fldValue: byte;
public
constructor create(const value: boolean);
procedure writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getSize(): int;
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
CoChar = class sealed(RefCountObject, Serializable, Value)
public const
MIN_RADIX = int(2);
MAX_RADIX = int(36);
MIN_VALUE = char(#$00);
MAX_VALUE = char(#$ff);
public
class function isDigit(character: char): boolean; static;
class function isLowerCase(character: char): boolean; static;
class function isUpperCase(character: char): boolean; static;
class function toLowerCase(character: char): char; static;
class function toUpperCase(character: char): char; static;
class function toChar(digit: int): char; static;
class function toDigit(character: char; radix: int): int; static;
private
fldValue: char;
public
constructor create(const value: char);
procedure writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getSize(): int;
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
CoUChar = class sealed(RefCountObject, Serializable, Value)
public const
MIN_RADIX = int(2);
MAX_RADIX = int(36);
MIN_VALUE = uchar(#$0000);
MAX_VALUE = uchar(#$ffff);
public
class function isDigit(character: uchar): boolean; static;
class function isLowerCase(character: uchar): boolean; static;
class function isUpperCase(character: uchar): boolean; static;
class function toLowerCase(character: uchar): uchar; static;
class function toUpperCase(character: uchar): uchar; static;
class function toChar(digit: int): uchar; static;
class function toDigit(character: uchar; radix: int): int; static;
private
fldValue: uchar;
public
constructor create(const value: uchar);
procedure writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getSize(): int;
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
CoByte = class sealed(RefCountObject, Serializable, Value)
public const
MIN_VALUE = byte(-$80);
MAX_VALUE = byte($7f);
public
class function parse(const str: AnsiString; radix: int = 10): byte; static;
class function parseUnsigned(const str: AnsiString; radix: int = 10): byte; static;
private
fldValue: byte;
public
constructor create(const value: byte);
procedure writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getSize(): int;
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
CoShort = class sealed(RefCountObject, Serializable, Value)
public const
MIN_VALUE = short(-$8000);
MAX_VALUE = short($7fff);
public
class function parse(const str: AnsiString; radix: int = 10): short; static;
class function parseUnsigned(const str: AnsiString; radix: int = 10): short; static;
class function byteSwap(value: short): short; static;
private
fldValue: short;
public
constructor create(const value: short);
procedure writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getSize(): int;
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
CoInt = class sealed(RefCountObject, Serializable, Value)
private
class function toUnsignedStringByShift(uvalue: int; shift: int): AnsiString; static;
public const
MIN_VALUE = int(-$80000000);
MAX_VALUE = int($7fffffff);
public
class function parse(const str: AnsiString; radix: int = 10): int; static;
class function parseUnsigned(const str: AnsiString; radix: int = 10): int; static;
class function byteSwap(value: int): int; static;
class function bound(value, minimum, maximum: int): int; static;
class function max(value1, value2: int): int; static;
class function min(value1, value2: int): int; static;
class function sar(value: int; bits: int): int; static;
class function rol(value: int; bits: int): int; static;
class function boundUnsigned(uvalue, uminimum, umaximum: int): int; static;
class function cmpUnsigned(uvalue1, uvalue2: int): int; static;
class function divUnsigned(uvalue1, uvalue2: int): int; static;
class function remUnsigned(uvalue1, uvalue2: int): int; static;
class function maxUnsigned(uvalue1, uvalue2: int): int; static;
class function minUnsigned(uvalue1, uvalue2: int): int; static;
class function toFloatBits(value: int): float; static;
class function toFloat(value: int): float; static;
class function toUnsignedFloat(uvalue: int): float; static;
class function toDouble(value: int): double; static;
class function toUnsignedDouble(uvalue: int): double; static;
class function toReal(value: int): real; static;
class function toUnsignedReal(uvalue: int): real; static;
class function toString(value: int; radix: int = 10): AnsiString; static;
class function toUnsignedString(uvalue: int; radix: int = 10): AnsiString; static;
class function toLeadZeroString(value: int; width: int; radix: int = 10): AnsiString; static;
class function toBinaryString(uvalue: int): AnsiString; static;
class function toOctalString(uvalue: int): AnsiString; static;
class function toHexString(uvalue: int): AnsiString; static;
private
fldValue: int;
public
constructor create(const value: int);
procedure writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getSize(): int;
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
CoLong = class sealed(RefCountObject, Serializable, Value)
private
class function toUnsignedStringByShift(uvalue: long; shift: int): AnsiString; static;
public const
MIN_VALUE = long(-$8000000000000000);
MAX_VALUE = long($7fffffffffffffff);
public
class function parse(const str: AnsiString; radix: int = 10): long; static;
class function parseUnsigned(const str: AnsiString; radix: int = 10): long; static;
class function byteSwap(value: long): long; static;
class function bound(value, minimum, maximum: long): long; static;
class function max(value1, value2: long): long; static;
class function min(value1, value2: long): long; static;
class function sar(value: long; bits: int): long; static;
class function rol(value: long; bits: int): long; static;
class function boundUnsigned(uvalue, uminimum, umaximum: long): long; static;
class function cmpUnsigned(uvalue1, uvalue2: long): int; static;
class function divUnsigned(uvalue1, uvalue2: long): long; static;
class function remUnsigned(uvalue1, uvalue2: long): long; static;
class function maxUnsigned(uvalue1, uvalue2: long): long; static;
class function minUnsigned(uvalue1, uvalue2: long): long; static;
class function toDoubleBits(value: long): double; static;
class function toFloat(value: long): float; static;
class function toUnsignedFloat(uvalue: long): float; static;
class function toDouble(value: long): double; static;
class function toUnsignedDouble(uvalue: long): double; static;
class function toReal(value: long): real; static;
class function toUnsignedReal(uvalue: long): real; static;
class function toString(value: long; radix: int = 10): AnsiString; static;
class function toUnsignedString(uvalue: long; radix: int = 10): AnsiString; static;
class function toLeadZeroString(value: long; width: int; radix: int = 10): AnsiString; static;
class function toBinaryString(uvalue: long): AnsiString; static;
class function toOctalString(uvalue: long): AnsiString; static;
class function toHexString(uvalue: long): AnsiString; static;
private
fldValue: long;
public
constructor create(const value: long);
procedure writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getSize(): int;
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
CoFloat = class sealed(RefCountObject, Serializable, Value)
public const
MIN_VALUE = float(1.40129846432481707e-45);
MAX_VALUE = float(3.40282346638528860e+38);
POSITIVE_INFINITY = float(+1.0 / 0.0);
NEGATIVE_INFINITY = float(-1.0 / 0.0);
NEGATIVE_ZERO = float(0.0 / -1.0);
NAN = float(0.0 / 0.0);
public
class function parse(const str: AnsiString): float; static;
class function isNaN(value: float): boolean; static;
class function isInfinite(value: float): boolean; static;
class function cmpl(value1, value2: float): int; static;
class function cmpg(value1, value2: float): int; static;
class function rem(value1, value2: float): float; static;
class function max(value1, value2: float): float; static;
class function min(value1, value2: float): float; static;
class function bound(value, minimum, maximum: float): float; static;
class function toIntBits(value: float): int; static;
class function toInt(value: float): int; static;
class function toUnsignedInt(value: float): int; static;
class function toLong(value: float): long; static;
class function toUnsignedLong(value: float): long; static;
class function toDouble(value: float): double; static;
class function toReal(value: float): real; static;
class function toString(value: float): AnsiString; static;
class function toString(value: float; sigDigits, ordDigits: int;
sigAll: boolean = false; ordAll: boolean = true; expForm: boolean = false;
sigSign: boolean = false; ordSign: boolean = true): AnsiString; static;
private
fldValue: float;
public
constructor create(const value: float);
procedure writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getSize(): int;
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
CoDouble = class sealed(RefCountObject, Serializable, Value)
public const
MIN_VALUE = double(4.94065645841246544e-324);
MAX_VALUE = double(1.79769313486231571e+308);
POSITIVE_INFINITY = double(+1.0 / 0.0);
NEGATIVE_INFINITY = double(-1.0 / 0.0);
NEGATIVE_ZERO = double(0.0 / -1.0);
NAN = double(0.0 / 0.0);
public
class function parse(const str: AnsiString): double; static;
class function isNaN(value: double): boolean; static;
class function isInfinite(value: double): boolean; static;
class function cmpl(value1, value2: double): int; static;
class function cmpg(value1, value2: double): int; static;
class function rem(value1, value2: double): double; static;
class function max(value1, value2: double): double; static;
class function min(value1, value2: double): double; static;
class function bound(value, minimum, maximum: double): double; static;
class function toLongBits(value: double): long; static;
class function toInt(value: double): int; static;
class function toUnsignedInt(value: double): int; static;
class function toLong(value: double): long; static;
class function toUnsignedLong(value: double): long; static;
class function toFloat(value: double): float; static;
class function toReal(value: double): real; static;
class function toString(value: double): AnsiString; static;
class function toString(value: double; sigDigits, ordDigits: int;
sigAll: boolean = false; ordAll: boolean = true; expForm: boolean = false;
sigSign: boolean = false; ordSign: boolean = true): AnsiString; static;
private
fldValue: double;
public
constructor create(const value: double);
procedure writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getSize(): int;
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
CoReal = class sealed(RefCountObject, Serializable, Value)
{$IFDEF WINDOWS}
public
class function MIN_VALUE: real; static;
class function MAX_VALUE: real; static;
class function POSITIVE_INFINITY: real; static;
class function NEGATIVE_INFINITY: real; static;
class function NEGATIVE_ZERO: real; static;
class function NAN: real; static;
{$ELSE}
public const
MIN_VALUE = real(3.6451995318824746e-4951);
MAX_VALUE = real(1.189731495357231765e+4932);
POSITIVE_INFINITY = real(+1.0 / 0.0);
NEGATIVE_INFINITY = real(-1.0 / 0.0);
NEGATIVE_ZERO = real(0.0 / -1.0);
NAN = real(0.0 / 0.0);
{$ENDIF}
public
class function parse(const str: AnsiString): real; static;
class function isNaN(value: real): boolean; static;
class function isInfinite(value: real): boolean; static;
class function cmpl(value1, value2: real): int; static;
class function cmpg(value1, value2: real): int; static;
class function rem(value1, value2: real): real; static;
class function max(value1, value2: real): real; static;
class function min(value1, value2: real): real; static;
class function bound(value, minimum, maximum: real): real; static;
class function extractExponent(const value: real): int; static;
class function extractSignificand(const value: real): long; static;
class function build(exponent: int; significand: long): real; static;
class function toInt(value: real): int; static;
class function toUnsignedInt(value: real): int; static;
class function toLong(value: real): long; static;
class function toUnsignedLong(value: real): long; static;
class function toFloat(value: real): float; static;
class function toDouble(value: real): double; static;
class function toString(value: real): AnsiString; static;
class function toString(value: real; sigDigits, ordDigits: int;
sigAll: boolean = false; ordAll: boolean = true; expForm: boolean = false;
sigSign: boolean = false; ordSign: boolean = true): AnsiString; static;
private
fldValue: real;
public
constructor create(const value: real);
procedure writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
procedure writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getSize(): int;
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
CoAnsiString = class sealed(RefCountObject, Value)
public const
LINE_ENDING = AnsiString({$IF DEFINED(WINDOWS)}#$0d#$0a{$ELSEIF DEFINED(UNIX)}#$0a{$ELSE}#$0d{$ENDIF});
private
fldHashComputed: boolean;
fldHashValue: long;
fldValue: AnsiString;
public
constructor create(const value: AnsiString);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
CoUnicodeString = class sealed(RefCountObject, Value)
public const
LINE_ENDING = UnicodeString({$IF DEFINED(WINDOWS)}#$000d#$000a{$ELSEIF DEFINED(UNIX)}#$000a{$ELSE}#$000d{$ENDIF});
private
fldHashComputed: boolean;
fldHashValue: long;
fldValue: UnicodeString;
public
constructor create(const value: UnicodeString);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
CoObject = class sealed(RefCountObject, Value)
private
fldValue: TObject;
public
constructor create(const value: TObject);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
CoSimple = class sealed(RefCountObject, Value)
private
fldValue: ISimple;
public
constructor create(const value: ISimple);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
CoUnknown = class sealed(RefCountObject, Value)
private
fldValue: IUnknown;
public
constructor create(const value: IUnknown);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function getType(): int;
function isNaN(): boolean;
function isInfinite(): boolean;
function asBoolean(): boolean;
function asInt(): int;
function asLong(): long;
function asFloat(): float;
function asDouble(): double;
function asReal(): real;
function asAnsiString(): AnsiString;
function asUnicodeString(): UnicodeString;
function asObject(): TObject;
function asSimple(): ISimple;
end;
RealRepresenter = class(&Object)
strict private const
MUL_MIN = long($0ccccccccccccccc);
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;
protected
class function round(value: real): long; static;
public const
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);
public
class function pow10(value: real; power: int): real; static;
private
fldSigAll: boolean;
fldOrdAll: boolean;
fldSigSign: boolean;
fldOrdSign: boolean;
fldExpForm: boolean;
fldSigDigits: int;
fldOrdDigits: int;
fldMinRepresentValue: long;
fldMaxRepresentValue: long;
fldLimitValueWithFractialPart: real;
fldLimitValueWithoutExponent: real;
protected
function parse(const str: AnsiString): real; virtual;
function represent(value: real): char_Array1d; virtual;
property minRepresentValue: long read fldMinRepresentValue;
property maxRepresentValue: long read fldMaxRepresentValue;
property limitValueWithFractialPart: real read fldLimitValueWithFractialPart;
property limitValueWithoutExponent: real read fldLimitValueWithoutExponent;
public
constructor create(sigDigits, ordDigits: int; sigAll: boolean = false; ordAll: boolean = true; expForm: boolean = false; sigSign: boolean = false; ordSign: boolean = true);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function writeTo(const dst: char_Array1d; offset: int; value: real): int; virtual;
function parseFloat(const str: AnsiString): float; virtual;
function parseDouble(const str: AnsiString): double; virtual;
function parseReal(const str: AnsiString): real; virtual;
function toString(value: real): AnsiString; overload; virtual;
function toCharArray(value: real): char_Array1d; virtual;
published
property orderAll: boolean read fldOrdAll;
property orderSign: boolean read fldOrdSign;
property significandAll: boolean read fldSigAll;
property significandSign: boolean read fldSigSign;
property exponentialForm: boolean read fldExpForm;
property orderDigits: int read fldOrdDigits;
property significandDigits: int read fldSigDigits;
end;
Mutex = class(&Object)
private
fldMutex: TRTLCriticalSection;
public
constructor create();
destructor destroy; override;
procedure beginSynchronized(); virtual;
procedure endSynchronized(); virtual;
function isHold(): boolean; virtual;
end;
Monitor = class(Mutex)
strict private const
OWNEDBY = long($794264656e774f07);
BLOCKED = long($64656b636f6c4207);
WAITING = long($676e697469615707);
strict private type
ThreadStateEntry = packed record
case int of
0: (
stateForDebug: String[7];
);
1: (
state: long;
threadId: long;
lockCount: long;
__reserved18: long;
);
end;
{ ThreadStateEntry[] } ThreadStateEntry_Array1d = specialize DynamicArray<ThreadStateEntry>;
private
class function newThreadStateEntryArray1d(length: int): ThreadStateEntry_Array1d; static;
private
fldLength: int;
fldNotifies: long;
fldEntries: ThreadStateEntry_Array1d;
fldOwnedBy: ThreadStateEntry;
procedure resume(const entry: ThreadStateEntry; needSignal: boolean);
procedure extractEntry();
procedure extractEntry(threadId: long);
procedure appendEntry(const entry: ThreadStateEntry);
function getEntryIndexByState(state: long): int;
function getEntryIndexByThreadId(threadId: long): int;
public
procedure beginSynchronized(); override; final;
procedure endSynchronized(); override; final;
procedure notify();
procedure notifyAll();
procedure wait();
procedure wait(timeInMillis: long);
procedure wait(timeInMillis: long; timeInNanos: int);
function isHold(): boolean; override; final;
end;
Thread = class(&Object, Runnable)
private const
FLAG_EXTERNAL = byte($01);
FLAG_AUTO_FREE = byte($02);
public const
UD_PRIORITY = int(0);
MIN_PRIORITY = int(1);
LOW_PRIORITY = int(3);
NORM_PRIORITY = int(5);
HIGH_PRIORITY = int(7);
MAX_PRIORITY = int(9);
public const
MIN_STACK_SIZE = long($000000001000);
DEFAULT_STACK_SIZE = long($000000800000);
MAX_STACK_SIZE = long($000100000000);
public
class procedure yield(); static;
class procedure sleep(timeInMillis: long); static;
class procedure sleep(timeInMillis: long; timeInNanos: int); static;
class function activeCount(): int; static;
{$IFNDEF LIBRARY}
class function enumerate(): Thread_Collection1d; static;
{$ENDIF}
class function current(): Thread; static;
private
fldStarted: boolean;
fldCreated: boolean;
fldTerminated: boolean;
fldFlags: byte;
fldPriority: int;
fldStackSize: long;
fldThreadId1: long;
fldThreadId2: long;
fldEnumerated: long;
fldDescription: AnsiString;
fldTarget: Runnable;
fldJoinMonitor: Monitor;
constructor create(threadId1, threadId2: long; external: boolean = true);
procedure notifyJoined();
procedure freeIfNecessary();
procedure setDescription(const newDescription: AnsiString);
function isStarted(): boolean;
function getFlag(mask: int): boolean;
function getPriority(): int;
function getDescription(): AnsiString;
protected
constructor create(stackSize: long = DEFAULT_STACK_SIZE; freeOnTerminate: boolean = true);
procedure setPriority(newPriority: int); virtual;
public
constructor create(target: Runnable; freeOnTerminate: boolean = true);
constructor create(target: Runnable; stackSize: long; freeOnTerminate: boolean = true);
destructor destroy; override;
procedure run(); virtual;
procedure start(); virtual;
procedure join();
procedure join(timeInMillis: long);
procedure join(timeInMillis: long; timeInNanos: int);
{$IFDEF WINDOWS}{$CALLING STDCALL}{$ELSE}{$CALLING CDECL}{$ENDIF}
function _addref(): int; override; final;
function _release(): int; override; final;
{$CALLING REGISTER}
function isAlive(): boolean;
function isExternal(): boolean;
published
property freeOnTerminate: boolean index FLAG_AUTO_FREE read getFlag;
property priority: int read getPriority write setPriority;
property description: AnsiString read getDescription write setDescription;
end;
Throwable = class(&Object)
private
fldHelpContext: int;
fldMessage: AnsiString;
fldStackTrace: Pointer_Array1d;
public
constructor create(const message: AnsiString = ''; helpContext: int = 0);
procedure printStackTrace();
function toString(): AnsiString; override;
function clone(): Throwable; virtual;
published
property helpContext: int read fldHelpContext write fldHelpContext;
property message: AnsiString read fldMessage write fldMessage;
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);
InstantiationException = class(RuntimeException);
IllegalStateException = class(RuntimeException);
IllegalMonitorStateException = class(IllegalStateException);
IllegalThreadStateException = class(IllegalStateException);
IllegalArgumentException = class(RuntimeException);
IllegalPropertyValueException = class(IllegalArgumentException);
NumberFormatException = class(IllegalArgumentException);
IndexOutOfBoundsException = class(RuntimeException);
ArrayIndexOutOfBoundsException = class(IndexOutOfBoundsException);
StringIndexOutOfBoundsException = class(IndexOutOfBoundsException);
NegativeArraySizeException = class(RuntimeException);
NullPointerException = class(RuntimeException);
SecurityException = class(RuntimeException);
SafecallException = class(RuntimeException);
UnsupportedOperationException = class(RuntimeException);
ReadOnlyPropertyException = class(UnsupportedOperationException);
WriteOnlyPropertyException = class(UnsupportedOperationException);
Error = class(Throwable);
ClassContentError = class(Error);
AbstractMethodError = class(ClassContentError);
BufferTooLargeError = class(Error);
MachineError = class(Error);
StackOverflowError = class(MachineError);
MemoryError = class(MachineError)
protected
fldFreeDisallowed: boolean;
procedure freeAllow(); virtual;
procedure freeDisallow(); virtual;
public
procedure freeInstance(); override;
end;
OutOfMemoryError = class(MemoryError);
InvalidPointerError = class(MemoryError);
AResource = class sealed
private
class procedure updateResourceStringReferences(); static;
public
class procedure setResourceString(const __unitName, rstrName, rstrValue: AnsiString); static;
class function getResourceString(const __unitName, rstrName: AnsiString): AnsiString; static;
class function unitToResourceName(const __unitName, rsrcName: AnsiString): AnsiString; static;
class function unitToTextResourceName(const __unitName, rsrcName: AnsiString): AnsiString; static;
class function readResourceAsAnsiString(const rsrcName: AnsiString): AnsiString; static;
class function readUnitResourceAsAnsiString(const __unitName, rstrName: AnsiString): AnsiString; static;
end;
Lang = class sealed
{
0 1 2 3 4
0 tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat,
5 tkSet, tkMethod, tkSString, tkLString, tkAString,
10 tkWString, tkVariant, tkArray, tkRecord, tkInterface,
15 tkClass, tkObject, tkWChar, tkBool, tkInt64,
20 tkQWord, tkDynArray, tkInterfaceRaw, tkProcVar, tkUString,
25 tkUChar, tkHelper, tkFile, tkClassRef, tkPointer
0 1 2 3
30 otSByte, otUByte, otSWord, otUWord,
34 otSLong, otULong, otSQWord, otUQWord
38 ftSingle, ftDouble, ftExtended, ftComp,
42 ftCurr
}
private
class function getGuidIndex(const guid: system.TGuid; capacity: int): int; static;
public const
{ === primitive types === }
TYPE_BOOLEAN = int(18);
TYPE_CHAR = int(2);
TYPE_UCHAR = 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(39);
TYPE_REAL = int(40);
TYPE_COMP = int(41);
TYPE_CURRENCY = int(42);
TYPE_ENUMERATION = int(3);
{ === pointer types === }
TYPE_POINTER = int(29);
TYPE_CLASS = int(15);
TYPE_CLASSREF = int(28);
TYPE_INTERFACE_RC = int(14);
TYPE_INTERFACE_RAW = int(22);
TYPE_FUNCTION = int(23);
TYPE_ANSISTRING = int(9);
TYPE_WIDESTRING = int(10);
TYPE_UNICODESTRING = int(24);
TYPE_ARRAY_DYNAMIC = int(21);
{ === structured types === }
TYPE_UNKNOWN = int(0);
TYPE_SET = int(5);
TYPE_FILE = int(27);
TYPE_RECORD = int(13);
TYPE_OBJECT = int(16);
TYPE_METHOD = int(6);
TYPE_HELPER = int(26);
TYPE_VARIANT = int(11);
TYPE_SHORTSTRING = int(7);
TYPE_ARRAY_STATIC = int(12);
public
class procedure registerInterfaces(const iinfos: array of Pointer); static;
class function isType(const typRef, typIID: ShortString): boolean; static;
class function isType(const typRef, typIID: system.TGuid): boolean; static;
class function isInstance(objRef: ISimple; const typIID: ShortString): boolean; static;
class function isInstance(objRef: ISimple; const typIID: system.TGuid): boolean; static;
class function isInstance(objRef: ISimple; const typRef: system.TClass): boolean; static;
class function isInstance(objRef: IUnknown; const typIID: ShortString): boolean; static;
class function identityHashCode(objRef: TObject): long; static;
class function identityHashCode(objRef: ISimple): long; static;
class function identityHashCode(objRef: IUnknown): long; static;
class function cast(objRef: ISimple; const typIID: ShortString): ISimple; static;
class function cast(objRef: ISimple; const typIID: system.TGuid): IUnknown; static;
class function cast(objRef: ISimple; const typRef: system.TClass): TObject; static;
class function cast(objRef: IUnknown; const typIID: ShortString): ISimple; static;
class function classFor(const typIID: ShortString): &Class; static;
class function classFor(const typIID: system.TGuid): &Class; static;
class function classFor(const typRef: system.TClass): &Class; static;
class function classFor(tinfo: Pointer): &Class; static;
end;
Math = class sealed
strict private const
ROUND_TO_NEAREST = int($0000);
ROUND_DOWN = int($0400);
ROUND_UP = int($0800);
ROUND_TOWARD_ZERO = int($0c00);
private
class procedure setRoundMode(mode: int); static;
{$IFDEF WINDOWS}
public
class function E: real; static;
class function PI: real; static;
class function LOG_2_10: real; static;
class function LOG_2_E: real; static;
class function LOG_10_2: real; static;
class function LOG_E_2: real; static;
{$ELSE}
public const
E = real(2.7182818284590452354);
PI = real(3.1415926535897932386);
LOG_2_10 = real(3.3219280948873623478);
LOG_2_E = real(1.4426950408889634074);
LOG_10_2 = real(0.30102999566398119522);
LOG_E_2 = real(0.69314718055994530945);
{$ENDIF}
public
class function abs(x: int): int; static;
class function abs(x: long): long; static;
class function abs(x: float): float; static;
class function abs(x: double): double; static;
class function abs(x: real): real; static;
class function sin(x: real): real; static;
class function cos(x: real): real; static;
class function tan(x: real): real; static;
class function asin(x: real): real; static;
class function acos(x: real): real; static;
class function atan(x: real): real; static;
class function exp(x: real): real; static;
class function exp2(x: real): real; static;
class function exp10(x: real): real; static;
class function log(x: real): real; static;
class function log2(x: real): real; static;
class function log10(x: real): real; static;
class function sqrt(x: real): real; static;
class function cbrt(x: real): real; static;
class function sinh(x: real): real; static;
class function cosh(x: real): real; static;
class function tanh(x: real): real; static;
class function asinh(x: real): real; static;
class function acosh(x: real): real; static;
class function atanh(x: real): real; static;
class function ceil(x: real): real; static;
class function floor(x: real): real; static;
class function round(x: real): real; static;
class function intPart(x: real): real; static;
class function fracPart(x: real): real; static;
class function atan2(x, y: real): real; static;
class function pow(x, y: real): real; static;
class function toRadians(angleInDegrees: real): real; static;
class function toDegrees(angleInRadians: real): real; static;
end;
&Array = class sealed
private
class procedure copyBy1(const src; var dst; length: long); static;
class procedure copyBy2(const src; var dst; length: long); static;
class procedure copyBy4(const src; var dst; length: long); static;
class procedure copyBy8(const src; var dst; length: long); static;
class procedure fillReal(var dst; length: int; const value: real); static;
class procedure fillLong(var dst; size, length: int; value: long); static;
class function findfeq(const src; size, length: int; value: long): int; static;
class function findfne(const src; size, length: int; value: long): int; static;
class function findbeq(const src; size, length: int; value: long): int; static;
class function findbne(const src; size, length: int; value: long): int; static;
class function compfeq(const src1, src2; size, length: int): int; static;
class function compfne(const src1, src2; size, length: int): int; static;
class function compbeq(const src1, src2; size, length: int): int; static;
class function compbne(const src1, src2; size, length: int): int; static;
public const
NOT_FOUND = int(-$80000000);
public
class procedure checkBounds(const aarray; offset, length: int); static;
class procedure copyRaw(const src; var dst; length: long); static;
class procedure copyPrimitives(const srcArray: boolean_Array1d; srcOffset: int; const dstArray: boolean_Array1d; dstOffset: int; length: int); static;
class procedure copyPrimitives(const srcArray: char_Array1d; srcOffset: int; const dstArray: char_Array1d; dstOffset: int; length: int); static;
class procedure copyPrimitives(const srcArray: uchar_Array1d; srcOffset: int; const dstArray: uchar_Array1d; dstOffset: int; length: int); static;
class procedure copyPrimitives(const srcArray: byte_Array1d; srcOffset: int; const dstArray: byte_Array1d; dstOffset: int; length: int); static;
class procedure copyPrimitives(const srcArray: short_Array1d; srcOffset: int; const dstArray: short_Array1d; dstOffset: int; length: int); static;
class procedure copyPrimitives(const srcArray: int_Array1d; srcOffset: int; const dstArray: int_Array1d; dstOffset: int; length: int); static;
class procedure copyPrimitives(const srcArray: long_Array1d; srcOffset: int; const dstArray: long_Array1d; dstOffset: int; length: int); static;
class procedure copyPrimitives(const srcArray: float_Array1d; srcOffset: int; const dstArray: float_Array1d; dstOffset: int; length: int); static;
class procedure copyPrimitives(const srcArray: double_Array1d; srcOffset: int; const dstArray: double_Array1d; dstOffset: int; length: int); static;
class procedure copyPrimitives(const srcArray: real_Array1d; srcOffset: int; const dstArray: real_Array1d; dstOffset: int; length: int); static;
class procedure copyStrings(const srcArray: AnsiString_Array1d; srcOffset: int; const dstArray: AnsiString_Array1d; dstOffset: int; length: int); static;
class procedure copyStrings(const srcArray: UnicodeString_Array1d; srcOffset: int; const dstArray: UnicodeString_Array1d; dstOffset: int; length: int); static;
class procedure copyObjects(const srcArray; srcOffset: int; const dstArray; dstOffset: int; length: int); static;
class procedure copySimples(const srcArray; srcOffset: int; const dstArray; dstOffset: int; length: int); static;
class procedure copyUnknowns(const srcArray; srcOffset: int; const dstArray; dstOffset: int; length: int); static;
class procedure copyArrays(const srcArray; srcOffset: int; const dstArray; dstOffset: int; length: int); static;
class procedure zeroRaw(out dst; length: long); static;
class procedure fillPrimitives(const dstArray: boolean_Array1d; dstOffset: int; length: int; value: boolean); static;
class procedure fillPrimitives(const dstArray: char_Array1d; dstOffset: int; length: int; value: char); static;
class procedure fillPrimitives(const dstArray: uchar_Array1d; dstOffset: int; length: int; value: uchar); static;
class procedure fillPrimitives(const dstArray: byte_Array1d; dstOffset: int; length: int; value: byte); static;
class procedure fillPrimitives(const dstArray: short_Array1d; dstOffset: int; length: int; value: short); static;
class procedure fillPrimitives(const dstArray: int_Array1d; dstOffset: int; length: int; value: int); static;
class procedure fillPrimitives(const dstArray: long_Array1d; dstOffset: int; length: int; value: long); static;
class procedure fillPrimitives(const dstArray: float_Array1d; dstOffset: int; length: int; value: float); static;
class procedure fillPrimitives(const dstArray: double_Array1d; dstOffset: int; length: int; value: double); static;
class procedure fillPrimitives(const dstArray: real_Array1d; dstOffset: int; length: int; value: real); static;
class procedure fillStrings(const dstArray: AnsiString_Array1d; dstOffset: int; length: int; const value: AnsiString); static;
class procedure fillStrings(const dstArray: UnicodeString_Array1d; dstOffset: int; length: int; const value: UnicodeString); static;
class procedure fillObjects(const dstArray; dstOffset: int; length: int; value: TObject); static;
class procedure fillSimples(const dstArray; dstOffset: int; length: int; value: ISimple); static;
class procedure fillUnknowns(const dstArray; dstOffset: int; length: int; value: IUnknown); static;
class procedure fillArrays(const dstArray; dstOffset: int; length: int; const value); static;
class function indexOf(value: boolean; const aarray: boolean_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function indexOf(value: char; const aarray: char_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function indexOf(value: uchar; const aarray: uchar_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function indexOf(value: int; const aarray: byte_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function indexOf(value: int; const aarray: short_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function indexOf(value: int; const aarray: int_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function indexOf(value: long; const aarray: long_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function indexOf(value: Pointer; const aarray; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOf(value: boolean; const aarray: boolean_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOf(value: char; const aarray: char_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOf(value: uchar; const aarray: uchar_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOf(value: int; const aarray: byte_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOf(value: int; const aarray: short_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOf(value: int; const aarray: int_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOf(value: long; const aarray: long_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOf(value: Pointer; const aarray; startFromIndex: int; maximumScanLength: int): int; static;
class function indexOfNon(value: boolean; const aarray: boolean_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function indexOfNon(value: char; const aarray: char_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function indexOfNon(value: uchar; const aarray: uchar_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function indexOfNon(value: int; const aarray: byte_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function indexOfNon(value: int; const aarray: short_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function indexOfNon(value: int; const aarray: int_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function indexOfNon(value: long; const aarray: long_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function indexOfNon(value: Pointer; const aarray; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOfNon(value: boolean; const aarray: boolean_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOfNon(value: char; const aarray: char_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOfNon(value: uchar; const aarray: uchar_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOfNon(value: int; const aarray: byte_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOfNon(value: int; const aarray: short_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOfNon(value: int; const aarray: int_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOfNon(value: long; const aarray: long_Array1d; startFromIndex: int; maximumScanLength: int): int; static;
class function lastIndexOfNon(value: Pointer; const aarray; startFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfEqual(const array1: boolean_Array1d; array1StartFromIndex: int; const array2: boolean_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfEqual(const array1: char_Array1d; array1StartFromIndex: int; const array2: char_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfEqual(const array1: uchar_Array1d; array1StartFromIndex: int; const array2: uchar_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfEqual(const array1: byte_Array1d; array1StartFromIndex: int; const array2: byte_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfEqual(const array1: short_Array1d; array1StartFromIndex: int; const array2: short_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfEqual(const array1: int_Array1d; array1StartFromIndex: int; const array2: int_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfEqual(const array1: long_Array1d; array1StartFromIndex: int; const array2: long_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfEqualPtr(const array1; array1StartFromIndex: int; const array2; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfNonEqual(const array1: boolean_Array1d; array1StartFromIndex: int; const array2: boolean_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfNonEqual(const array1: char_Array1d; array1StartFromIndex: int; const array2: char_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfNonEqual(const array1: uchar_Array1d; array1StartFromIndex: int; const array2: uchar_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfNonEqual(const array1: byte_Array1d; array1StartFromIndex: int; const array2: byte_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfNonEqual(const array1: short_Array1d; array1StartFromIndex: int; const array2: short_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfNonEqual(const array1: int_Array1d; array1StartFromIndex: int; const array2: int_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfNonEqual(const array1: long_Array1d; array1StartFromIndex: int; const array2: long_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function offsetOfNonEqualPtr(const array1; array1StartFromIndex: int; const array2; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfEqual(const array1: boolean_Array1d; array1StartFromIndex: int; const array2: boolean_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfEqual(const array1: char_Array1d; array1StartFromIndex: int; const array2: char_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfEqual(const array1: uchar_Array1d; array1StartFromIndex: int; const array2: uchar_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfEqual(const array1: byte_Array1d; array1StartFromIndex: int; const array2: byte_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfEqual(const array1: short_Array1d; array1StartFromIndex: int; const array2: short_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfEqual(const array1: int_Array1d; array1StartFromIndex: int; const array2: int_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfEqual(const array1: long_Array1d; array1StartFromIndex: int; const array2: long_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfEqualPtr(const array1; array1StartFromIndex: int; const array2; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfNonEqual(const array1: boolean_Array1d; array1StartFromIndex: int; const array2: boolean_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfNonEqual(const array1: char_Array1d; array1StartFromIndex: int; const array2: char_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfNonEqual(const array1: uchar_Array1d; array1StartFromIndex: int; const array2: uchar_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfNonEqual(const array1: byte_Array1d; array1StartFromIndex: int; const array2: byte_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfNonEqual(const array1: short_Array1d; array1StartFromIndex: int; const array2: short_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfNonEqual(const array1: int_Array1d; array1StartFromIndex: int; const array2: int_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfNonEqual(const array1: long_Array1d; array1StartFromIndex: int; const array2: long_Array1d; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function negOffsetOfNonEqualPtr(const array1; array1StartFromIndex: int; const array2; array2StartFromIndex: int; maximumScanLength: int): int; static;
class function newBoolean1d(length: int): boolean_Array1d; static;
class function newBoolean1d(const components: array of boolean): boolean_Array1d; static;
class function newChar1d(length: int): char_Array1d; static;
class function newChar1d(const components: array of char): char_Array1d; static;
class function newUChar1d(length: int): uchar_Array1d; static;
class function newUChar1d(const components: array of uchar): uchar_Array1d; static;
class function newByte1d(length: int): byte_Array1d; static;
class function newByte1d(const components: array of byte): byte_Array1d; static;
class function newShort1d(length: int): short_Array1d; static;
class function newShort1d(const components: array of short): short_Array1d; static;
class function newInt1d(length: int): int_Array1d; static;
class function newInt1d(const components: array of int): int_Array1d; static;
class function newLong1d(length: int): long_Array1d; static;
class function newLong1d(const components: array of long): long_Array1d; static;
class function newFloat1d(length: int): float_Array1d; static;
class function newFloat1d(const components: array of float): float_Array1d; static;
class function newDouble1d(length: int): double_Array1d; static;
class function newDouble1d(const components: array of double): double_Array1d; static;
class function newReal1d(length: int): real_Array1d; static;
class function newReal1d(const components: array of real): real_Array1d; static;
class function newAnsiString1d(length: int): AnsiString_Array1d; static;
class function newAnsiString1d(const components: array of AnsiString): AnsiString_Array1d; static;
class function newUnicodeString1d(length: int): UnicodeString_Array1d; static;
class function newUnicodeString1d(const components: array of UnicodeString): UnicodeString_Array1d; static;
class function newPointer1d(length: int): Pointer_Array1d; static;
class function newPointer1d(const components: array of Pointer): Pointer_Array1d; static;
class function newTObject1d(length: int): TObject_Array1d; static;
class function newTObject1d(const components: array of TObject): TObject_Array1d; static;
class function newISimple1d(length: int): ISimple_Array1d; static;
class function newISimple1d(const components: array of ISimple): ISimple_Array1d; static;
class function newIUnknown1d(length: int): IUnknown_Array1d; static;
class function newIUnknown1d(const components: array of IUnknown): IUnknown_Array1d; static;
class function newBoolean2d(length: int): boolean_Array2d; static;
class function newBoolean2d(length1, length2: int): boolean_Array2d; static;
class function newBoolean2d(const components: array of boolean_Array1d): boolean_Array2d; static;
class function newChar2d(length: int): char_Array2d; static;
class function newChar2d(length1, length2: int): char_Array2d; static;
class function newChar2d(const components: array of char_Array1d): char_Array2d; static;
class function newUChar2d(length: int): uchar_Array2d; static;
class function newUChar2d(length1, length2: int): uchar_Array2d; static;
class function newUChar2d(const components: array of uchar_Array1d): uchar_Array2d; static;
class function newByte2d(length: int): byte_Array2d; static;
class function newByte2d(length1, length2: int): byte_Array2d; static;
class function newByte2d(const components: array of byte_Array1d): byte_Array2d; static;
class function newShort2d(length: int): short_Array2d; static;
class function newShort2d(length1, length2: int): short_Array2d; static;
class function newShort2d(const components: array of short_Array1d): short_Array2d; static;
class function newInt2d(length: int): int_Array2d; static;
class function newInt2d(length1, length2: int): int_Array2d; static;
class function newInt2d(const components: array of int_Array1d): int_Array2d; static;
class function newLong2d(length: int): long_Array2d; static;
class function newLong2d(length1, length2: int): long_Array2d; static;
class function newLong2d(const components: array of long_Array1d): long_Array2d; static;
class function newFloat2d(length: int): float_Array2d; static;
class function newFloat2d(length1, length2: int): float_Array2d; static;
class function newFloat2d(const components: array of float_Array1d): float_Array2d; static;
class function newDouble2d(length: int): double_Array2d; static;
class function newDouble2d(length1, length2: int): double_Array2d; static;
class function newDouble2d(const components: array of double_Array1d): double_Array2d; static;
class function newReal2d(length: int): real_Array2d; static;
class function newReal2d(length1, length2: int): real_Array2d; static;
class function newReal2d(const components: array of real_Array1d): real_Array2d; static;
class function newAnsiString2d(length: int): AnsiString_Array2d; static;
class function newAnsiString2d(length1, length2: int): AnsiString_Array2d; static;
class function newAnsiString2d(const components: array of AnsiString_Array1d): AnsiString_Array2d; static;
class function newUnicodeString2d(length: int): UnicodeString_Array2d; static;
class function newUnicodeString2d(length1, length2: int): UnicodeString_Array2d; static;
class function newUnicodeString2d(const components: array of UnicodeString_Array1d): UnicodeString_Array2d; static;
class function newPointer2d(length: int): Pointer_Array2d; static;
class function newPointer2d(length1, length2: int): Pointer_Array2d; static;
class function newPointer2d(const components: array of Pointer_Array1d): Pointer_Array2d; static;
class function newTObject2d(length: int): TObject_Array2d; static;
class function newTObject2d(length1, length2: int): TObject_Array2d; static;
class function newTObject2d(const components: array of TObject_Array1d): TObject_Array2d; static;
class function newISimple2d(length: int): ISimple_Array2d; static;
class function newISimple2d(length1, length2: int): ISimple_Array2d; static;
class function newISimple2d(const components: array of ISimple_Array1d): ISimple_Array2d; static;
class function newIUnknown2d(length: int): IUnknown_Array2d; static;
class function newIUnknown2d(length1, length2: int): IUnknown_Array2d; static;
class function newIUnknown2d(const components: array of IUnknown_Array1d): IUnknown_Array2d; static;
end;
TObjectExtended = class helper for TObject
private const
TM_FIELD = int(0);
TM_SPECIAL = int(1);
TM_VIRTUAL = int(2);
TM_CONST = int(3);
private
class function getPropertyInfo(const name: AnsiString): PPropInfo;
public
procedure writePropertyOfBoolean(const name: AnsiString; const value: boolean);
procedure writePropertyOfLong(const name: AnsiString; const value: long);
procedure writePropertyOfDouble(const name: AnsiString; const value: double);
procedure writePropertyOfAnsiString(const name: AnsiString; const value: AnsiString);
procedure writePropertyOfUnicodeString(const name: AnsiString; const value: UnicodeString);
procedure writePropertyOfObject(const name: AnsiString; const value: TObject);
procedure writePropertyOfSimple(const name: AnsiString; const value: ISimple);
procedure writePropertyOfUnknown(const name: AnsiString; const value: IUnknown);
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 readPropertyOfAnsiString(const name: AnsiString): AnsiString;
function readPropertyOfUnicodeString(const name: AnsiString): UnicodeString;
function readPropertyOfObject(const name: AnsiString): TObject;
function readPropertyOfSimple(const name: AnsiString): ISimple;
function readPropertyOfUnknown(const name: AnsiString): IUnknown;
function getClass(): &Class;
end;
ISimpleExtended = type helper for ISimple
public
function getClass(): &Class;
end;
IUnknownExtended = type helper for IUnknown
public
function getClass(): &Class;
end;
AnsiStringExtended = type helper for AnsiString
public
class function create(length: int): AnsiString; static;
class function create(const src: byte_Array1d): AnsiString; static;
class function create(const src: char_Array1d): AnsiString; static;
class function create(const src: byte_Array1d; offset, length: int): AnsiString; static;
class function create(const src: char_Array1d; offset, length: int): AnsiString; static;
class function create(const charCodes: int_Array1d; offset, length: int): AnsiString; static;
class function format(const form: AnsiString; const data: array of Value): AnsiString; static;
private
function getLength(): int;
public
procedure getChars(beginIndex, endIndex: int; const dst: char_Array1d; offset: int);
function startsWith(const prefix: AnsiString; position: int = 1): boolean;
function endsWith(const suffix: AnsiString): boolean;
function indexOf(const prefix: AnsiString; startFromIndex: int = 1): int;
function lastIndexOf(const prefix: AnsiString; startFromIndex: int = int(CoInt.MAX_VALUE + 1)): int;
function replaceAll(oldCharacter, newCharacter: char): AnsiString;
function copy(): AnsiString;
function copy(beginIndex: int): AnsiString;
function copy(beginIndex, endIndex: int): AnsiString;
function trim(): AnsiString;
function substring(beginIndex: int): AnsiString;
function substring(beginIndex, endIndex: int): AnsiString;
function toLowerCase(): AnsiString;
function toUpperCase(): AnsiString;
function toUTF16(): UnicodeString;
function toByteArray(): byte_Array1d;
function toCharArray(): char_Array1d;
function toCharCodes(): int_Array1d;
function split(): AnsiString_Array1d;
property length: int read getLength;
end;
UnicodeStringExtended = type helper for UnicodeString
public
class function create(length: int): UnicodeString; static;
class function create(const src: short_Array1d): UnicodeString; static;
class function create(const src: uchar_Array1d): UnicodeString; static;
class function create(const src: short_Array1d; offset, length: int): UnicodeString; static;
class function create(const src: uchar_Array1d; offset, length: int): UnicodeString; static;
class function create(const charCodes: int_Array1d; offset, length: int): UnicodeString; static;
class function format(const form: UnicodeString; const data: array of Value): UnicodeString; static;
private
function getLength(): int;
public
procedure getChars(beginIndex, endIndex: int; const dst: uchar_Array1d; offset: int);
function equalsIgnoreCase(const anot: UnicodeString): boolean;
function startsWith(const prefix: UnicodeString; position: int = 1): boolean;
function endsWith(const suffix: UnicodeString): boolean;
function indexOf(const prefix: UnicodeString; startFromIndex: int = 1): int;
function lastIndexOf(const prefix: UnicodeString; startFromIndex: int = int(CoInt.MAX_VALUE + 1)): int;
function replaceAll(oldCharacter, newCharacter: uchar): UnicodeString;
function copy(): UnicodeString;
function copy(beginIndex: int): UnicodeString;
function copy(beginIndex, endIndex: int): UnicodeString;
function trim(): UnicodeString;
function substring(beginIndex: int): UnicodeString;
function substring(beginIndex, endIndex: int): UnicodeString;
function toLowerCase(): UnicodeString;
function toUpperCase(): UnicodeString;
function toUTF8(): AnsiString;
function toShortArray(): short_Array1d;
function toUCharArray(): uchar_Array1d;
function toCharCodes(): int_Array1d;
function split(): UnicodeString_Array1d;
property length: int read getLength;
end;
{%endregion}
{%region real operators (Windows only)}
{$IFDEF WINDOWS}
operator :=(value: long): real;
operator :=(value: double): real;
operator +(const value: real): real;
operator -(const value: real): real;
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 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;
{$ENDIF}
{%endregion}
implementation
{%region} uses
pascalx.io.charset.basiclatin,
pascalx.lang.locale;
{%endregion}
{$R *.res}
{$WARN 7104 OFF} { позволить обращение к локальным переменным через [rbp-<смещение>] }
{$WARN 7105 OFF} { позволить использовать инструкцию lea rsp, [rsp-<смещение>] чтобы уменьшить значение регистра указателя стака }
{$WARN 7120 OFF} { позволить не указывать размер операндов памяти для инструкций SSE и AVX в тех случаях, когда это необязательно }
{$WARN 7121 OFF}
{$WARN 7122 OFF}
{$WARN 7123 OFF} { позволить отрицательные смещения в операндах памяти }
{$ASMMODE INTEL}
{$TYPEINFO OFF}
{$CALLING REGISTER}
{%region} type
Pint = ^int;
PFXContext = ^FXContext;
PResourceStringInitEntry = ^ResourceStringInitEntry;
PResourceStringInitList = ^ResourceStringInitList;
PResourceStringList = ^ResourceStringList;
PResourceStringStruct = ^ResourceStringStruct;
PPResourceStringStruct = ^PResourceStringStruct;
TypeInformation = class;
PointerTypeInformation = class;
PrimitiveTypeInformation = class;
ClassTypeInformation = class;
ClassRefTypeInformation = class;
InterfaceTypeInformation = class;
DynamicArrayTypeInformation = class;
FunctionTypeInformation = class;
StructuredTypeInformation = class;
PropertyInformation = class;
ThreadCollection = class;
InterfaceEntry = class;
ThreadEntry = class;
int2 = packed array [0..1] of int;
int4 = packed array [0..3] of int;
long2 = packed array [0..1] of long;
{ InterfaceEntry[] } InterfaceEntry_Array1d = specialize DynamicArray<InterfaceEntry>;
{ ThreadEntry[] } ThreadEntry_Array1d = specialize DynamicArray<ThreadEntry>;
{ int2[] } int2_Array1d = specialize DynamicArray<int2>;
{$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; __reserved005: byte;
fop: short;
fip: long;
fdp: long;
mxcsr: int;
mxcsrMask: int;
st0: real; __reserved02A: packed array [0..5] of byte;
st1: real; __reserved03A: packed array [0..5] of byte;
st2: real; __reserved04A: packed array [0..5] of byte;
st3: real; __reserved05A: packed array [0..5] of byte;
st4: real; __reserved06A: packed array [0..5] of byte;
st5: real; __reserved07A: packed array [0..5] of byte;
st6: real; __reserved08A: packed array [0..5] of byte;
st7: real; __reserved09A: packed array [0..5] of byte;
case int of
0: (
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;
);
1: (
xmm: packed array [0..15] of long2;
__reserved1A0: packed array [0..$2f] of byte;
available: packed array [0..$2f] of byte;
);
end;
RealStruct = packed record
case int of
0: (
significand: long;
exponent: short;
);
1: (
bytes: packed array [0..9] of system.UInt8;
);
2: (
words: packed array [0..4] of system.UInt16;
);
3: (
value: real;
);
end;
ResourceStringInitEntry = packed record
address: Pointer;
data: PResourceStringStruct;
end;
ResourceStringInitList = packed record
length: long;
list: packed array [0..0] of PResourceStringInitEntry;
end;
ResourceStringTable = packed record
start: PPResourceStringStruct;
finish: PPResourceStringStruct;
end;
ResourceStringList = packed record
length: long;
list: packed array [0..0] of ResourceStringTable;
end;
ResourceStringStruct = packed record
name: AnsiString;
value: AnsiString;
default: AnsiString;
hash: int;
__reserved1C: int;
end;
TypeInformation = class abstract(RefCountObject, &Class)
protected
fldInfo: PTypeInfo;
fldData: PTypeData;
public
constructor create(info: PTypeInfo);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function isPointer(): boolean; virtual; abstract;
function isPrimitive(): boolean; virtual; abstract;
function isInstance(ref: TObject): boolean; virtual;
function isInstance(ref: ISimple): boolean; virtual;
function isInstance(ref: IUnknown): boolean; virtual;
function isAssignableFrom(cls: &Class): boolean; virtual;
function getTypeKind(): int; virtual;
function getUnitName(): AnsiString; virtual;
function getSimpleName(): AnsiString; virtual;
function getOriginalUnit(): AnsiString; virtual;
function getOriginalName(): AnsiString;
function getCanonicalName(): AnsiString;
function getProperties(): Property_Array1d; virtual;
function getInterfaces(): Class_Array1d; virtual;
function getProperty(const name: AnsiString): &Property; virtual;
function getSuperclass(): &Class; virtual;
function getReference(): &Class; virtual;
function getComponentType(): &Class; virtual;
function createInstance(): DynamicObject; virtual;
end;
PrimitiveTypeInformation = class sealed(TypeInformation)
private
fldKind: int;
fldName: AnsiString;
public
constructor create(info: PTypeInfo; kind: int; const name: AnsiString);
function equals(anot: TObject): boolean; override;
function getHashCode(): long; override;
function toString(): AnsiString; override;
function isPointer(): boolean; override;
function isPrimitive(): boolean; override;
function isAssignableFrom(cls: &Class): boolean; override;
function getTypeKind(): int; override;
function getSimpleName(): AnsiString; override;
end;
PointerTypeInformation = class(TypeInformation)
public
function isPointer(): boolean; override; final;
function isPrimitive(): boolean; override; final;
end;
ClassTypeInformation = class sealed(PointerTypeInformation)
private
class function typeInfoToLangType(tinfo: PTypeInfo): int; static;
class function propInfoToProperty(pinfo: PPropInfo): &Property; static;
private
fldType: TClass;
public
constructor create(info: TClass);
constructor create(info: PTypeInfo);
function toString(): AnsiString; override;
function isInstance(ref: TObject): boolean; override;
function isInstance(ref: ISimple): boolean; override;
function isInstance(ref: IUnknown): boolean; override;
function isAssignableFrom(cls: &Class): boolean; override;
function getTypeKind(): int; override;
function getOriginalUnit(): AnsiString; override;
function getProperties(): Property_Array1d; override;
function getInterfaces(): Class_Array1d; override;
function getProperty(const name: AnsiString): &Property; override;
function getSuperclass(): &Class; override;
function createInstance(): DynamicObject; override;
end;
ClassRefTypeInformation = class sealed(PointerTypeInformation)
private
fldType: TClass;
public
constructor create(info: PTypeInfo);
function toString(): AnsiString; override;
function isAssignableFrom(cls: &Class): boolean; override;
function getTypeKind(): int; override;
function getReference(): &Class; override;
end;
InterfaceTypeInformation = class sealed(PointerTypeInformation)
public
function toString(): AnsiString; override;
function isInstance(ref: TObject): boolean; override;
function isInstance(ref: ISimple): boolean; override;
function isInstance(ref: IUnknown): boolean; override;
function isAssignableFrom(cls: &Class): boolean; override;
function getOriginalUnit(): AnsiString; override;
function getInterfaces(): Class_Array1d; override;
end;
DynamicArrayTypeInformation = class sealed(PointerTypeInformation)
private
fldComponent: PTypeInfo;
public
constructor create(info: PTypeInfo);
function toString(): AnsiString; override;
function isAssignableFrom(cls: &Class): boolean; override;
function getTypeKind(): int; override;
function getUnitName(): AnsiString; override;
function getSimpleName(): AnsiString; override;
function getOriginalUnit(): AnsiString; override;
function getComponentType(): &Class; override;
end;
FunctionTypeInformation = class sealed(PointerTypeInformation)
public
function isAssignableFrom(cls: &Class): boolean; override;
function getTypeKind(): int; override;
end;
StructuredTypeInformation = class(TypeInformation)
public
function isPointer(): boolean; override; final;
function isPrimitive(): boolean; override; final;
end;
PropertyInformation = class sealed(RefCountObject, &Property)
private
fldFlags: int;
fldName: AnsiString;
fldType: &Class;
public
constructor create(readable, writeable, storeable: boolean; &type: &Class; const name: AnsiString);
function isReadable(): boolean;
function isWriteable(): boolean;
function isStoreable(): boolean;
function getName(): AnsiString;
function getType(): &Class;
end;
ThreadCollection = class sealed(RefCountObject, Thread_Collection1d)
private
fldThreads: Thread_Array1d;
public
constructor create(const threads: Thread_Array1d);
destructor destroy; override;
procedure copyInto(const dstArray; dstOffset: int);
function getLength(): int;
function componentAt(index: int): Thread;
function toArray(): Thread_Array1d;
end;
InterfaceEntry = class sealed(&Object)
public
constructor create(const guid: system.TGuid; info: PTypeInfo; next: InterfaceEntry);
public
guid: system.TGuid;
info: PTypeInfo;
next: InterfaceEntry;
end;
ThreadEntry = class sealed(&Object)
public
constructor create(const threadId1, threadId2: long; threadRef: Thread; next: ThreadEntry);
destructor destroy; override;
public
threadId1: long;
threadId2: long;
event: long;
next: ThreadEntry;
threadRef: Thread;
threadOld: Thread;
end;
{%endregion}
{%region} var
ints: packed array [0..2] of int = (
int($80000000),
int($ffffc000),
int($00004000)
);
longs: packed array [0..5] of long = (
long($000000007fffffff),
long($7fffffffffffffff),
long($8000000000000000),
long($ffffffffffffffff),
long($ffffffff80000000),
long($0000000080000000)
);
floats: packed array [0..2] of float = (
2.14748365e+09,
9.22337204e+18,
CoFloat.NAN
);
doubles: packed array [0..1] of double = (
2.14748364800000000e+009,
9.22337203685477581e+018
);
int4s: packed array [0..0] of int4 = (
( int($7fffffff), int(0), int(0), int(0) )
);
long2s: packed array [0..0] of long2 = (
( long($7fffffffffffffff), long(0) )
);
reals: packed array [0..59] of RealStruct = (
( significand: long($8000000000000000); exponent: short($bfff) ), { –1.0 }
( significand: long($aaaaaaaaaaaaaaab); exponent: short($3ffd) ), { 1.0 / 3.0 }
( significand: long($8000000000000000); exponent: short($3ffe) ), { 1.0 / 2.0 }
( significand: long($c90fdaa22168c235); exponent: short($4001) ), { 2.0 * π }
( significand: long($e52ee0d31e0fbdc3); exponent: short($4004) ), { 180.0 / π }
( significand: long($a000000000000000); exponent: short($4002) ), { 1.e+0001 }
( significand: long($c800000000000000); exponent: short($4005) ), { 1.e+0002 }
( significand: long($fa00000000000000); exponent: short($4008) ), { 1.e+0003 }
( significand: long($9c40000000000000); exponent: short($400c) ), { 1.e+0004 }
( significand: long($c350000000000000); exponent: short($400f) ), { 1.e+0005 }
( significand: long($f424000000000000); exponent: short($4012) ), { 1.e+0006 }
( significand: long($9896800000000000); exponent: short($4016) ), { 1.e+0007 }
( significand: long($bebc200000000000); exponent: short($4019) ), { 1.e+0008 }
( significand: long($ee6b280000000000); exponent: short($401c) ), { 1.e+0009 }
( significand: long($9502f90000000000); exponent: short($4020) ), { 1.e+0010 }
( significand: long($ba43b74000000000); exponent: short($4023) ), { 1.e+0011 }
( significand: long($e8d4a51000000000); exponent: short($4026) ), { 1.e+0012 }
( significand: long($9184e72a00000000); exponent: short($402a) ), { 1.e+0013 }
( significand: long($b5e620f480000000); exponent: short($402d) ), { 1.e+0014 }
( significand: long($e35fa931a0000000); exponent: short($4030) ), { 1.e+0015 }
( significand: long($8e1bc9bf04000000); exponent: short($4034) ), { 1.e+0016 }
( significand: long($b1a2bc2ec5000000); exponent: short($4037) ), { 1.e+0017 }
( significand: long($de0b6b3a76400000); exponent: short($403a) ), { 1.e+0018 }
( significand: long($8ac7230489e80000); exponent: short($403e) ), { 1.e+0019 }
( significand: long($ad78ebc5ac620000); exponent: short($4041) ), { 1.e+0020 }
( significand: long($d8d726b7177a8000); exponent: short($4044) ), { 1.e+0021 }
( significand: long($878678326eac9000); exponent: short($4048) ), { 1.e+0022 }
( significand: long($a968163f0a57b400); exponent: short($404b) ), { 1.e+0023 }
( significand: long($d3c21bcecceda100); exponent: short($404e) ), { 1.e+0024 }
( significand: long($84595161401484a0); exponent: short($4052) ), { 1.e+0025 }
( significand: long($a56fa5b99019a5c8); exponent: short($4055) ), { 1.e+0026 }
( significand: long($cecb8f27f4200f3a); exponent: short($4058) ), { 1.e+0027 }
( significand: long($813f3978f8940984); exponent: short($405c) ), { 1.e+0028 }
( significand: long($a18f07d736b90be5); exponent: short($405f) ), { 1.e+0029 }
( significand: long($c9f2c9cd04674edf); exponent: short($4062) ), { 1.e+0030 }
( significand: long($fc6f7c4045812296); exponent: short($4065) ), { 1.e+0031 }
( significand: long($9dc5ada82b70b59e); exponent: short($4069) ), { 1.e+0032 }
( significand: long($c2781f49ffcfa6d5); exponent: short($40d3) ), { 1.e+0064 }
( significand: long($efb3ab16c59b14a3); exponent: short($413d) ), { 1.e+0096 }
( significand: long($93ba47c980e98ce0); exponent: short($41a8) ), { 1.e+0128 }
( significand: long($b616a12b7fe617aa); exponent: short($4212) ), { 1.e+0160 }
( significand: long($e070f78d3927556b); exponent: short($427c) ), { 1.e+0192 }
( significand: long($8a5296ffe33cc930); exponent: short($42e7) ), { 1.e+0224 }
( significand: long($aa7eebfb9df9de8e); exponent: short($4351) ), { 1.e+0256 }
( significand: long($d226fc195c6a2f8c); exponent: short($43bb) ), { 1.e+0288 }
( significand: long($81842f29f2cce376); exponent: short($4426) ), { 1.e+0320 }
( significand: long($9fa42700db900ad2); exponent: short($4490) ), { 1.e+0352 }
( significand: long($c4c5e310aef8aa17); exponent: short($44fa) ), { 1.e+0384 }
( significand: long($f28a9c07e9b09c59); exponent: short($4564) ), { 1.e+0416 }
( significand: long($957a4ae1ebf7f3d4); exponent: short($45cf) ), { 1.e+0448 }
( significand: long($b83ed8dc0795a262); exponent: short($4639) ), { 1.e+0480 }
( significand: long($e319a0aea60e91c7); exponent: short($46a3) ), { 1.e+0512 }
( significand: long($c976758681750c17); exponent: short($4d48) ), { 1.e+1024 }
( significand: long($b2b8353b3993a7e4); exponent: short($53ed) ), { 1.e+1536 }
( significand: long($9e8b3b5dc53d5de5); exponent: short($5a92) ), { 1.e+2048 }
( significand: long($8ca554c020a1f0a6); exponent: short($6137) ), { 1.e+2560 }
( significand: long($f9895d25d88b5a8b); exponent: short($67db) ), { 1.e+3072 }
( significand: long($dd5dc8a2bf27f3f8); exponent: short($6e80) ), { 1.e+3584 }
( significand: long($c46052028a20979b); exponent: short($7525) ), { 1.e+4096 }
( significand: long($ae3511626ed559f0); exponent: short($7bca) ) { 1.e+4608 }
);
{$IFDEF WINDOWS}
previousGetExceptionObject: FunctionGetExceptionObject;
previousGetExceptionClass: FunctionGetExceptionClass;
{$ENDIF}
previousExceptionHandler: TErrorProc;
errorInvalidPointer: MemoryError;
errorOutOfMemory: MemoryError;
fpusseDefaultContext: FXContext;
primitives: Class_Array1d;
representReal: RealRepresenter;
representFloat: RealRepresenter;
representDouble: RealRepresenter;
registeredInterfacesLength: int;
registeredInterfacesEntries: InterfaceEntry_Array1d;
threadCounter: int = $007fffff;
threadLength: int;
threadEntries: ThreadEntry_Array1d;
threadOperation: Mutex;
resourcestringOverrides: AnsiString_Array1d;
resourcestringInits: PResourceStringInitList; external name '_FPC_ResStrInitTables';
resourcestringTables: PResourceStringList; external name '_FPC_ResourceStringTables';
{%endregion}
{%region OS API — thread}
{$IFDEF WINDOWS}
const
TH32CS_SNAPTHREAD = system.DWord($00000004);
{$PACKRECORDS C}
type
PThreadEntry32 = ^ThreadEntry32;
ThreadEntry32 = record
dwSize: system.DWord;
cntUsage: system.DWord;
th32ThreadId: system.DWord;
th32OwnerProcessID: system.DWord;
tpBasePri: system.LongInt;
tpDeltaPri: system.LongInt;
dwFlags: system.DWord;
end;
{$PACKRECORDS DEFAULT}
{$CALLING STDCALL}
function createToolhelp32Snapshot(dwFlags, th32ProcessID: system.DWord): system.THandle; external windows.KERNEL32 name 'CreateToolhelp32Snapshot';
function thread32First(hSnapshot: system.THandle; lpThreadEntry: PThreadEntry32): system.LongBool; external windows.KERNEL32 name 'Thread32First';
function thread32Next(hSnapshot: system.THandle; lpThreadEntry: PThreadEntry32): system.LongBool; external windows.KERNEL32 name 'Thread32Next';
function threadSetDescription(hThread: system.THandle; lpThreadDescription: system.PWideChar): system.HResult; external windows.KERNEL32 name 'SetThreadDescription';
function threadGetDescription(hThread: system.THandle; ppszThreadDescription: system.PPWideChar): system.HResult; external windows.KERNEL32 name 'GetThreadDescription';
function isDebuggerPresent(): system.LongBool; external windows.KERNEL32 name 'IsDebuggerPresent';
{$ELSE}
const
SYSCALL_NR_GETTID = long(186);
const
DT_DIR = int(4);
{$CALLING CDECL}
function threadSetDescription(__thread: unixtype.PThread_t; __description: system.PAnsiChar): int; external pthreads.LIBTHREADS name 'pthread_setname_np';
function threadGetDescription(__thread: unixtype.PThread_t; __description: system.PAnsiChar; __size: int): int; external pthreads.LIBTHREADS name 'pthread_getname_np';
function threadGetSchedParam(__thread: unixtype.PThread_t; __policy, __priority: Pint): int; external pthreads.LIBTHREADS name 'pthread_getschedparam';
function threadGetSelf(): unixtype.PThread_t; external pthreads.LIBTHREADS name 'pthread_self';
function threadTryJoin(__thread: unixtype.PThread_t; __retval: PPointer): int; external pthreads.LIBTHREADS name 'pthread_tryjoin_np';
function doSyscall(__sysnr: long): long; external name 'FPC_SYSCALL0';
{$ENDIF}
{$CALLING REGISTER}
procedure threadSleep(timeInMillis: long; timeInNanos: int);
{$IFNDEF WINDOWS}
var
callResult: int;
timeRequired: unixtype.TimeSpec;
timeRemaining: unixtype.TimeSpec;
{$ENDIF}
begin
if (timeInMillis < CoLong.MAX_VALUE) and (timeInNanos >= 500000) or (timeInMillis = 0) and (timeInNanos > 0) then inc(timeInMillis);
if timeInMillis > $fffffffe then timeInMillis := $fffffffe;
{$IFDEF WINDOWS}
windows.sleep(system.DWord(timeInMillis));
{$ELSE}
if timeInMillis = 0 then begin
system.threadSwitch();
exit;
end;
timeRequired.tv_sec := timeInMillis div 1000;
timeRequired.tv_nsec := 1000000 * (timeInMillis mod 1000);
timeRemaining.tv_sec := 0;
timeRemaining.tv_nsec := 0;
repeat
callResult := baseunix.fpNanoSleep(@timeRequired, @timeRemaining);
timeRequired := timeRemaining;
until (callResult <> -1) or (baseunix.fpGetErrNo() <> baseunix.ESysEINTR);
{$ENDIF}
end;
procedure threadSetPriority(threadId2: long; newPriority: int);
{$IFDEF WINDOWS}
var
threadHandle: system.THandle;
begin
if threadId2 < 0 then exit;
threadHandle := windows.openThread(windows.THREAD_SET_LIMITED_INFORMATION, false, system.DWord(threadId2));
if threadHandle = windows.INVALID_HANDLE_VALUE then exit;
try
case newPriority of
Thread.MIN_PRIORITY - 0:
newPriority := windows.THREAD_PRIORITY_IDLE;
Thread.LOW_PRIORITY - 1:
newPriority := windows.THREAD_PRIORITY_LOWEST;
Thread.LOW_PRIORITY - 0:
newPriority := windows.THREAD_PRIORITY_BELOW_NORMAL;
Thread.NORM_PRIORITY - 1..
Thread.NORM_PRIORITY + 1:
newPriority := windows.THREAD_PRIORITY_NORMAL;
Thread.HIGH_PRIORITY + 0:
newPriority := windows.THREAD_PRIORITY_ABOVE_NORMAL;
Thread.HIGH_PRIORITY + 1:
newPriority := windows.THREAD_PRIORITY_HIGHEST;
else
newPriority := windows.THREAD_PRIORITY_TIME_CRITICAL;
end;
windows.setThreadPriority(threadHandle, newPriority);
finally
windows.closeHandle(threadHandle);
end;
end
{$ELSE}
begin
end
{$ENDIF};
procedure threadSetDescription(threadId2: long; const newDescription: AnsiString);
{$IFDEF WINDOWS}
const
MS_VC_EXCEPTION = system.DWord($406d1388);
type
ThreadNameInfo = record
dwType: system.DWord;
szName: system.PAnsiChar;
dwThreadID: system.DWord;
dwFlags: system.DWord;
end;
var
threadHandle: system.THandle;
threadInfo: ThreadNameInfo;
begin
if threadId2 < 0 then exit;
threadHandle := windows.openThread(windows.THREAD_SET_LIMITED_INFORMATION, false, system.DWord(threadId2));
if threadHandle = windows.INVALID_HANDLE_VALUE then exit;
try
if isDebuggerPresent() then begin
with threadInfo do begin
dwType := $1000;
szName := system.PAnsiChar(newDescription);
dwThreadID := system.DWord(threadId2);
dwFlags := 0;
end;
try
windows.raiseException(MS_VC_EXCEPTION, 0, sizeof(ThreadNameInfo) div sizeof(system.DWord), @threadInfo);
except
end;
end;
threadSetDescription(threadHandle, system.PWideChar(newDescription.toUTF16()));
finally
windows.closeHandle(threadHandle);
end;
end
{$ELSE}
var
threadDescription: AnsiString;
begin
if threadId2 < 0 then exit;
if newDescription.length < $10 then begin
threadDescription := newDescription;
end else begin
threadDescription := newDescription.substring($01, $10);
end;
threadSetDescription(unixtype.PThread_t(threadId2), system.PAnsiChar(threadDescription));
end
{$ENDIF};
function threadCreate(threadFunction: CodePointer; threadArgument: Pointer; stackSize: long): boolean;
{$IFDEF WINDOWS}
var
threadIdInternal: system.DWord;
begin
threadIdInternal := 0;
system.isMultiThread := true;
result := windows.createThread(nil, system.QWord(stackSize), threadFunction, threadArgument, 0, threadIdInternal) <> 0;
end
{$ELSE}
var
threadIdInternal: system.TThreadID;
begin
threadIdInternal := 0;
system.isMultiThread := true;
result := system.beginThread(TThreadFunc(threadFunction), threadArgument, threadIdInternal, system.QWord(stackSize)) <> 0;
end
{$ENDIF};
function threadIsAlive(threadId1, threadId2: long): boolean;
{$IFDEF WINDOWS}
var
threadHandle: system.THandle;
threadExitCode: system.DWord;
begin
if threadId1 < 0 then begin
result := false;
exit;
end;
threadHandle := windows.openThread(windows.THREAD_QUERY_LIMITED_INFORMATION, false, system.DWord(threadId1));
if threadHandle = windows.INVALID_HANDLE_VALUE then begin
result := false;
exit;
end;
try
threadExitCode := 0;
result := windows.getExitCodeThread(threadHandle, @threadExitCode) and (threadExitCode = windows.STILL_ACTIVE);
finally
windows.closeHandle(threadHandle);
end;
end
{$ELSE}
var
objectType: int;
threadNameLength: int;
objectName: AnsiString;
threadNameInstance: AnsiString;
objectInfo: baseunix.PDirEnt;
directoryInfo: baseunix.PDir;
threadExitCode: Pointer;
begin
if (threadId1 and threadId2) < 0 then begin
result := false;
exit;
end;
if threadId2 >= 0 then begin
threadExitCode := nil;
result := threadTryJoin(unixtype.PThread_t(threadId2), @threadExitCode) <> 0;
exit;
end;
threadNameInstance := CoLong.toString(threadId1);
threadNameLength := threadNameInstance.length;
directoryInfo := baseunix.fpOpenDir('/proc/self/task/');
if directoryInfo = nil then begin
result := false;
exit;
end;
try
repeat
objectInfo := baseunix.fpReadDir(directoryInfo^);
if objectInfo = nil then break;
objectName := AnsiString(system.PAnsiChar(@(objectInfo^.d_name)));
objectType := objectInfo^.d_type;
if
(objectName <> '.') and (objectName <> '..') and (objectType = DT_DIR) and
(objectName.length = threadNameLength) and (&Array.compfne(objectName[1], threadNameInstance[1], 0, threadNameLength) = &Array.NOT_FOUND)
then begin
result := true;
exit;
end;
until false;
finally
baseunix.fpCloseDir(directoryInfo^);
end;
result := false;
end
{$ENDIF};
function threadGetActiveCount(): int;
{$IFDEF WINDOWS}
var
processId: system.DWord;
threadInfo: ThreadEntry32;
snapshotHandle: system.THandle;
begin
processId := windows.getCurrentProcessId();
snapshotHandle := createToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if snapshotHandle = windows.INVALID_HANDLE_VALUE then begin
result := 0;
exit;
end;
try
result := 0;
threadInfo.dwSize := sizeof(ThreadEntry32);
if thread32First(snapshotHandle, @threadInfo) then repeat
if threadInfo.th32OwnerProcessID = processId then inc(result);
until not thread32Next(snapshotHandle, @threadInfo);
finally
windows.closeHandle(snapshotHandle);
end;
end
{$ELSE}
var
objectType: int;
objectName: AnsiString;
objectInfo: baseunix.PDirEnt;
directoryInfo: baseunix.PDir;
begin
directoryInfo := baseunix.fpOpenDir('/proc/self/task/');
if directoryInfo = nil then begin
result := 0;
exit;
end;
try
result := 0;
repeat
objectInfo := baseunix.fpReadDir(directoryInfo^);
if objectInfo = nil then break;
objectName := AnsiString(system.PAnsiChar(@(objectInfo^.d_name)));
objectType := objectInfo^.d_type;
if (objectName <> '.') and (objectName <> '..') and (objectType = DT_DIR) then inc(result);
until false;
finally
baseunix.fpCloseDir(directoryInfo^);
end;
end
{$ENDIF};
function threadGetPriority(threadId2: long): int;
{$IFDEF WINDOWS}
var
threadHandle: system.THandle;
begin
if threadId2 < 0 then begin
result := Thread.UD_PRIORITY;
exit;
end;
threadHandle := windows.openThread(windows.THREAD_QUERY_LIMITED_INFORMATION, false, system.DWord(threadId2));
if threadHandle = windows.INVALID_HANDLE_VALUE then begin
result := Thread.UD_PRIORITY;
exit;
end;
try
case windows.getThreadPriority(threadHandle) of
windows.THREAD_PRIORITY_IDLE:
result := Thread.MIN_PRIORITY;
windows.THREAD_PRIORITY_LOWEST:
result := Thread.LOW_PRIORITY - 1;
windows.THREAD_PRIORITY_BELOW_NORMAL:
result := Thread.LOW_PRIORITY - 0;
windows.THREAD_PRIORITY_NORMAL:
result := Thread.NORM_PRIORITY;
windows.THREAD_PRIORITY_ABOVE_NORMAL:
result := Thread.HIGH_PRIORITY + 0;
windows.THREAD_PRIORITY_HIGHEST:
result := Thread.HIGH_PRIORITY + 1;
windows.THREAD_PRIORITY_TIME_CRITICAL:
result := Thread.MAX_PRIORITY;
else
result := Thread.UD_PRIORITY;
end;
finally
windows.closeHandle(threadHandle);
end;
end
{$ELSE}
var
policy: int;
priority: int;
begin
if threadId2 < 0 then begin
result := Thread.UD_PRIORITY;
exit;
end;
policy := 0;
priority := 0;
if threadGetSchedParam(unixtype.PThread_t(threadId2), @policy, @priority) <> 0 then begin
result := Thread.UD_PRIORITY;
exit;
end;
result := Thread.NORM_PRIORITY;
end
{$ENDIF};
function threadGetCurrentId(): long;
begin
result := {$IFDEF WINDOWS}long(windows.getCurrentThreadId()){$ELSE}doSyscall(SYSCALL_NR_GETTID){$ENDIF};
end;
{$IFNDEF WINDOWS}
function threadGetCurrentId2(): long;
begin
result := long(threadGetSelf());
end;
{$ENDIF}
function threadGetDescription(threadId2: long): AnsiString;
{$IFDEF WINDOWS}
var
threadHandle: system.THandle;
threadDescription: system.PWideChar;
begin
if threadId2 < 0 then begin
result := '';
exit;
end;
threadHandle := windows.openThread(windows.THREAD_QUERY_LIMITED_INFORMATION, false, system.DWord(threadId2));
if threadHandle = windows.INVALID_HANDLE_VALUE then begin
result := '';
exit;
end;
try
threadDescription := nil;
if windows.succeeded(threadGetDescription(threadHandle, @threadDescription)) then try
result := UnicodeString(threadDescription).toUTF8();
exit;
finally
windows.localFree(windows.HLocal((@threadDescription)^));
end;
finally
windows.closeHandle(threadHandle);
end;
result := '';
end
{$ELSE}
var
threadDescription: packed array [$00..$0f] of char;
begin
if threadId2 < 0 then begin
result := '';
exit;
end;
threadDescription[0] := #$00;
if threadGetDescription(unixtype.PThread_t(threadId2), @threadDescription, $10) = 0 then begin
result := AnsiString(system.PAnsiChar(@threadDescription));
exit;
end;
result := '';
end
{$ENDIF};
function threadEnumerateIds1(): long_Array1d;
{$IFDEF WINDOWS}
var
threadIdsLength: int;
threadIdsData: long_Array1d;
threadIdsCopy: long_Array1d;
threadInfo: ThreadEntry32;
processId: system.DWord;
snapshotHandle: system.THandle;
begin
processId := windows.getCurrentProcessId();
snapshotHandle := createToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if snapshotHandle = windows.INVALID_HANDLE_VALUE then begin
result := nil;
exit;
end;
try
threadIdsLength := 0;
threadIdsData := &Array.newLong1d($3f);
threadInfo.dwSize := sizeof(ThreadEntry32);
if thread32First(snapshotHandle, @threadInfo) then repeat
if threadInfo.th32OwnerProcessID = processId then begin
if threadIdsLength = length(threadIdsData) then begin
threadIdsCopy := &Array.newLong1d((threadIdsLength shl 1) or 1);
&Array.copyPrimitives(threadIdsData, 0, threadIdsCopy, 0, threadIdsLength);
threadIdsData := threadIdsCopy;
end;
threadIdsData[threadIdsLength] := threadInfo.th32ThreadId;
inc(threadIdsLength);
end;
until not thread32Next(snapshotHandle, @threadInfo);
if threadIdsLength < length(threadIdsData) then begin
threadIdsCopy := &Array.newLong1d(threadIdsLength);
&Array.copyPrimitives(threadIdsData, 0, threadIdsCopy, 0, threadIdsLength);
threadIdsData := threadIdsCopy;
end;
result := threadIdsData;
finally
windows.closeHandle(snapshotHandle);
end;
end
{$ELSE}
var
objectType: int;
threadIdsLength: int;
objectName: AnsiString;
objectInfo: baseunix.PDirEnt;
directoryInfo: baseunix.PDir;
threadIdsData: long_Array1d;
threadIdsCopy: long_Array1d;
begin
directoryInfo := baseunix.fpOpenDir('/proc/self/task/');
if directoryInfo = nil then begin
result := nil;
exit;
end;
try
threadIdsLength := 0;
threadIdsData := &Array.newLong1d($3f);
repeat
objectInfo := baseunix.fpReadDir(directoryInfo^);
if objectInfo = nil then break;
objectName := AnsiString(system.PAnsiChar(@(objectInfo^.d_name)));
objectType := objectInfo^.d_type;
if (objectName <> '.') and (objectName <> '..') and (objectType = DT_DIR) then begin
if threadIdsLength = length(threadIdsData) then begin
threadIdsCopy := &Array.newLong1d((threadIdsLength shl 1) or 1);
&Array.copyPrimitives(threadIdsData, 0, threadIdsCopy, 0, threadIdsLength);
threadIdsData := threadIdsCopy;
end;
threadIdsData[threadIdsLength] := CoLong.parse(objectName);
inc(threadIdsLength);
end;
until false;
if threadIdsLength < length(threadIdsData) then begin
threadIdsCopy := &Array.newLong1d(threadIdsLength);
&Array.copyPrimitives(threadIdsData, 0, threadIdsCopy, 0, threadIdsLength);
threadIdsData := threadIdsCopy;
end;
result := threadIdsData;
finally
baseunix.fpCloseDir(directoryInfo^);
end;
end
{$ENDIF};
{%endregion}
{%region OS API — mutex}
procedure mutexCreate(aMutex: system.PRTLCriticalSection);
begin
{$IFDEF WINDOWS}
windows.initializeCriticalSection(aMutex);
{$ELSE}
system.initCriticalSection(aMutex^);
{$ENDIF}
end;
procedure mutexDestroy(aMutex: system.PRTLCriticalSection);
begin
{$IFDEF WINDOWS}
windows.deleteCriticalSection(aMutex);
{$ELSE}
system.doneCriticalSection(aMutex^);
{$ENDIF}
end;
procedure mutexLock(aMutex: system.PRTLCriticalSection);
begin
{$IFDEF WINDOWS}
windows.enterCriticalSection(aMutex);
{$ELSE}
system.enterCriticalSection(aMutex^);
{$ENDIF}
end;
procedure mutexUnlock(aMutex: system.PRTLCriticalSection);
begin
{$IFDEF WINDOWS}
windows.leaveCriticalSection(aMutex);
{$ELSE}
system.leaveCriticalSection(aMutex^);
{$ENDIF}
end;
function mutexIsHold(aMutex: system.PRTLCriticalSection): boolean;
begin
result := aMutex^.{$IFDEF WINDOWS}owningThread <> 0{$ELSE}__m_owner <> nil{$ENDIF};
end;
{%endregion}
{%region OS API — event}
function eventCreate(manualReset, initialState: boolean; const name: AnsiString): long;
begin
{$IFDEF WINDOWS}
result := long(windows.createEventW(nil, manualReset, initialState, system.PWideChar(name.toUTF16())));
{$ELSE}
result := long(system.basicEventCreate(nil, manualReset, initialState, name));
{$ENDIF}
end;
procedure eventDestroy(aEvent: long);
begin
{$IFDEF WINDOWS}
windows.closeHandle(system.THandle(aEvent));
{$ELSE}
system.basicEventDestroy(PEventState((@aEvent)^));
{$ENDIF}
end;
procedure eventSetSignalled(aEvent: long);
begin
{$IFDEF WINDOWS}
windows.setEvent(system.THandle(aEvent));
{$ELSE}
system.basicEventSetEvent(PEventState((@aEvent)^));
{$ENDIF}
end;
procedure eventWaitSignalled(aEvent: long; timeInMillis: long; timeInNanos: int);
begin
if (timeInMillis < CoLong.MAX_VALUE) and (timeInNanos >= 500000) or (timeInMillis = 0) and (timeInNanos > 0) then inc(timeInMillis);
if timeInMillis > $fffffffe then timeInMillis := $fffffffe;
if timeInMillis = 0 then timeInMillis := -1;
{$IFDEF WINDOWS}
windows.waitForSingleObject(system.THandle(aEvent), system.DWord(timeInMillis));
{$ELSE}
system.basicEventWaitFor(system.Cardinal(timeInMillis), PEventState((@aEvent)^));
{$ENDIF}
end;
{%endregion}
{%region routines — fxcontext}
procedure fxcontextLoadFrom(context: PFXContext); assembler; nostackframe;
asm
db $48
{$IFDEF WINDOWS}
fxrstor [rcx+$00]
{$ELSE}
fxrstor [rdi+$00]
{$ENDIF}
end;
procedure fxcontextSaveTo(context: PFXContext); assembler; nostackframe;
asm
db $48
{$IFDEF WINDOWS}
fxsave [rcx+$00]
{$ELSE}
fxsave [rdi+$00]
{$ENDIF}
end;
{%endregion}
{%region routines — exception}
{$IFDEF WINDOWS}
function exceptionObject(errorNumber: int; const rec: windows.TExceptionRecord): TObject;
var
exceptionInstance: TObject;
begin
case errorNumber of
1,
203: exceptionInstance := errorOutOfMemory;
204: exceptionInstance := errorInvalidPointer;
200,
205..
208,
215: exceptionInstance := ArithmeticException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'arithmetic'));
202: exceptionInstance := StackOverflowError.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, '!machine-error.stack-overflow'));
211: exceptionInstance := AbstractMethodError.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, '!error.abstract-method'));
216: exceptionInstance := NullPointerException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'null-pointer'));
219: exceptionInstance := ClassCastException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'class-cast'));
229: exceptionInstance := SafecallException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'safecall'));
else exceptionInstance := previousGetExceptionObject(errorNumber, rec);
end;
if exceptionInstance = nil then begin
exceptionInstance := NullPointerException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'null-pointer'));
end;
result := exceptionInstance;
end;
function exceptionClass(errorNumber: int): TClass;
var
exceptionType: TClass;
begin
case errorNumber of
1,
203: exceptionType := OutOfMemoryError;
204: exceptionType := InvalidPointerError;
200,
205..
208,
215: exceptionType := ArithmeticException;
202: exceptionType := StackOverflowError;
211: exceptionType := AbstractMethodError;
216: exceptionType := NullPointerException;
219: exceptionType := ClassCastException;
229: exceptionType := SafecallException;
else exceptionType := previousGetExceptionClass(errorNumber);
end;
if exceptionType = nil then begin
exceptionType := NullPointerException;
end;
result := exceptionType;
end;
{$ENDIF}
procedure exceptionHandler(errorNumber: int; address: CodePointer; frame: Pointer);
var
exceptionInstance: TObject;
begin
case errorNumber of
1,
203: exceptionInstance := errorOutOfMemory;
204: exceptionInstance := errorInvalidPointer;
200,
205..
208,
215: exceptionInstance := ArithmeticException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'arithmetic'));
202: exceptionInstance := StackOverflowError.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, '!machine-error.stack-overflow'));
211: exceptionInstance := AbstractMethodError.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, '!error.abstract-method'));
216: exceptionInstance := NullPointerException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'null-pointer'));
219: exceptionInstance := ClassCastException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'class-cast'));
229: exceptionInstance := SafecallException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'safecall'));
else
exceptionInstance := nil;
previousExceptionHandler(errorNumber, address, frame);
end;
if exceptionInstance = nil then begin
exceptionInstance := NullPointerException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'null-pointer'));
end;
raise exceptionInstance at address, frame;
end;
procedure exceptionInitialize();
begin
{$IFDEF WINDOWS}
previousGetExceptionObject := FunctionGetExceptionObject(exceptObjProc);
previousGetExceptionClass := FunctionGetExceptionClass(exceptClsProc);
{$ENDIF}
previousExceptionHandler := errorProc;
errorInvalidPointer := InvalidPointerError.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, '!error.invalid-pointer'));
errorInvalidPointer.freeDisallow();
errorOutOfMemory := OutOfMemoryError.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, '!machine-error.out-of-memory'));
errorOutOfMemory.freeDisallow();
{$IFDEF WINDOWS}
exceptObjProc := @exceptionObject;
exceptClsProc := @exceptionClass;
{$ENDIF}
errorProc := @exceptionHandler;
end;
procedure exceptionFinalize();
begin
{$IFDEF WINDOWS}
exceptObjProc := previousGetExceptionObject;
exceptClsProc := previousGetExceptionClass;
{$ENDIF}
errorProc := previousExceptionHandler;
errorInvalidPointer.freeAllow();
errorInvalidPointer.free();
errorOutOfMemory.freeAllow();
errorOutOfMemory.free();
end;
{%endregion}
{%region routines — thread}
procedure threadInitialize();
begin
threadLength := 0;
threadEntries := ThreadEntry_Array1d(&Array.newTObject1d($3f));
threadOperation := Mutex.create();
end;
procedure threadFinalize();
var
idx: int;
currEntry: ThreadEntry;
nextEntry: ThreadEntry;
begin
threadOperation.beginSynchronized();
try
for idx := length(threadEntries) - 1 downto 0 do begin
currEntry := threadEntries[idx];
threadEntries[idx] := nil;
while currEntry <> nil do begin
nextEntry := currEntry.next;
currEntry.free();
currEntry := nextEntry;
end;
end;
threadEntries := nil;
threadLength := 0;
finally
threadOperation.endSynchronized();
end;
threadOperation.free();
threadOperation := nil;
end;
procedure threadClean();
var
idx: int;
prevEntry: ThreadEntry;
currEntry: ThreadEntry;
nextEntry: ThreadEntry;
begin
threadOperation.beginSynchronized();
try
for idx := length(threadEntries) - 1 downto 0 do begin
prevEntry := nil;
currEntry := threadEntries[idx];
while currEntry <> nil do begin
if not threadIsAlive(currEntry.threadId1, currEntry.threadId2) then begin
nextEntry := currEntry.next;
currEntry.free();
if prevEntry = nil then begin
threadEntries[idx] := nextEntry;
end else begin
prevEntry.next := nextEntry;
end;
dec(threadLength);
currEntry := nextEntry;
continue;
end;
prevEntry := currEntry;
currEntry := currEntry.next;
end;
end;
finally
threadOperation.endSynchronized();
end;
end;
procedure threadRehash();
var
oldCap: int;
oldIdx: int;
newCap: int;
newIdx: int;
oldEntry: ThreadEntry;
newEntry: ThreadEntry;
oldTable: ThreadEntry_Array1d;
newTable: ThreadEntry_Array1d;
begin
oldTable := threadEntries;
oldCap := length(oldTable);
newCap := (oldCap shl 1) or 1;
if newCap < 0 then newCap := CoInt.MAX_VALUE;
newTable := ThreadEntry_Array1d(&Array.newTObject1d(newCap));
for oldIdx := oldCap - 1 downto 0 do begin
oldEntry := oldTable[oldIdx];
while oldEntry <> nil do begin
newIdx := int((oldEntry.threadId1 and CoLong.MAX_VALUE) mod newCap);
newEntry := oldEntry;
oldEntry := oldEntry.next;
newEntry.next := newTable[newIdx];
newTable[newIdx] := newEntry;
end;
end;
threadEntries := newTable;
end;
procedure threadAdd(threadInstance: Thread);
var
len: int;
cap: int;
idx: int;
threadId1: long;
currEntry: ThreadEntry;
begin
threadId1 := threadInstance.fldThreadId1;
threadOperation.beginSynchronized();
try
cap := length(threadEntries);
idx := int((threadId1 and CoLong.MAX_VALUE) mod cap);
currEntry := threadEntries[idx];
while currEntry <> nil do begin
if currEntry.threadId1 = threadId1 then begin
currEntry.threadOld := currEntry.threadRef;
currEntry.threadRef := threadInstance;
exit;
end;
currEntry := currEntry.next;
end;
len := threadLength + 1;
if len > ((cap shl 1) or 1) then begin
threadRehash();
idx := int((threadId1 and CoLong.MAX_VALUE) mod length(threadEntries));
end;
threadEntries[idx] := ThreadEntry.create(threadId1, threadInstance.fldThreadId2, threadInstance, threadEntries[idx]);
threadLength := len;
finally
threadOperation.endSynchronized();
end;
end;
procedure threadDecrementEnum(threadInstance: Thread);
begin
threadOperation.beginSynchronized();
try
dec(threadInstance.fldEnumerated);
finally
threadOperation.endSynchronized();
end;
end;
procedure threadRemove(threadInstance: Thread; needDecrementEnum: boolean = false);
var
idx: int;
threadId1: long;
prevEntry: ThreadEntry;
currEntry: ThreadEntry;
nextEntry: ThreadEntry;
begin
threadId1 := threadInstance.fldThreadId1;
threadOperation.beginSynchronized();
try
if needDecrementEnum then dec(threadInstance.fldEnumerated);
idx := int((threadId1 and CoLong.MAX_VALUE) mod length(threadEntries));
prevEntry := nil;
currEntry := threadEntries[idx];
while currEntry <> nil do begin
if currEntry.threadId1 = threadId1 then begin
nextEntry := currEntry.next;
currEntry.free();
if prevEntry = nil then begin
threadEntries[idx] := nextEntry;
end else begin
prevEntry.next := nextEntry;
end;
dec(threadLength);
exit;
end;
prevEntry := currEntry;
currEntry := currEntry.next;
end;
threadInstance.freeIfNecessary();
finally
threadOperation.endSynchronized();
end;
end;
function threadGetEvent(threadId1: long): long;
var
idx: int;
currEntry: ThreadEntry;
begin
threadOperation.beginSynchronized();
try
idx := int((threadId1 and CoLong.MAX_VALUE) mod length(threadEntries));
currEntry := threadEntries[idx];
while currEntry <> nil do begin
if currEntry.threadId1 = threadId1 then begin
result := currEntry.event;
exit;
end;
currEntry := currEntry.next;
end;
finally
threadOperation.endSynchronized();
end;
result := 0;
end;
function threadGet(threadId1: long; needIncrementEnum: boolean = false): Thread;
var
len: int;
cap: int;
idx: int;
currEntry: ThreadEntry;
threadInstance: Thread;
begin
threadOperation.beginSynchronized();
try
cap := length(threadEntries);
idx := int((threadId1 and CoLong.MAX_VALUE) mod cap);
currEntry := threadEntries[idx];
while currEntry <> nil do begin
if currEntry.threadId1 = threadId1 then begin
threadInstance := currEntry.threadRef;
if needIncrementEnum then inc(threadInstance.fldEnumerated);
result := threadInstance;
exit;
end;
currEntry := currEntry.next;
end;
len := threadLength + 1;
if len > ((cap shl 1) or 1) then begin
threadRehash();
idx := int((threadId1 and CoLong.MAX_VALUE) mod length(threadEntries));
end;
threadInstance := Thread.create(threadId1, -1);
if needIncrementEnum then inc(threadInstance.fldEnumerated);
threadEntries[idx] := ThreadEntry.create(threadId1, -1, threadInstance, threadEntries[idx]);
threadLength := len;
result := threadInstance;
finally
threadOperation.endSynchronized();
end;
end;
function threadFunction(threadInstance: Thread): {$IFDEF WINDOWS}int; stdcall{$ELSE}long; cdecl{$ENDIF};
var
threadId1: long;
threadId2: long;
threadTarget: Runnable;
begin
try
fxcontextLoadFrom(@fpusseDefaultContext);
threadId1 := threadGetCurrentId();
threadId2 := {$IFDEF WINDOWS}threadId1{$ELSE}threadGetCurrentId2(){$ENDIF};
threadInstance.fldThreadId1 := threadId1;
threadInstance.fldThreadId2 := threadId2;
threadAdd(threadInstance);
threadInstance.fldCreated := false;
try
try
threadSetPriority(threadId2, threadInstance.fldPriority);
threadSetDescription(threadId2, threadInstance.fldDescription);
threadTarget := threadInstance.fldTarget;
if threadTarget = nil then threadTarget := threadInstance;
threadTarget.run();
finally
threadInstance.notifyJoined();
end;
except
on exception: Throwable do begin
exception.printStackTrace();
end;
on exception: TObject do begin
if isConsole then begin
writeln(system.errOutput, exception.toString(){$IFDEF WINDOWS}.toUTF16(){$ENDIF});
end;
end;
else begin
if isConsole then begin
writeln(system.errOutput, AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, '!error.unknown'){$IFDEF WINDOWS}.toUTF16(){$ENDIF});
end;
end;
end;
threadRemove(threadInstance);
threadClean();
except
if isConsole then begin
writeln(system.errOutput, AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, '!error.thread-registration'){$IFDEF WINDOWS}.toUTF16(){$ENDIF});
end;
end;
result := 0;
end;
{%endregion}
{%region routines — interface}
procedure interfaceInitialize();
begin
registeredInterfacesLength := 0;
registeredInterfacesEntries := InterfaceEntry_Array1d(&Array.newTObject1d($3f));
end;
procedure interfaceFinalize();
var
idx: int;
currEntry: InterfaceEntry;
nextEntry: InterfaceEntry;
begin
for idx := length(registeredInterfacesEntries) - 1 downto 0 do begin
currEntry := registeredInterfacesEntries[idx];
registeredInterfacesEntries[idx] := nil;
while currEntry <> nil do begin
nextEntry := currEntry.next;
currEntry.free();
currEntry := nextEntry;
end;
end;
registeredInterfacesEntries := nil;
registeredInterfacesLength := 0;
end;
{%endregion}
{%region routines — interlocked}
function interlockedIncrementInt(field: Pint): int; assembler; nostackframe;
asm
mov eax, $00000001
{$IFDEF WINDOWS}
lock xadd dword [rcx+$00], eax
{$ELSE}
lock xadd dword [rdi+$00], eax
{$ENDIF}
inc eax
end;
function interlockedDecrementInt(field: Pint): int; assembler; nostackframe;
asm
mov eax, $ffffffff
{$IFDEF WINDOWS}
lock xadd dword [rcx+$00], eax
{$ELSE}
lock xadd dword [rdi+$00], eax
{$ENDIF}
dec eax
end;
{%endregion}
{%region routines — newInt2}
function newInt2(value0, value1: int): int2;
begin
result[0] := value0;
result[1] := value1;
end;
function newInt2Array1d(length: int): int2_Array1d;
begin
result := nil;
setLength(result, length);
end;
{%endregion}
{%region routines — GUID}
function guidTryParse(const str: ShortString; out guid: system.TGuid): boolean;
var
success: boolean;
idx: int;
procedure skipChar(chr: char);
begin
if str[idx] <> chr then begin
success := false;
end;
inc(idx);
end;
function readChar(): int;
var
chr: char;
begin
chr := str[idx];
inc(idx);
case chr of
'0'..'9':
result := int(chr) - int('0');
'a'..'f':
result := int(chr) - (int('a') - $0a);
'A'..'F':
result := int(chr) - (int('A') - $0a);
else
success := false;
result := 0;
end;
end;
begin
if length(str) <> 38 then begin
guid.data1 := 0;
guid.data2 := 0;
guid.data3 := 0;
long(guid.data4) := 0;
result := false;
exit;
end;
success := true;
idx := 1;
skipChar('{');
guid.data1 := system.DWord(
(readChar() shl $1c) or (readChar() shl $18) or (readChar() shl $14) or (readChar() shl $10) or
(readChar() shl $0c) or (readChar() shl $08) or (readChar() shl $04) or readChar()
);
skipChar('-');
guid.data2 := system.Word((readChar() shl $0c) or (readChar() shl $08) or (readChar() shl $04) or readChar());
skipChar('-');
guid.data3 := system.Word((readChar() shl $0c) or (readChar() shl $08) or (readChar() shl $04) or readChar());
skipChar('-');
guid.data4[0] := system.Byte((readChar() shl 4) or readChar());
guid.data4[1] := system.Byte((readChar() shl 4) or readChar());
skipChar('-');
guid.data4[2] := system.Byte((readChar() shl 4) or readChar());
guid.data4[3] := system.Byte((readChar() shl 4) or readChar());
guid.data4[4] := system.Byte((readChar() shl 4) or readChar());
guid.data4[5] := system.Byte((readChar() shl 4) or readChar());
guid.data4[6] := system.Byte((readChar() shl 4) or readChar());
guid.data4[7] := system.Byte((readChar() shl 4) or readChar());
skipChar('}');
result := success;
end;
function guidToString(const guid: system.TGuid): ShortString;
const
HEX: array [$00..$0f] of char = ( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' );
var
cnt: int;
idx: int;
val: long;
str: ShortString;
procedure writeChar();
begin
str[idx] := HEX[int((val shr (cnt shl 2)) and $0f)];
inc(idx);
end;
begin
str := '{00000000-0000-0000-0000-000000000000}';
val := guid.data1;
idx := 2;
for cnt := $07 downto $00 do writeChar();
val := guid.data2;
inc(idx);
for cnt := $03 downto $00 do writeChar();
val := guid.data3;
inc(idx);
for cnt := $03 downto $00 do writeChar();
val := CoLong.byteSwap(long(guid.data4));
inc(idx);
for cnt := $0f downto $0c do writeChar();
{ val := val; }
inc(idx);
for cnt := $0b downto $00 do writeChar();
result := str;
end;
{%endregion}
{%region routines — resourcestring}
function resourcestringOverride(const name, value: AnsiString; hash: int; arg: Pointer): AnsiString;
var
idx: int;
pos: int;
str: AnsiString;
ovr: AnsiString;
begin
str := name.toLowerCase();
for idx := 0 to system.length(resourcestringOverrides) - 1 do begin
ovr := resourcestringOverrides[idx];
pos := ovr.indexOf('=');
if (pos > 0) and (str = ovr.substring(1, pos).toLowerCase()) then begin
result := ovr.substring(1 + pos);
exit;
end;
end;
result := value;
end;
{%endregion}
{%region &Object}
constructor &Object.create();
begin
inherited create();
end;
destructor &Object.destroy;
begin
inherited destroy;
end;
procedure &Object.afterConstruction();
begin
end;
procedure &Object.beforeDestruction();
begin
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() + '@' + CoLong.toHexString(getHashCode());
end;
function &Object.queryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid: system.TGuid; out obj): int; {$IFDEF WINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
begin
if &Array.compfne(IObjectInstance, iid, 3, 2) = &Array.NOT_FOUND then begin
TObject(obj) := self;
result := system.S_OK;
exit;
end;
if getInterface(guidToString(iid), obj) then begin
result := system.S_OK;
exit;
end;
result := system.E_NOINTERFACE;
end;
function &Object._addref(): int; {$IFDEF WINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
begin
result := -1;
end;
function &Object._release(): int; {$IFDEF WINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
begin
result := -1;
end;
{%endregion}
{%region RefCountObject}
class function RefCountObject.newInstance(): TObject;
begin
result := inherited newInstance();
if result <> nil then begin
RefCountObject(result).fldRefCount := 1;
end;
end;
procedure RefCountObject.afterConstruction(); assembler; nostackframe;
asm
{$IFDEF WINDOWS}
lock dec dword [rcx+offset fldRefCount]
{$ELSE}
lock dec dword [rdi+offset fldRefCount]
{$ENDIF}
end;
procedure RefCountObject.beforeDestruction();
begin
if fldRefCount <> 0 then begin
raise InvalidPointerError.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, '!error.invalid-ref-count'));
end;
end;
function RefCountObject._addref(): int; {$IFDEF WINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
begin
result := interlockedIncrementInt(@fldRefCount);
end;
function RefCountObject._release(): int; {$IFDEF WINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
begin
result := interlockedDecrementInt(@fldRefCount);
if result = 0 then destroy;
end;
{%endregion}
{%region DynamicObject}
constructor DynamicObject.create();
begin
inherited create();
end;
{%endregion}
{%region CoBoolean}
constructor CoBoolean.create(const value: boolean);
begin
inherited create();
if value then begin
fldValue := -1;
exit;
end;
fldValue := 0;
end;
procedure CoBoolean.writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 1);
dst[offset] := byte(-fldValue);
end;
procedure CoBoolean.writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 1);
dst[offset] := byte(-fldValue);
end;
function CoBoolean.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is CoBoolean) and (CoBoolean(anot).fldValue = fldValue);
end;
function CoBoolean.getHashCode(): long;
begin
if fldValue <> 0 then begin
result := 1231;
exit;
end;
result := 1237;
end;
function CoBoolean.toString(): AnsiString;
begin
if fldValue <> 0 then begin
result := 'true';
exit;
end;
result := 'false';
end;
function CoBoolean.getSize(): int;
begin
result := sizeof(fldValue);
end;
function CoBoolean.getType(): int;
begin
result := Lang.TYPE_BOOLEAN;
end;
function CoBoolean.isNaN(): boolean;
begin
result := false;
end;
function CoBoolean.isInfinite(): boolean;
begin
result := false;
end;
function CoBoolean.asBoolean(): boolean;
begin
result := fldValue <> 0;
end;
function CoBoolean.asInt(): int;
begin
result := fldValue;
end;
function CoBoolean.asLong(): long;
begin
result := fldValue;
end;
function CoBoolean.asFloat(): float;
begin
result := CoInt.toFloat(fldValue);
end;
function CoBoolean.asDouble(): double;
begin
result := CoInt.toDouble(fldValue);
end;
function CoBoolean.asReal(): real;
begin
result := CoInt.toReal(fldValue);
end;
function CoBoolean.asAnsiString(): AnsiString;
begin
if fldValue <> 0 then begin
result := 'true';
exit;
end;
result := 'false';
end;
function CoBoolean.asUnicodeString(): UnicodeString;
begin
if fldValue <> 0 then begin
result := 'true';
exit;
end;
result := 'false';
end;
function CoBoolean.asObject(): TObject;
begin
result := self;
end;
function CoBoolean.asSimple(): ISimple;
begin
result := self;
end;
{%endregion}
{%region CoChar}
class function CoChar.isDigit(character: char): boolean;
begin
result := (character >= '0') and (character <= '9');
end;
class function CoChar.isLowerCase(character: char): boolean;
begin
result := (character >= 'a') and (character <= 'z');
end;
class function CoChar.isUpperCase(character: char): boolean;
begin
result := (character >= 'A') and (character <= 'Z');
end;
class function CoChar.toLowerCase(character: char): char;
begin
if (character >= 'A') and (character <= 'Z') then begin
result := char(int(character) + $20);
exit;
end;
result := character;
end;
class function CoChar.toUpperCase(character: char): char;
begin
if (character >= 'a') and (character <= 'z') then begin
result := char(int(character) - $20);
exit;
end;
result := character;
end;
class function CoChar.toChar(digit: int): char;
begin
if (digit >= $00) and (digit < $0a) then begin
result := char(digit + int('0'));
exit;
end;
if (digit >= $0a) and (digit < CoChar.MAX_RADIX) then begin
result := char(digit + (int('a') - $0a));
exit;
end;
result := '?';
end;
class function CoChar.toDigit(character: char; radix: int): int;
var
value: int;
begin
value := -1;
if (radix >= CoChar.MIN_RADIX) and (radix <= CoChar.MAX_RADIX) then begin
if (character >= '0') and (character <= '9') then begin
value := int(character) - int('0');
end else
if (character >= 'A') and (character <= 'Z') or (character >= 'a') and (character <= 'z') then begin
value := (int(character) and $1f) + 9;
end;
end;
if value >= radix then value := -1;
result := value;
end;
constructor CoChar.create(const value: char);
begin
inherited create();
fldValue := value;
end;
procedure CoChar.writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 1);
dst[offset] := byte(fldValue);
end;
procedure CoChar.writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 1);
dst[offset] := byte(fldValue);
end;
function CoChar.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is CoChar) and (CoChar(anot).fldValue = fldValue);
end;
function CoChar.getHashCode(): long;
begin
result := long(fldValue);
end;
function CoChar.toString(): AnsiString;
begin
result := fldValue;
end;
function CoChar.getSize(): int;
begin
result := sizeof(fldValue);
end;
function CoChar.getType(): int;
begin
result := Lang.TYPE_CHAR;
end;
function CoChar.isNaN(): boolean;
begin
result := false;
end;
function CoChar.isInfinite(): boolean;
begin
result := false;
end;
function CoChar.asBoolean(): boolean;
begin
result := fldValue <> #$00;
end;
function CoChar.asInt(): int;
begin
result := int(fldValue);
end;
function CoChar.asLong(): long;
begin
result := long(fldValue);
end;
function CoChar.asFloat(): float;
begin
result := CoInt.toFloat(int(fldValue));
end;
function CoChar.asDouble(): double;
begin
result := CoInt.toDouble(int(fldValue));
end;
function CoChar.asReal(): real;
begin
result := CoInt.toReal(int(fldValue));
end;
function CoChar.asAnsiString(): AnsiString;
begin
result := fldValue;
end;
function CoChar.asUnicodeString(): UnicodeString;
begin
result := uchar(fldValue);
end;
function CoChar.asObject(): TObject;
begin
result := self;
end;
function CoChar.asSimple(): ISimple;
begin
result := self;
end;
{%endregion}
{%region CoUChar}
class function CoUChar.isDigit(character: uchar): boolean;
begin
result := BasicLatin.isDigit(character) or Locale.getInstance().isDigit(character);
end;
class function CoUChar.isLowerCase(character: uchar): boolean;
begin
result := BasicLatin.isLowerCase(character) or Locale.getInstance().isLowerCase(character);
end;
class function CoUChar.isUpperCase(character: uchar): boolean;
begin
result := BasicLatin.isUpperCase(character) or Locale.getInstance().isUpperCase(character);
end;
class function CoUChar.toLowerCase(character: uchar): uchar;
begin
if character < #$0100 then begin
result := BasicLatin.toLowerCase(character);
exit;
end;
result := Locale.getInstance().toLowerCase(character);
end;
class function CoUChar.toUpperCase(character: uchar): uchar;
begin
if character < #$0100 then begin
result := BasicLatin.toUpperCase(character);
exit;
end;
result := Locale.getInstance().toUpperCase(character);
end;
class function CoUChar.toChar(digit: int): uchar;
begin
if (digit >= $00) and (digit < $0a) then begin
result := uchar(digit + int('0'));
exit;
end;
if (digit >= $0a) and (digit < CoUChar.MAX_RADIX) then begin
result := uchar(digit + (int('a') - $0a));
exit;
end;
result := '?';
end;
class function CoUChar.toDigit(character: uchar; radix: int): int;
var
value: int;
begin
value := -1;
if (radix >= CoUChar.MIN_RADIX) and (radix <= CoUChar.MAX_RADIX) then begin
if (character >= '0') and (character <= '9') then begin
value := int(character) - int('0');
end else
if (character >= 'A') and (character <= 'Z') or (character >= 'a') and (character <= 'z') then begin
value := (int(character) and $1f) + 9;
end;
end;
if value >= radix then value := -1;
result := value;
end;
constructor CoUChar.create(const value: uchar);
begin
inherited create();
fldValue := value;
end;
procedure CoUChar.writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 2);
short((@(dst[offset]))^) := CoShort.byteSwap(short(fldValue));
end;
procedure CoUChar.writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 2);
uchar((@(dst[offset]))^) := fldValue;
end;
function CoUChar.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is CoUChar) and (CoUChar(anot).fldValue = fldValue);
end;
function CoUChar.getHashCode(): long;
begin
result := long(fldValue);
end;
function CoUChar.toString(): AnsiString;
begin
result := UnicodeString(fldValue).toUTF8();
end;
function CoUChar.getSize(): int;
begin
result := sizeof(fldValue);
end;
function CoUChar.getType(): int;
begin
result := Lang.TYPE_UCHAR;
end;
function CoUChar.isNaN(): boolean;
begin
result := false;
end;
function CoUChar.isInfinite(): boolean;
begin
result := false;
end;
function CoUChar.asBoolean(): boolean;
begin
result := fldValue <> #$0000;
end;
function CoUChar.asInt(): int;
begin
result := int(fldValue);
end;
function CoUChar.asLong(): long;
begin
result := long(fldValue);
end;
function CoUChar.asFloat(): float;
begin
result := CoInt.toFloat(int(fldValue));
end;
function CoUChar.asDouble(): double;
begin
result := CoInt.toDouble(int(fldValue));
end;
function CoUChar.asReal(): real;
begin
result := CoInt.toReal(int(fldValue));
end;
function CoUChar.asAnsiString(): AnsiString;
begin
result := UnicodeString(fldValue).toUTF8();
end;
function CoUChar.asUnicodeString(): UnicodeString;
begin
result := fldValue;
end;
function CoUChar.asObject(): TObject;
begin
result := self;
end;
function CoUChar.asSimple(): ISimple;
begin
result := self;
end;
{%endregion}
{%region CoByte}
class function CoByte.parse(const str: AnsiString; radix: int): byte;
var
value: int;
begin
value := CoInt.parse(str, radix);
if (value < MIN_VALUE) or (value > MAX_VALUE) then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
result := byte(value);
end;
class function CoByte.parseUnsigned(const str: AnsiString; radix: int): byte;
var
value: int;
begin
value := CoInt.parseUnsigned(str, radix);
if (value and $ffffff00) <> 0 then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
result := byte(value);
end;
constructor CoByte.create(const value: byte);
begin
inherited create();
fldValue := value;
end;
procedure CoByte.writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 1);
dst[offset] := fldValue;
end;
procedure CoByte.writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 1);
dst[offset] := fldValue;
end;
function CoByte.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is CoByte) and (CoByte(anot).fldValue = fldValue);
end;
function CoByte.getHashCode(): long;
begin
result := fldValue;
end;
function CoByte.toString(): AnsiString;
begin
result := CoInt.toString(fldValue);
end;
function CoByte.getSize(): int;
begin
result := sizeof(fldValue);
end;
function CoByte.getType(): int;
begin
result := Lang.TYPE_BYTE;
end;
function CoByte.isNaN(): boolean;
begin
result := false;
end;
function CoByte.isInfinite(): boolean;
begin
result := false;
end;
function CoByte.asBoolean(): boolean;
begin
result := fldValue <> 0;
end;
function CoByte.asInt(): int;
begin
result := fldValue;
end;
function CoByte.asLong(): long;
begin
result := fldValue;
end;
function CoByte.asFloat(): float;
begin
result := CoInt.toFloat(fldValue);
end;
function CoByte.asDouble(): double;
begin
result := CoInt.toDouble(fldValue);
end;
function CoByte.asReal(): real;
begin
result := CoInt.toReal(fldValue);
end;
function CoByte.asAnsiString(): AnsiString;
begin
result := CoInt.toString(fldValue);
end;
function CoByte.asUnicodeString(): UnicodeString;
begin
result := CoInt.toString(fldValue).toUTF16();
end;
function CoByte.asObject(): TObject;
begin
result := self;
end;
function CoByte.asSimple(): ISimple;
begin
result := self;
end;
{%endregion}
{%region CoShort}
class function CoShort.parse(const str: AnsiString; radix: int): short;
var
value: int;
begin
value := CoInt.parse(str, radix);
if (value < MIN_VALUE) or (value > MAX_VALUE) then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
result := short(value);
end;
class function CoShort.parseUnsigned(const str: AnsiString; radix: int): short;
var
value: int;
begin
value := CoInt.parseUnsigned(str, radix);
if (value and $ffff0000) <> 0 then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
result := short(value);
end;
class function CoShort.byteSwap(value: short): short; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
mov ax, cx
{$ELSE}
mov ax, di
{$ENDIF}
xchg al, ah
movsx eax, ax
end;
constructor CoShort.create(const value: short);
begin
inherited create();
fldValue := value;
end;
procedure CoShort.writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 2);
short((@(dst[offset]))^) := byteSwap(fldValue);
end;
procedure CoShort.writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 2);
short((@(dst[offset]))^) := fldValue;
end;
function CoShort.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is CoShort) and (CoShort(anot).fldValue = fldValue);
end;
function CoShort.getHashCode(): long;
begin
result := fldValue;
end;
function CoShort.toString(): AnsiString;
begin
result := CoInt.toString(fldValue);
end;
function CoShort.getSize(): int;
begin
result := sizeof(fldValue);
end;
function CoShort.getType(): int;
begin
result := Lang.TYPE_SHORT;
end;
function CoShort.isNaN(): boolean;
begin
result := false;
end;
function CoShort.isInfinite(): boolean;
begin
result := false;
end;
function CoShort.asBoolean(): boolean;
begin
result := fldValue <> 0;
end;
function CoShort.asInt(): int;
begin
result := fldValue;
end;
function CoShort.asLong(): long;
begin
result := fldValue;
end;
function CoShort.asFloat(): float;
begin
result := CoInt.toFloat(fldValue);
end;
function CoShort.asDouble(): double;
begin
result := CoInt.toDouble(fldValue);
end;
function CoShort.asReal(): real;
begin
result := CoInt.toReal(fldValue);
end;
function CoShort.asAnsiString(): AnsiString;
begin
result := CoInt.toString(fldValue);
end;
function CoShort.asUnicodeString(): UnicodeString;
begin
result := CoInt.toString(fldValue).toUTF16();
end;
function CoShort.asObject(): TObject;
begin
result := self;
end;
function CoShort.asSimple(): ISimple;
begin
result := self;
end;
{%endregion}
{%region CoInt}
class function CoInt.toUnsignedStringByShift(uvalue: int; shift: int): AnsiString;
var
idx: int;
len: int;
msk: int;
buf: char_Array1d;
begin
idx := 32;
len := idx;
msk := (1 shl shift) - 1;
buf := &Array.newChar1d(len);
repeat
dec(idx);
buf[idx] := CoChar.toChar(uvalue and msk);
uvalue := uvalue shr shift;
until uvalue = 0;
result := AnsiString.create(buf, idx, len - idx);
end;
class function CoInt.parse(const str: AnsiString; radix: int): int;
var
negative: boolean;
idx: int;
len: int;
limit: int;
digit: int;
mulmin: int;
parsed: int;
begin
len := str.length;
if len <= 0 then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
if (radix < CoChar.MIN_RADIX) or (radix > CoChar.MAX_RADIX) then begin
raise NumberFormatException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format.radix'), [ CoInt.create(radix) ]));
end;
parsed := 0;
idx := 0;
if str[1] = '-' then begin
inc(idx);
negative := true;
limit := -$80000000;
end else begin
negative := false;
limit := -$7fffffff;
end;
if idx < len then begin
digit := CoChar.toDigit(str[idx + 1], radix);
if digit < 0 then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
parsed := -digit;
inc(idx);
end;
mulmin := limit div radix;
while idx < len do begin
digit := CoChar.toDigit(str[idx + 1], radix);
if (digit < 0) or (parsed < mulmin) then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
parsed := parsed * radix;
if parsed < limit + digit then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
parsed := parsed - digit;
inc(idx);
end;
if negative then begin
if idx < 2 then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
result := parsed;
exit;
end;
result := -parsed;
end;
class function CoInt.parseUnsigned(const str: AnsiString; radix: int): int;
var
idx: int;
len: int;
digit: int;
mulmin: int;
parsed: int;
begin
len := str.length;
if len <= 0 then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
if (radix < CoChar.MIN_RADIX) or (radix > CoChar.MAX_RADIX) then begin
raise NumberFormatException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format.radix'), [ CoInt.create(radix) ]));
end;
parsed := CoChar.toDigit(str[1], radix);
if parsed < 0 then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
mulmin := divUnsigned(int($ffffffff), radix);
for idx := 1 to len - 1 do begin
digit := CoChar.toDigit(str[idx + 1], radix);
if (digit < 0) or (cmpUnsigned(parsed, mulmin) > 0) then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
parsed := parsed * radix;
if cmpUnsigned(parsed, $ffffffff - digit) > 0 then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
parsed := parsed + digit;
end;
result := parsed;
end;
class function CoInt.byteSwap(value: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
mov eax, ecx
{$ELSE}
mov eax, edi
{$ENDIF}
bswap eax
end;
class function CoInt.bound(value, minimum, maximum: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cmp ecx, edx
jge @00
mov eax, edx
ret
@00: cmp ecx, r8d
jle @01
mov eax, r8d
ret
@01: mov eax, ecx
{$ELSE}
cmp edi, esi
jge @00
mov eax, esi
ret
@00: cmp edi, edx
jle @01
mov eax, edx
ret
@01: mov eax, edi
{$ENDIF}
end;
class function CoInt.max(value1, value2: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cmp ecx, edx
jl @00
mov eax, ecx
ret
@00: mov eax, edx
{$ELSE}
cmp edi, esi
jl @00
mov eax, edi
ret
@00: mov eax, esi
{$ENDIF}
end;
class function CoInt.min(value1, value2: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cmp ecx, edx
jg @00
mov eax, ecx
ret
@00: mov eax, edx
{$ELSE}
cmp edi, esi
jg @00
mov eax, edi
ret
@00: mov eax, esi
{$ENDIF}
end;
class function CoInt.sar(value: int; bits: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
mov eax, ecx
mov ecx, edx
{$ELSE}
mov eax, edi
mov ecx, esi
{$ENDIF}
sar eax, cl
end;
class function CoInt.rol(value: int; bits: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
mov eax, ecx
mov ecx, edx
{$ELSE}
mov eax, edi
mov ecx, esi
{$ENDIF}
rol eax, cl
end;
class function CoInt.boundUnsigned(uvalue, uminimum, umaximum: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cmp ecx, edx
jae @00
mov eax, edx
ret
@00: cmp ecx, r8d
jbe @01
mov eax, r8d
ret
@01: mov eax, ecx
{$ELSE}
cmp edi, esi
jae @00
mov eax, esi
ret
@00: cmp edi, edx
jbe @01
mov eax, edx
ret
@01: mov eax, edi
{$ENDIF}
end;
class function CoInt.cmpUnsigned(uvalue1, uvalue2: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cmp ecx, edx
{$ELSE}
cmp edi, esi
{$ENDIF}
jb @lt
je @eq
@gt: mov eax, $00000001
ret
@lt: mov eax, $ffffffff
ret
@eq: xor eax, eax
end;
class function CoInt.divUnsigned(uvalue1, uvalue2: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
mov eax, ecx
mov ecx, edx
{$ELSE}
mov eax, edi
mov ecx, esi
{$ENDIF}
xor edx, edx
div ecx
end;
class function CoInt.remUnsigned(uvalue1, uvalue2: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
mov eax, ecx
mov ecx, edx
{$ELSE}
mov eax, edi
mov ecx, esi
{$ENDIF}
xor edx, edx
div ecx
mov eax, edx
end;
class function CoInt.maxUnsigned(uvalue1, uvalue2: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cmp ecx, edx
jb @00
mov eax, ecx
ret
@00: mov eax, edx
{$ELSE}
cmp edi, esi
jb @00
mov eax, edi
ret
@00: mov eax, esi
{$ENDIF}
end;
class function CoInt.minUnsigned(uvalue1, uvalue2: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cmp ecx, edx
ja @00
mov eax, ecx
ret
@00: mov eax, edx
{$ELSE}
cmp edi, esi
ja @00
mov eax, edi
ret
@00: mov eax, esi
{$ENDIF}
end;
class function CoInt.toFloatBits(value: int): float; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
movd xmm0, ecx
{$ELSE}
movd xmm0, edi
{$ENDIF}
end;
class function CoInt.toFloat(value: int): float; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cvtsi2ss xmm0, ecx
{$ELSE}
cvtsi2ss xmm0, edi
{$ENDIF}
end;
class function CoInt.toUnsignedFloat(uvalue: int): float; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
sub ecx, $80000000
cvtsi2ss xmm0, ecx
{$ELSE}
sub edi, $80000000
cvtsi2ss xmm0, edi
{$ENDIF}
addss xmm0, [rip+floats-@00+$00]
@00:
end;
class function CoInt.toDouble(value: int): double; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cvtsi2sd xmm0, ecx
{$ELSE}
cvtsi2sd xmm0, edi
{$ENDIF}
end;
class function CoInt.toUnsignedDouble(uvalue: int): double; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
sub ecx, $80000000
cvtsi2sd xmm0, ecx
{$ELSE}
sub edi, $80000000
cvtsi2sd xmm0, edi
{$ENDIF}
addsd xmm0, [rip+doubles-@00+$00]
@00:
end;
class function CoInt.toReal(value: int): real; assembler; nostackframe;
asm
dd $000008c8
{$IFDEF WINDOWS}
mov qword [rbp-$08], rdx
fild dword [rbp-$08]
fstp tbyte [rcx+$00]
{$ELSE}
mov qword [rbp-$08], rdi
fild dword [rbp-$08]
{$ENDIF}
leave
end;
class function CoInt.toUnsignedReal(uvalue: int): real; assembler; nostackframe;
asm
dd $000008c8
{$IFDEF WINDOWS}
sub edx, $80000000
mov qword [rbp-$08], rdx
fild dword [rbp-$08]
fld qword [rip+doubles-@00+$00]
@00: faddp st(1), st
fstp tbyte [rcx+$00]
{$ELSE}
sub edi, $80000000
mov qword [rbp-$08], rdi
fild dword [rbp-$08]
fld qword [rip+doubles-@00+$00]
@00: faddp st(1), st
{$ENDIF}
leave
end;
class function CoInt.toString(value: int; radix: int): AnsiString;
var
negative: boolean;
idx: int;
len: int;
posrd: int absolute radix;
negrd: int;
buf: char_Array1d;
begin
negative := value < 0;
idx := 32;
len := idx + 1;
buf := &Array.newChar1d(len);
if (radix < CoChar.MIN_RADIX) or (radix > CoChar.MAX_RADIX) then radix := 10;
if not negative then value := -value;
negrd := -posrd;
while value <= negrd do begin
buf[idx] := CoChar.toChar(-(value mod posrd));
value := value div posrd;
dec(idx);
end;
buf[idx] := CoChar.toChar(-value);
if negative then begin
dec(idx);
buf[idx] := '-';
end;
result := AnsiString.create(buf, idx, len - idx);
end;
class function CoInt.toUnsignedString(uvalue: int; radix: int): AnsiString;
var
idx: int;
len: int;
posrd: int absolute radix;
buf: char_Array1d;
begin
idx := 31;
len := idx + 1;
buf := &Array.newChar1d(len);
if (radix < CoChar.MIN_RADIX) or (radix > CoChar.MAX_RADIX) then radix := 10;
while cmpUnsigned(uvalue, posrd) >= 0 do begin
buf[idx] := CoChar.toChar(remUnsigned(uvalue, posrd));
uvalue := divUnsigned(uvalue, posrd);
dec(idx);
end;
buf[idx] := CoChar.toChar(uvalue);
result := AnsiString.create(buf, idx, len - idx);
end;
class function CoInt.toLeadZeroString(value: int; width, radix: int): AnsiString;
var
negative: boolean;
idx: int;
len: int;
count: int;
posrd: int absolute radix;
negrd: int;
buf: char_Array1d;
begin
negative := value < 0;
idx := 32;
len := idx + 1;
buf := &Array.newChar1d(len);
if width > idx then width := idx;
if (radix < CoChar.MIN_RADIX) or (radix > CoChar.MAX_RADIX) then radix := 10;
if not negative then value := -value;
negrd := -posrd;
while value <= negrd do begin
buf[idx] := CoChar.toChar(-(value mod posrd));
value := value div posrd;
dec(idx);
end;
buf[idx] := CoChar.toChar(-value);
for count := len - idx to width - 1 do begin
dec(idx);
buf[idx] := '0';
end;
if negative then begin
dec(idx);
buf[idx] := '-';
end;
result := AnsiString.create(buf, idx, len - idx);
end;
class function CoInt.toBinaryString(uvalue: int): AnsiString;
begin
result := toUnsignedStringByShift(uvalue, 1);
end;
class function CoInt.toOctalString(uvalue: int): AnsiString;
begin
result := toUnsignedStringByShift(uvalue, 3);
end;
class function CoInt.toHexString(uvalue: int): AnsiString;
begin
result := toUnsignedStringByShift(uvalue, 4);
end;
constructor CoInt.create(const value: int);
begin
inherited create();
fldValue := value;
end;
procedure CoInt.writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 4);
int((@(dst[offset]))^) := byteSwap(fldValue);
end;
procedure CoInt.writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 4);
int((@(dst[offset]))^) := fldValue;
end;
function CoInt.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is CoInt) and (CoInt(anot).fldValue = fldValue);
end;
function CoInt.getHashCode(): long;
begin
result := fldValue;
end;
function CoInt.toString(): AnsiString;
begin
result := toString(fldValue);
end;
function CoInt.getSize(): int;
begin
result := sizeof(fldValue);
end;
function CoInt.getType(): int;
begin
result := Lang.TYPE_INT;
end;
function CoInt.isNaN(): boolean;
begin
result := false;
end;
function CoInt.isInfinite(): boolean;
begin
result := false;
end;
function CoInt.asBoolean(): boolean;
begin
result := fldValue <> 0;
end;
function CoInt.asInt(): int;
begin
result := fldValue;
end;
function CoInt.asLong(): long;
begin
result := fldValue;
end;
function CoInt.asFloat(): float;
begin
result := toFloat(fldValue);
end;
function CoInt.asDouble(): double;
begin
result := toDouble(fldValue);
end;
function CoInt.asReal(): real;
begin
result := toReal(fldValue);
end;
function CoInt.asAnsiString(): AnsiString;
begin
result := toString(fldValue);
end;
function CoInt.asUnicodeString(): UnicodeString;
begin
result := toString(fldValue).toUTF16();
end;
function CoInt.asObject(): TObject;
begin
result := self;
end;
function CoInt.asSimple(): ISimple;
begin
result := self;
end;
{%endregion}
{%region CoLong}
class function CoLong.toUnsignedStringByShift(uvalue: long; shift: int): AnsiString;
var
idx: int;
len: int;
msk: long;
buf: char_Array1d;
begin
idx := 64;
len := idx;
msk := (1 shl shift) - 1;
buf := &Array.newChar1d(len);
repeat
dec(idx);
buf[idx] := CoChar.toChar(int(uvalue and msk));
uvalue := uvalue shr shift;
until uvalue = 0;
result := AnsiString.create(buf, idx, len - idx);
end;
class function CoLong.parse(const str: AnsiString; radix: int): long;
var
negative: boolean;
idx: int;
len: int;
limit: long;
digit: long;
mulmin: long;
parsed: long;
begin
len := str.length;
if len <= 0 then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
if (radix < CoChar.MIN_RADIX) or (radix > CoChar.MAX_RADIX) then begin
raise NumberFormatException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format.radix'), [ CoInt.create(radix) ]));
end;
parsed := 0;
idx := 0;
if str[1] = '-' then begin
inc(idx);
negative := true;
limit := -$8000000000000000;
end else begin
negative := false;
limit := -$7fffffffffffffff;
end;
if idx < len then begin
digit := CoChar.toDigit(str[idx + 1], radix);
if digit < 0 then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
parsed := -digit;
inc(idx);
end;
mulmin := limit div radix;
while idx < len do begin
digit := CoChar.toDigit(str[idx + 1], radix);
if (digit < 0) or (parsed < mulmin) then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
parsed := parsed * radix;
if parsed < limit + digit then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
parsed := parsed - digit;
inc(idx);
end;
if negative then begin
if idx < 2 then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
result := parsed;
exit;
end;
result := -parsed;
end;
class function CoLong.parseUnsigned(const str: AnsiString; radix: int): long;
var
idx: int;
len: int;
digit: long;
mulmin: long;
parsed: long;
begin
len := str.length;
if len <= 0 then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
if (radix < CoChar.MIN_RADIX) or (radix > CoChar.MAX_RADIX) then begin
raise NumberFormatException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format.radix'), [ CoInt.create(radix) ]));
end;
parsed := CoChar.toDigit(str[1], radix);
if parsed < 0 then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
mulmin := divUnsigned(long($ffffffffffffffff), radix);
for idx := 1 to len - 1 do begin
digit := CoChar.toDigit(str[idx + 1], radix);
if (digit < 0) or (cmpUnsigned(parsed, mulmin) > 0) then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
parsed := parsed * radix;
if cmpUnsigned(parsed, $ffffffffffffffff - digit) > 0 then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
parsed := parsed + digit;
end;
result := parsed;
end;
class function CoLong.byteSwap(value: long): long; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
mov rax, rcx
{$ELSE}
mov rax, rdi
{$ENDIF}
bswap rax
end;
class function CoLong.bound(value, minimum, maximum: long): long; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cmp rcx, rdx
jge @00
mov rax, rdx
ret
@00: cmp rcx, r8
jle @01
mov rax, r8
ret
@01: mov rax, rcx
{$ELSE}
cmp rdi, rsi
jge @00
mov rax, rsi
ret
@00: cmp rdi, rdx
jle @01
mov rax, rdx
ret
@01: mov rax, rdi
{$ENDIF}
end;
class function CoLong.max(value1, value2: long): long; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cmp rcx, rdx
jl @00
mov rax, rcx
ret
@00: mov rax, rdx
{$ELSE}
cmp rdi, rsi
jl @00
mov rax, rdi
ret
@00: mov rax, rsi
{$ENDIF}
end;
class function CoLong.min(value1, value2: long): long; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cmp rcx, rdx
jg @00
mov rax, rcx
ret
@00: mov rax, rdx
{$ELSE}
cmp rdi, rsi
jg @00
mov rax, rdi
ret
@00: mov rax, rsi
{$ENDIF}
end;
class function CoLong.sar(value: long; bits: int): long; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
mov rax, rcx
mov ecx, edx
{$ELSE}
mov rax, rdi
mov ecx, esi
{$ENDIF}
sar rax, cl
end;
class function CoLong.rol(value: long; bits: int): long; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
mov rax, rcx
mov ecx, edx
{$ELSE}
mov rax, rdi
mov ecx, esi
{$ENDIF}
rol rax, cl
end;
class function CoLong.boundUnsigned(uvalue, uminimum, umaximum: long): long; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cmp rcx, rdx
jae @00
mov rax, rdx
ret
@00: cmp rcx, r8
jbe @01
mov rax, r8
ret
@01: mov rax, rcx
{$ELSE}
cmp rdi, rsi
jae @00
mov rax, rsi
ret
@00: cmp rdi, rdx
jbe @01
mov rax, rdx
ret
@01: mov rax, rdi
{$ENDIF}
end;
class function CoLong.cmpUnsigned(uvalue1, uvalue2: long): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cmp rcx, rdx
{$ELSE}
cmp rdi, rsi
{$ENDIF}
jb @lt
je @eq
@gt: mov eax, $00000001
ret
@lt: mov eax, $ffffffff
ret
@eq: xor eax, eax
end;
class function CoLong.divUnsigned(uvalue1, uvalue2: long): long; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
mov rax, rcx
mov rcx, rdx
{$ELSE}
mov rax, rdi
mov rcx, rsi
{$ENDIF}
xor rdx, rdx
div rcx
end;
class function CoLong.remUnsigned(uvalue1, uvalue2: long): long; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
mov rax, rcx
mov rcx, rdx
{$ELSE}
mov rax, rdi
mov rcx, rsi
{$ENDIF}
xor rdx, rdx
div rcx
mov rax, rdx
end;
class function CoLong.maxUnsigned(uvalue1, uvalue2: long): long; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cmp rcx, rdx
jb @00
mov rax, rcx
ret
@00: mov rax, rdx
{$ELSE}
cmp rdi, rsi
jb @00
mov rax, rdi
ret
@00: mov rax, rsi
{$ENDIF}
end;
class function CoLong.minUnsigned(uvalue1, uvalue2: long): long; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cmp rcx, rdx
ja @00
mov rax, rcx
ret
@00: mov rax, rdx
{$ELSE}
cmp rdi, rsi
ja @00
mov rax, rdi
ret
@00: mov rax, rsi
{$ENDIF}
end;
class function CoLong.toDoubleBits(value: long): double; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
movq xmm0, rcx
{$ELSE}
movq xmm0, rdi
{$ENDIF}
end;
class function CoLong.toFloat(value: long): float; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cvtsi2ss xmm0, rcx
{$ELSE}
cvtsi2ss xmm0, rdi
{$ENDIF}
end;
class function CoLong.toUnsignedFloat(uvalue: long): float; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
sub rcx, [rip+longs-@00+$10]
@00: cvtsi2ss xmm0, rcx
{$ELSE}
sub rdi, [rip+longs-@00+$10]
@00: cvtsi2ss xmm0, rdi
{$ENDIF}
addss xmm0, [rip+floats-@01+$04]
@01:
end;
class function CoLong.toDouble(value: long): double; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
cvtsi2sd xmm0, rcx
{$ELSE}
cvtsi2sd xmm0, rdi
{$ENDIF}
end;
class function CoLong.toUnsignedDouble(uvalue: long): double; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
sub rcx, [rip+longs-@00+$10]
@00: cvtsi2sd xmm0, rcx
{$ELSE}
sub rdi, [rip+longs-@00+$10]
@00: cvtsi2sd xmm0, rdi
{$ENDIF}
addsd xmm0, [rip+doubles-@01+$08]
@01:
end;
class function CoLong.toReal(value: long): real; assembler; nostackframe;
asm
dd $000008c8
{$IFDEF WINDOWS}
mov qword [rbp-$08], rdx
fild qword [rbp-$08]
fstp tbyte [rcx+$00]
{$ELSE}
mov qword [rbp-$08], rdi
fild qword [rbp-$08]
{$ENDIF}
leave
end;
class function CoLong.toUnsignedReal(uvalue: long): real; assembler; nostackframe;
asm
dd $000008c8
{$IFDEF WINDOWS}
sub rdx, [rip+longs-@00+$10]
@00: mov qword [rbp-$08], rdx
fild qword [rbp-$08]
fld qword [rip+doubles-@01+$08]
@01: faddp st(1), st
fstp tbyte [rcx+$00]
{$ELSE}
sub rdi, [rip+longs-@00+$10]
@00: mov qword [rbp-$08], rdi
fild qword [rbp-$08]
fld qword [rip+doubles-@01+$08]
@01: faddp st(1), st
{$ENDIF}
leave
end;
class function CoLong.toString(value: long; radix: int): AnsiString;
var
negative: boolean;
idx: int;
len: int;
posrd: long;
negrd: long;
buf: char_Array1d;
begin
negative := value < 0;
idx := 64;
len := idx + 1;
buf := &Array.newChar1d(len);
if (radix < CoChar.MIN_RADIX) or (radix > CoChar.MAX_RADIX) then radix := 10;
if not negative then value := -value;
posrd := radix;
negrd := -posrd;
while value <= negrd do begin
buf[idx] := CoChar.toChar(int(-(value mod posrd)));
value := value div posrd;
dec(idx);
end;
buf[idx] := CoChar.toChar(int(-value));
if negative then begin
dec(idx);
buf[idx] := '-';
end;
result := AnsiString.create(buf, idx, len - idx);
end;
class function CoLong.toUnsignedString(uvalue: long; radix: int): AnsiString;
var
idx: int;
len: int;
posrd: long;
buf: char_Array1d;
begin
idx := 63;
len := idx + 1;
buf := &Array.newChar1d(len);
if (radix < CoChar.MIN_RADIX) or (radix > CoChar.MAX_RADIX) then radix := 10;
posrd := radix;
while cmpUnsigned(uvalue, posrd) >= 0 do begin
buf[idx] := CoChar.toChar(int(remUnsigned(uvalue, posrd)));
uvalue := divUnsigned(uvalue, posrd);
dec(idx);
end;
buf[idx] := CoChar.toChar(int(uvalue));
result := AnsiString.create(buf, idx, len - idx);
end;
class function CoLong.toLeadZeroString(value: long; width, radix: int): AnsiString;
var
negative: boolean;
idx: int;
len: int;
count: int;
posrd: long;
negrd: long;
buf: char_Array1d;
begin
negative := value < 0;
idx := 64;
len := idx + 1;
buf := &Array.newChar1d(len);
if width > idx then width := idx;
if (radix < CoChar.MIN_RADIX) or (radix > CoChar.MAX_RADIX) then radix := 10;
if not negative then value := -value;
posrd := radix;
negrd := -posrd;
while value <= negrd do begin
buf[idx] := CoChar.toChar(int(-(value mod posrd)));
value := value div posrd;
dec(idx);
end;
buf[idx] := CoChar.toChar(int(-value));
for count := len - idx to width - 1 do begin
dec(idx);
buf[idx] := '0';
end;
if negative then begin
dec(idx);
buf[idx] := '-';
end;
result := AnsiString.create(buf, idx, len - idx);
end;
class function CoLong.toBinaryString(uvalue: long): AnsiString;
begin
result := toUnsignedStringByShift(uvalue, 1);
end;
class function CoLong.toOctalString(uvalue: long): AnsiString;
begin
result := toUnsignedStringByShift(uvalue, 3);
end;
class function CoLong.toHexString(uvalue: long): AnsiString;
begin
result := toUnsignedStringByShift(uvalue, 4);
end;
constructor CoLong.create(const value: long);
begin
inherited create();
fldValue := value;
end;
procedure CoLong.writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 8);
long((@(dst[offset]))^) := byteSwap(fldValue);
end;
procedure CoLong.writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 8);
long((@(dst[offset]))^) := fldValue;
end;
function CoLong.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is CoLong) and (CoLong(anot).fldValue = fldValue);
end;
function CoLong.getHashCode(): long;
begin
result := fldValue;
end;
function CoLong.toString(): AnsiString;
begin
result := toString(fldValue);
end;
function CoLong.getSize(): int;
begin
result := sizeof(fldValue);
end;
function CoLong.getType(): int;
begin
result := Lang.TYPE_LONG;
end;
function CoLong.isNaN(): boolean;
begin
result := false;
end;
function CoLong.isInfinite(): boolean;
begin
result := false;
end;
function CoLong.asBoolean(): boolean;
begin
result := fldValue <> 0;
end;
function CoLong.asInt(): int;
begin
result := int(fldValue);
end;
function CoLong.asLong(): long;
begin
result := fldValue;
end;
function CoLong.asFloat(): float;
begin
result := toFloat(fldValue);
end;
function CoLong.asDouble(): double;
begin
result := toDouble(fldValue);
end;
function CoLong.asReal(): real;
begin
result := toReal(fldValue);
end;
function CoLong.asAnsiString(): AnsiString;
begin
result := toString(fldValue);
end;
function CoLong.asUnicodeString(): UnicodeString;
begin
result := toString(fldValue).toUTF16();
end;
function CoLong.asObject(): TObject;
begin
result := self;
end;
function CoLong.asSimple(): ISimple;
begin
result := self;
end;
{%endregion}
{%region CoFloat}
class function CoFloat.parse(const str: AnsiString): float;
begin
result := representFloat.parseFloat(str);
end;
class function CoFloat.isNaN(value: float): boolean;
begin
result := value <> value;
end;
class function CoFloat.isInfinite(value: float): boolean;
begin
result := (value = POSITIVE_INFINITY) or (value = NEGATIVE_INFINITY);
end;
class function CoFloat.cmpl(value1, value2: float): int; assembler; nostackframe;
asm
comiss xmm0, xmm1
jp @lt
jb @lt
je @eq
@gt: mov eax, $00000001
ret
@lt: mov eax, $ffffffff
ret
@eq: xor eax, eax
end;
class function CoFloat.cmpg(value1, value2: float): int; assembler; nostackframe;
asm
comiss xmm0, xmm1
jp @gt
jb @lt
je @eq
@gt: mov eax, $00000001
ret
@lt: mov eax, $ffffffff
ret
@eq: xor eax, eax
end;
class function CoFloat.rem(value1, value2: float): float; assembler; nostackframe;
asm
dd $000008c8
movss dword [rbp-$08], xmm0
movss dword [rbp-$04], xmm1
fld dword [rbp-$04]
fld dword [rbp-$08]
@00: fprem
fnstsw ax
test eax, $00000400
jnz @00
fstp st(1)
fstp dword [rbp-$08]
movss xmm0, [rbp-$08]
leave
end;
class function CoFloat.max(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 (toIntBits(value1) = CoInt.MIN_VALUE) or (value1 < value2) then begin
result := value2;
exit;
end;
result := value1;
end;
class function CoFloat.min(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 (toIntBits(value2) = CoInt.MIN_VALUE) or (value1 > value2) then begin
result := value2;
exit;
end;
result := value1;
end;
class function CoFloat.bound(value, minimum, maximum: float): float;
begin
result := min(max(minimum, value), maximum);
end;
class function CoFloat.toIntBits(value: float): int; assembler; nostackframe;
asm
movd eax, xmm0
end;
class function CoFloat.toInt(value: float): int; assembler; nostackframe;
asm
movss xmm1, xmm0
movss xmm2, [rip+floats-@00+$00]
@00: movss xmm3, xmm0
cvttps2dq xmm0, xmm0
cmpss xmm1, xmm1, $07
cmpss xmm2, xmm3, $02
paddd xmm0, xmm2
pand xmm0, xmm1
movd eax, xmm0
end;
class function CoFloat.toUnsignedInt(value: float): int; assembler; nostackframe;
asm
subss xmm0, [rip+floats-@00+$00]
@00: movss xmm1, xmm0
movss xmm2, [rip+floats-@01+$00]
@01: movss xmm3, xmm0
cvttps2dq xmm0, xmm0
cmpss xmm1, xmm1, $07
cmpss xmm2, xmm3, $02
movd xmm3, [rip+ints-@02+$00]
@02: paddd xmm0, xmm3
paddd xmm0, xmm2
pand xmm0, xmm1
movd eax, xmm0
end;
class function CoFloat.toLong(value: float): long; assembler; nostackframe;
asm
cvtss2sd xmm0, xmm0
movsd xmm1, xmm0
movsd xmm2, [rip+doubles-@00+$08]
@00: 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;
class function CoFloat.toUnsignedLong(value: float): long; assembler; nostackframe;
asm
subss xmm0, [rip+floats-@00+$04]
@00: cvtss2sd xmm0, xmm0
movsd xmm1, xmm0
movsd xmm2, [rip+doubles-@01+$08]
@01: movsd xmm3, xmm0
cvttsd2si rax, xmm0
movq xmm0, rax
cmpsd xmm1, xmm1, $07
cmpsd xmm2, xmm3, $02
movq xmm3, [rip+longs-@02+$10]
@02: paddq xmm0, xmm3
paddq xmm0, xmm2
pand xmm0, xmm1
movq rax, xmm0
end;
class function CoFloat.toDouble(value: float): double; assembler; nostackframe;
asm
cvtss2sd xmm0, xmm0
end;
class function CoFloat.toReal(value: float): real; assembler; nostackframe;
asm
dd $000008c8
{$IFDEF WINDOWS}
movss dword [rbp-$08], xmm1
fld dword [rbp-$08]
fstp tbyte [rcx+$00]
{$ELSE}
movss dword [rbp-$08], xmm0
fld dword [rbp-$08]
{$ENDIF}
leave
end;
class function CoFloat.toString(value: float): AnsiString;
begin
result := representFloat.toString(toReal(value));
end;
class function CoFloat.toString(value: float; sigDigits, ordDigits: int; sigAll, ordAll, expForm, sigSign, ordSign: boolean): AnsiString;
begin
with RealRepresenter.create(sigDigits, ordDigits, sigAll, ordAll, expForm, sigSign, ordSign) do try
result := toString(toReal(value));
finally
free();
end;
end;
constructor CoFloat.create(const value: float);
begin
inherited create();
fldValue := value;
end;
procedure CoFloat.writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 4);
int((@(dst[offset]))^) := CoInt.byteSwap(toIntBits(fldValue));
end;
procedure CoFloat.writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 4);
float((@(dst[offset]))^) := fldValue;
end;
function CoFloat.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is CoFloat) and (toIntBits(CoFloat(anot).fldValue) = toIntBits(fldValue));
end;
function CoFloat.getHashCode(): long;
begin
result := toIntBits(fldValue);
end;
function CoFloat.toString(): AnsiString;
begin
result := toString(fldValue);
end;
function CoFloat.getSize(): int;
begin
result := sizeof(fldValue);
end;
function CoFloat.getType(): int;
begin
result := Lang.TYPE_FLOAT;
end;
function CoFloat.isNaN(): boolean;
begin
result := isNaN(fldValue);
end;
function CoFloat.isInfinite(): boolean;
begin
result := isInfinite(fldValue);
end;
function CoFloat.asBoolean(): boolean;
begin
result := fldValue <> 0.0;
end;
function CoFloat.asInt(): int;
begin
result := toInt(fldValue);
end;
function CoFloat.asLong(): long;
begin
result := toLong(fldValue);
end;
function CoFloat.asFloat(): float;
begin
result := fldValue;
end;
function CoFloat.asDouble(): double;
begin
result := toDouble(fldValue);
end;
function CoFloat.asReal(): real;
begin
result := toReal(fldValue);
end;
function CoFloat.asAnsiString(): AnsiString;
begin
result := toString(fldValue);
end;
function CoFloat.asUnicodeString(): UnicodeString;
begin
result := toString(fldValue).toUTF16();
end;
function CoFloat.asObject(): TObject;
begin
result := self;
end;
function CoFloat.asSimple(): ISimple;
begin
result := self;
end;
{%endregion}
{%region CoDouble}
class function CoDouble.parse(const str: AnsiString): double;
begin
result := representDouble.parseDouble(str);
end;
class function CoDouble.isNaN(value: double): boolean;
begin
result := value <> value;
end;
class function CoDouble.isInfinite(value: double): boolean;
begin
result := (value = POSITIVE_INFINITY) or (value = NEGATIVE_INFINITY);
end;
class function CoDouble.cmpl(value1, value2: double): int; assembler; nostackframe;
asm
comisd xmm0, xmm1
jp @lt
jb @lt
je @eq
@gt: mov eax, $00000001
ret
@lt: mov eax, $ffffffff
ret
@eq: xor eax, eax
end;
class function CoDouble.cmpg(value1, value2: double): int; assembler; nostackframe;
asm
comisd xmm0, xmm1
jp @gt
jb @lt
je @eq
@gt: mov eax, $00000001
ret
@lt: mov eax, $ffffffff
ret
@eq: xor eax, eax
end;
class function CoDouble.rem(value1, value2: double): double; assembler; nostackframe;
asm
dd $000010c8
movsd qword [rbp-$10], xmm0
movsd qword [rbp-$08], xmm1
fld qword [rbp-$08]
fld qword [rbp-$10]
@00: fprem
fnstsw ax
test eax, $00000400
jnz @00
fstp st(1)
fstp qword [rbp-$10]
movsd xmm0, [rbp-$10]
leave
end;
class function CoDouble.max(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 (toLongBits(value1) = CoLong.MIN_VALUE) or (value1 < value2) then begin
result := value2;
exit;
end;
result := value1;
end;
class function CoDouble.min(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 (toLongBits(value2) = CoLong.MIN_VALUE) or (value1 > value2) then begin
result := value2;
exit;
end;
result := value1;
end;
class function CoDouble.bound(value, minimum, maximum: double): double;
begin
result := min(max(minimum, value), maximum);
end;
class function CoDouble.toLongBits(value: double): long; assembler; nostackframe;
asm
movq rax, xmm0
end;
class function CoDouble.toInt(value: double): int; assembler; nostackframe;
asm
movsd xmm1, xmm0
movsd xmm2, [rip+doubles-@00+$00]
@00: movsd xmm3, xmm0
cvttpd2dq xmm0, xmm0
cmpsd xmm1, xmm1, $07
cmpsd xmm2, xmm3, $02
paddd xmm0, xmm2
pand xmm0, xmm1
movd eax, xmm0
end;
class function CoDouble.toUnsignedInt(value: double): int; assembler; nostackframe;
asm
subsd xmm0, [rip+doubles-@00+$00]
@00: movsd xmm1, xmm0
movsd xmm2, [rip+doubles-@01+$00]
@01: movsd xmm3, xmm0
cvttpd2dq xmm0, xmm0
cmpsd xmm1, xmm1, $07
cmpsd xmm2, xmm3, $02
movd xmm3, [rip+ints-@02+$00]
@02: paddd xmm0, xmm3
paddd xmm0, xmm2
pand xmm0, xmm1
movd eax, xmm0
end;
class function CoDouble.toLong(value: double): long; assembler; nostackframe;
asm
movsd xmm1, xmm0
movsd xmm2, [rip+doubles-@00+$08]
@00: 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;
class function CoDouble.toUnsignedLong(value: double): long; assembler; nostackframe;
asm
subsd xmm0, [rip+doubles-@00+$08]
@00: movsd xmm1, xmm0
movsd xmm2, [rip+doubles-@01+$08]
@01: movsd xmm3, xmm0
cvttsd2si rax, xmm0
movq xmm0, rax
cmpsd xmm1, xmm1, $07
cmpsd xmm2, xmm3, $02
movq xmm3, [rip+longs-@02+$10]
@02: paddq xmm0, xmm3
paddq xmm0, xmm2
pand xmm0, xmm1
movq rax, xmm0
end;
class function CoDouble.toFloat(value: double): float; assembler; nostackframe;
asm
cvtsd2ss xmm0, xmm0
end;
class function CoDouble.toReal(value: double): real; assembler; nostackframe;
asm
dd $000008c8
{$IFDEF WINDOWS}
movsd qword [rbp-$08], xmm1
fld qword [rbp-$08]
fstp tbyte [rcx+$00]
{$ELSE}
movsd qword [rbp-$08], xmm0
fld qword [rbp-$08]
{$ENDIF}
leave
end;
class function CoDouble.toString(value: double): AnsiString;
begin
result := representDouble.toString(toReal(value));
end;
class function CoDouble.toString(value: double; sigDigits, ordDigits: int; sigAll, ordAll, expForm, sigSign, ordSign: boolean): AnsiString;
begin
with RealRepresenter.create(sigDigits, ordDigits, sigAll, ordAll, expForm, sigSign, ordSign) do try
result := toString(toReal(value));
finally
free();
end;
end;
constructor CoDouble.create(const value: double);
begin
inherited create();
fldValue := value;
end;
procedure CoDouble.writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 8);
long((@(dst[offset]))^) := CoLong.byteSwap(toLongBits(fldValue));
end;
procedure CoDouble.writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 8);
double((@(dst[offset]))^) := fldValue;
end;
function CoDouble.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is CoDouble) and (toLongBits(CoDouble(anot).fldValue) = toLongBits(fldValue));
end;
function CoDouble.getHashCode(): long;
begin
result := toLongBits(fldValue);
end;
function CoDouble.toString(): AnsiString;
begin
result := toString(fldValue);
end;
function CoDouble.getSize(): int;
begin
result := sizeof(fldValue);
end;
function CoDouble.getType(): int;
begin
result := Lang.TYPE_DOUBLE;
end;
function CoDouble.isNaN(): boolean;
begin
result := isNaN(fldValue);
end;
function CoDouble.isInfinite(): boolean;
begin
result := isInfinite(fldValue);
end;
function CoDouble.asBoolean(): boolean;
begin
result := fldValue <> 0.0;
end;
function CoDouble.asInt(): int;
begin
result := toInt(fldValue);
end;
function CoDouble.asLong(): long;
begin
result := toLong(fldValue);
end;
function CoDouble.asFloat(): float;
begin
result := toFloat(fldValue);
end;
function CoDouble.asDouble(): double;
begin
result := fldValue;
end;
function CoDouble.asReal(): real;
begin
result := toReal(fldValue);
end;
function CoDouble.asAnsiString(): AnsiString;
begin
result := toString(fldValue);
end;
function CoDouble.asUnicodeString(): UnicodeString;
begin
result := toString(fldValue).toUTF16();
end;
function CoDouble.asObject(): TObject;
begin
result := self;
end;
function CoDouble.asSimple(): ISimple;
begin
result := self;
end;
{%endregion}
{%region CoReal}
{$IFDEF WINDOWS}
class function CoReal.MIN_VALUE: real;
begin
result := CoReal.build($0000, $0000000000000001); { минимальное значение }
end;
class function CoReal.MAX_VALUE: real;
begin
result := CoReal.build($7ffe, $ffffffffffffffff); { максимальное значение }
end;
class function CoReal.POSITIVE_INFINITY: real;
begin
result := CoReal.build($7fff, $8000000000000000); { +∞ }
end;
class function CoReal.NEGATIVE_INFINITY: real;
begin
result := CoReal.build($ffff, $8000000000000000); { –∞ }
end;
class function CoReal.NEGATIVE_ZERO: real;
begin
result := CoReal.build($8000, $0000000000000000); { –0 }
end;
class function CoReal.NAN: real;
begin
result := CoReal.build($ffff, $c000000000000000); { не число }
end;
{$ENDIF}
class function CoReal.parse(const str: AnsiString): real;
begin
result := representReal.parseReal(str);
end;
class function CoReal.isNaN(value: real): boolean;
begin
result := value <> value;
end;
class function CoReal.isInfinite(value: real): boolean;
begin
result := (value = POSITIVE_INFINITY) or (value = NEGATIVE_INFINITY);
end;
class function CoReal.cmpl(value1, value2: real): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
fld tbyte [rcx+$00]
{$ELSE}
fld tbyte [rsp+$18]
fld tbyte [rsp+$08]
{$ENDIF}
fcomip st, st(1)
ffree st
fincstp
jp @lt
jb @lt
je @eq
@gt: mov eax, $00000001
ret
@lt: mov eax, $ffffffff
ret
@eq: xor eax, eax
end;
class function CoReal.cmpg(value1, value2: real): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
fld tbyte [rcx+$00]
{$ELSE}
fld tbyte [rsp+$18]
fld tbyte [rsp+$08]
{$ENDIF}
fcomip st, st(1)
ffree st
fincstp
jp @gt
jb @lt
je @eq
@gt: mov eax, $00000001
ret
@lt: mov eax, $ffffffff
ret
@eq: xor eax, eax
end;
class function CoReal.rem(value1, value2: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [r8+$00]
fld tbyte [rdx+$00]
@00: fprem
fnstsw ax
test eax, $00000400
jnz @00
fstp st(1)
fstp tbyte [rcx+$00]
{$ELSE}
fld tbyte [rsp+$18]
fld tbyte [rsp+$08]
@00: fprem
fnstsw ax
test eax, $00000400
jnz @00
fstp st(1)
{$ENDIF}
end;
class function CoReal.max(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 (extractExponent(value1) = CoShort.MIN_VALUE) and (extractSignificand(value1) = 0) or (value1 < value2) then begin
result := value2;
exit;
end;
result := value1;
end;
class function CoReal.min(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 (extractExponent(value2) = CoShort.MIN_VALUE) and (extractSignificand(value2) = 0) or (value1 > value2) then begin
result := value2;
exit;
end;
result := value1;
end;
class function CoReal.bound(value, minimum, maximum: real): real;
begin
result := min(max(minimum, value), maximum);
end;
class function CoReal.extractExponent(const value: real): int;
var
struct: RealStruct absolute value;
begin
result := struct.exponent;
end;
class function CoReal.extractSignificand(const value: real): long;
var
struct: RealStruct absolute value;
begin
result := struct.significand;
end;
class function CoReal.build(exponent: int; significand: long): real;
var
struct: RealStruct absolute result;
begin
struct.significand := significand;
struct.exponent := short(exponent);
end;
class function CoReal.toInt(value: real): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rcx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fild qword [rip+longs-@00+$00]
@00: fcomip st, st(1)
jnp @01
ffree st
fincstp
xor eax, eax
ret
@01: ja @02
ffree st
fincstp
mov eax, $7fffffff
ret
@02: lea rsp, [rsp-$08]
fisttp dword [rsp+$00]
pop rax
mov eax, eax
end;
class function CoReal.toUnsignedInt(value: real): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rcx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fild dword [rip+ints-@00+$00]
@00: faddp st(1), st
fild qword [rip+longs-@01+$00]
@01: fcomip st, st(1)
jnp @02
ffree st
fincstp
xor eax, eax
ret
@02: ja @03
ffree st
fincstp
mov eax, $ffffffff
ret
@03: lea rsp, [rsp-$08]
fisttp dword [rsp+$00]
pop rax
add eax, $80000000
end;
class function CoReal.toLong(value: real): long; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rcx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fild qword [rip+longs-@00+$08]
@00: fcomip st, st(1)
jnp @01
ffree st
fincstp
xor eax, eax
ret
@01: ja @03
ffree st
fincstp
mov rax, [rip+longs-@02+$08]
@02: ret
@03: lea rsp, [rsp-$08]
fisttp qword [rsp+$00]
pop rax
end;
class function CoReal.toUnsignedLong(value: real): long; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rcx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fild qword [rip+longs-@00+$10]
@00: faddp st(1), st
fild qword [rip+longs-@01+$08]
@01: fcomip st, st(1)
jnp @02
ffree st
fincstp
xor eax, eax
ret
@02: ja @04
ffree st
fincstp
mov rax, [rip+longs-@03+$18]
@03: ret
@04: lea rsp, [rsp-$08]
fisttp qword [rsp+$00]
pop rax
add rax, [rip+longs-@05+$10]
@05:
end;
class function CoReal.toFloat(value: real): float; assembler; nostackframe;
asm
dd $000008c8
{$IFDEF WINDOWS}
fld tbyte [rcx+$00]
{$ELSE}
fld tbyte [value+$00]
{$ENDIF}
fstp dword [rbp-$08]
movss xmm0, [rbp-$08]
leave
end;
class function CoReal.toDouble(value: real): double; assembler; nostackframe;
asm
dd $000008c8
{$IFDEF WINDOWS}
fld tbyte [rcx+$00]
{$ELSE}
fld tbyte [value+$00]
{$ENDIF}
fstp qword [rbp-$08]
movsd xmm0, [rbp-$08]
leave
end;
class function CoReal.toString(value: real): AnsiString;
begin
result := representReal.toString(value);
end;
class function CoReal.toString(value: real; sigDigits, ordDigits: int; sigAll, ordAll, expForm, sigSign, ordSign: boolean): AnsiString;
begin
with RealRepresenter.create(sigDigits, ordDigits, sigAll, ordAll, expForm, sigSign, ordSign) do try
result := toString(value);
finally
free();
end;
end;
constructor CoReal.create(const value: real);
begin
inherited create();
fldValue := value;
end;
procedure CoReal.writeToByteArrayBigEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 10);
short((@(dst[offset]))^) := CoShort.byteSwap(RealStruct(fldValue).exponent);
long((@(dst[offset + 2]))^) := CoLong.byteSwap(RealStruct(fldValue).significand);
end;
procedure CoReal.writeToByteArrayLittleEndian(const dst: byte_Array1d; offset: int);
begin
&Array.checkBounds(dst, offset, 10);
real((@(dst[offset]))^) := fldValue;
end;
function CoReal.equals(anot: TObject): boolean;
begin
result := (anot = self) or (
(anot is CoReal) and
(RealStruct(CoReal(anot).fldValue).exponent = RealStruct(fldValue).exponent) and
(RealStruct(CoReal(anot).fldValue).significand = RealStruct(fldValue).significand)
);
end;
function CoReal.getHashCode(): long;
begin
result := CoDouble.toLongBits(toDouble(fldValue));
end;
function CoReal.toString(): AnsiString;
begin
result := toString(fldValue);
end;
function CoReal.getSize(): int;
begin
result := sizeof(fldValue);
end;
function CoReal.getType(): int;
begin
result := Lang.TYPE_REAL;
end;
function CoReal.isNaN(): boolean;
begin
result := isNaN(fldValue);
end;
function CoReal.isInfinite(): boolean;
begin
result := isInfinite(fldValue);
end;
function CoReal.asBoolean(): boolean;
begin
result := fldValue <> 0.0;
end;
function CoReal.asInt(): int;
begin
result := toInt(fldValue);
end;
function CoReal.asLong(): long;
begin
result := toLong(fldValue);
end;
function CoReal.asFloat(): float;
begin
result := toFloat(fldValue);
end;
function CoReal.asDouble(): double;
begin
result := toDouble(fldValue);
end;
function CoReal.asReal(): real;
begin
result := fldValue;
end;
function CoReal.asAnsiString(): AnsiString;
begin
result := toString(fldValue);
end;
function CoReal.asUnicodeString(): UnicodeString;
begin
result := toString(fldValue).toUTF16();
end;
function CoReal.asObject(): TObject;
begin
result := self;
end;
function CoReal.asSimple(): ISimple;
begin
result := self;
end;
{%endregion}
{%region CoAnsiString}
constructor CoAnsiString.create(const value: AnsiString);
begin
inherited create();
fldValue := value;
end;
function CoAnsiString.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is CoAnsiString) and (CoAnsiString(anot).fldValue = fldValue);
end;
function CoAnsiString.getHashCode(): long;
var
idx: int;
mul: long;
str: AnsiString;
begin
if fldHashComputed then begin
result := fldHashValue;
exit;
end;
result := 0;
mul := 1;
str := fldValue;
for idx := 0 to str.length - 1 do begin
inc(result, mul * int(str[idx + 1]));
mul := 31 * mul;
end;
fldHashValue := result;
fldHashComputed := true;
end;
function CoAnsiString.toString(): AnsiString;
begin
result := fldValue;
end;
function CoAnsiString.getType(): int;
begin
result := Lang.TYPE_ANSISTRING;
end;
function CoAnsiString.isNaN(): boolean;
begin
result := false;
end;
function CoAnsiString.isInfinite(): boolean;
begin
result := false;
end;
function CoAnsiString.asBoolean(): boolean;
begin
result := fldValue.length > 0;
end;
function CoAnsiString.asInt(): int;
begin
try
result := CoInt.parse(fldValue);
except
result := 0;
end;
end;
function CoAnsiString.asLong(): long;
begin
try
result := CoLong.parse(fldValue);
except
result := 0;
end;
end;
function CoAnsiString.asFloat(): float;
begin
try
result := CoFloat.parse(fldValue);
except
result := 0;
end;
end;
function CoAnsiString.asDouble(): double;
begin
try
result := CoDouble.parse(fldValue);
except
result := 0;
end;
end;
function CoAnsiString.asReal(): real;
begin
try
result := CoReal.parse(fldValue);
except
result := 0;
end;
end;
function CoAnsiString.asAnsiString(): AnsiString;
begin
result := fldValue;
end;
function CoAnsiString.asUnicodeString(): UnicodeString;
begin
result := fldValue.toUTF16();
end;
function CoAnsiString.asObject(): TObject;
begin
result := self;
end;
function CoAnsiString.asSimple(): ISimple;
begin
result := self;
end;
{%endregion}
{%region CoUnicodeString}
constructor CoUnicodeString.create(const value: UnicodeString);
begin
inherited create();
fldValue := value;
end;
function CoUnicodeString.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is CoUnicodeString) and (CoUnicodeString(anot).fldValue = fldValue);
end;
function CoUnicodeString.getHashCode(): long;
var
idx: int;
mul: long;
str: UnicodeString;
begin
if fldHashComputed then begin
result := fldHashValue;
exit;
end;
result := 0;
mul := 1;
str := fldValue;
for idx := 0 to str.length - 1 do begin
inc(result, mul * int(str[idx + 1]));
mul := 31 * mul;
end;
fldHashValue := result;
fldHashComputed := true;
end;
function CoUnicodeString.toString(): AnsiString;
begin
result := fldValue.toUTF8();
end;
function CoUnicodeString.getType(): int;
begin
result := Lang.TYPE_UNICODESTRING;
end;
function CoUnicodeString.isNaN(): boolean;
begin
result := false;
end;
function CoUnicodeString.isInfinite(): boolean;
begin
result := false;
end;
function CoUnicodeString.asBoolean(): boolean;
begin
result := fldValue.length > 0;
end;
function CoUnicodeString.asInt(): int;
begin
try
result := CoInt.parse(fldValue.toUTF8());
except
result := 0;
end;
end;
function CoUnicodeString.asLong(): long;
begin
try
result := CoLong.parse(fldValue.toUTF8());
except
result := 0;
end;
end;
function CoUnicodeString.asFloat(): float;
begin
try
result := CoFloat.parse(fldValue.toUTF8());
except
result := 0;
end;
end;
function CoUnicodeString.asDouble(): double;
begin
try
result := CoDouble.parse(fldValue.toUTF8());
except
result := 0;
end;
end;
function CoUnicodeString.asReal(): real;
begin
try
result := CoReal.parse(fldValue.toUTF8());
except
result := 0;
end;
end;
function CoUnicodeString.asAnsiString(): AnsiString;
begin
result := fldValue.toUTF8();
end;
function CoUnicodeString.asUnicodeString(): UnicodeString;
begin
result := fldValue;
end;
function CoUnicodeString.asObject(): TObject;
begin
result := self;
end;
function CoUnicodeString.asSimple(): ISimple;
begin
result := self;
end;
{%endregion}
{%region CoObject}
constructor CoObject.create(const value: TObject);
begin
inherited create();
fldValue := value;
end;
function CoObject.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is CoObject) and (CoObject(anot).fldValue = fldValue);
end;
function CoObject.getHashCode(): long;
begin
result := long(fldValue);
end;
function CoObject.toString(): AnsiString;
var
obj: TObject;
begin
obj := fldValue;
if obj = nil then begin
result := 'null';
exit;
end;
result := obj.toString();
end;
function CoObject.getType(): int;
begin
result := Lang.TYPE_OBJECT;
end;
function CoObject.isNaN(): boolean;
begin
result := false;
end;
function CoObject.isInfinite(): boolean;
begin
result := false;
end;
function CoObject.asBoolean(): boolean;
begin
result := false;
end;
function CoObject.asInt(): int;
begin
result := 0;
end;
function CoObject.asLong(): long;
begin
result := 0;
end;
function CoObject.asFloat(): float;
begin
result := 0;
end;
function CoObject.asDouble(): double;
begin
result := 0;
end;
function CoObject.asReal(): real;
begin
result := 0;
end;
function CoObject.asAnsiString(): AnsiString;
begin
result := '';
end;
function CoObject.asUnicodeString(): UnicodeString;
begin
result := '';
end;
function CoObject.asObject(): TObject;
begin
result := fldValue;
end;
function CoObject.asSimple(): ISimple;
var
val: TObject;
ref: ISimple;
begin
val := fldValue;
if (val <> nil) and val.getInterface(getTypeData(PTypeInfo(typeInfo(ISimple)))^.iidStr, ref) then begin
result := ref;
exit;
end;
result := nil;
end;
{%endregion}
{%region CoSimple}
constructor CoSimple.create(const value: ISimple);
begin
inherited create();
fldValue := value;
end;
function CoSimple.equals(anot: TObject): boolean;
var
ref1: ISimple;
ref2: ISimple;
piid: system.PGuid;
begin
if anot = self then begin
result := true;
exit;
end;
if not(anot is CoSimple) then begin
result := false;
exit;
end;
ref1 := fldValue;
ref2 := CoSimple(anot).fldValue;
piid := @(getTypeData(PTypeInfo(typeInfo(ISimple)))^.guid);
if
((ref1 = nil) or (ref1.queryInterface(piid^, ref1) = system.S_OK)) and
((ref2 = nil) or (ref2.queryInterface(piid^, ref2) = system.S_OK))
then begin
result := ref1 = ref2;
exit;
end;
result := false;
end;
function CoSimple.getHashCode(): long;
var
ref: ISimple;
begin
ref := fldValue;
if ref <> nil then begin
ref.queryInterface(getTypeData(PTypeInfo(typeInfo(ISimple)))^.guid, ref);
end;
result := long(ref);
end;
function CoSimple.toString(): AnsiString;
var
obj: TObject;
ref: ISimple;
begin
ref := fldValue;
if (ref = nil) or (ref.queryInterface(IObjectInstance, obj) <> system.S_OK) then begin
result := 'null';
exit;
end;
result := obj.toString();
end;
function CoSimple.getType(): int;
begin
result := Lang.TYPE_INTERFACE_RAW;
end;
function CoSimple.isNaN(): boolean;
begin
result := false;
end;
function CoSimple.isInfinite(): boolean;
begin
result := false;
end;
function CoSimple.asBoolean(): boolean;
begin
result := false;
end;
function CoSimple.asInt(): int;
begin
result := 0;
end;
function CoSimple.asLong(): long;
begin
result := 0;
end;
function CoSimple.asFloat(): float;
begin
result := 0;
end;
function CoSimple.asDouble(): double;
begin
result := 0;
end;
function CoSimple.asReal(): real;
begin
result := 0;
end;
function CoSimple.asAnsiString(): AnsiString;
begin
result := '';
end;
function CoSimple.asUnicodeString(): UnicodeString;
begin
result := '';
end;
function CoSimple.asObject(): TObject;
var
obj: TObject;
ref: ISimple;
begin
ref := fldValue;
if (ref = nil) or (ref.queryInterface(IObjectInstance, obj) <> system.S_OK) then begin
result := nil;
exit;
end;
result := obj;
end;
function CoSimple.asSimple(): ISimple;
begin
result := fldValue;
end;
{%endregion}
{%region CoUnknown}
constructor CoUnknown.create(const value: IUnknown);
begin
inherited create();
fldValue := value;
end;
function CoUnknown.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is CoUnknown) and ((CoUnknown(anot).fldValue as IUnknown) = (fldValue as IUnknown));
end;
function CoUnknown.getHashCode(): long;
begin
result := long(fldValue as IUnknown);
end;
function CoUnknown.toString(): AnsiString;
var
obj: TObject;
ref: IUnknown;
begin
ref := fldValue;
if (ref = nil) or (ref.queryInterface(IObjectInstance, obj) <> system.S_OK) then begin
result := 'null';
exit;
end;
result := obj.toString();
end;
function CoUnknown.getType(): int;
begin
result := Lang.TYPE_INTERFACE_RC;
end;
function CoUnknown.isNaN(): boolean;
begin
result := false;
end;
function CoUnknown.isInfinite(): boolean;
begin
result := false;
end;
function CoUnknown.asBoolean(): boolean;
begin
result := false;
end;
function CoUnknown.asInt(): int;
begin
result := 0;
end;
function CoUnknown.asLong(): long;
begin
result := 0;
end;
function CoUnknown.asFloat(): float;
begin
result := 0;
end;
function CoUnknown.asDouble(): double;
begin
result := 0;
end;
function CoUnknown.asReal(): real;
begin
result := 0;
end;
function CoUnknown.asAnsiString(): AnsiString;
begin
result := '';
end;
function CoUnknown.asUnicodeString(): UnicodeString;
begin
result := '';
end;
function CoUnknown.asObject(): TObject;
var
obj: TObject;
ref: IUnknown;
begin
ref := fldValue;
if (ref = nil) or (ref.queryInterface(IObjectInstance, obj) <> system.S_OK) then begin
result := nil;
exit;
end;
result := obj;
end;
function CoUnknown.asSimple(): ISimple;
begin
result := ISimple(Pointer(fldValue));
end;
{%endregion}
{%region RealRepresenter}
class function RealRepresenter.tab_04_00(power: int): real;
begin
case power and $1f of
0: result := 1;
1: result := reals[5].value;
2: result := reals[6].value;
3: result := reals[7].value;
4: result := reals[8].value;
5: result := reals[9].value;
6: result := reals[10].value;
7: result := reals[11].value;
8: result := reals[12].value;
9: result := reals[13].value;
10: result := reals[14].value;
11: result := reals[15].value;
12: result := reals[16].value;
13: result := reals[17].value;
14: result := reals[18].value;
15: result := reals[19].value;
16: result := reals[20].value;
17: result := reals[21].value;
18: result := reals[22].value;
19: result := reals[23].value;
20: result := reals[24].value;
21: result := reals[25].value;
22: result := reals[26].value;
23: result := reals[27].value;
24: result := reals[28].value;
25: result := reals[29].value;
26: result := reals[30].value;
27: result := reals[31].value;
28: result := reals[32].value;
29: result := reals[33].value;
30: result := reals[34].value;
31: result := reals[35].value;
else result := 0;
end;
end;
class function RealRepresenter.tab_08_05(power: int): real;
begin
case (power shr 5) and $0f of
0: result := 1;
1: result := reals[36].value;
2: result := reals[37].value;
3: result := reals[38].value;
4: result := reals[39].value;
5: result := reals[40].value;
6: result := reals[41].value;
7: result := reals[42].value;
8: result := reals[43].value;
9: result := reals[44].value;
10: result := reals[45].value;
11: result := reals[46].value;
12: result := reals[47].value;
13: result := reals[48].value;
14: result := reals[49].value;
15: result := reals[50].value;
else result := 0;
end;
end;
class function RealRepresenter.tab_12_09(power: int): real;
begin
case (power shr 9) and $0f of
0: result := 1;
1: result := reals[51].value;
2: result := reals[52].value;
3: result := reals[53].value;
4: result := reals[54].value;
5: result := reals[55].value;
6: result := reals[56].value;
7: result := reals[57].value;
8: result := reals[58].value;
9: result := reals[59].value;
else result := CoReal.POSITIVE_INFINITY;
end;
end;
class function RealRepresenter.round(value: real): long; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rcx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fild qword [rip+longs-@00+$08]
@00: fcomip st, st(1)
jnp @01
ffree st
fincstp
xor eax, eax
ret
@01: ja @03
ffree st
fincstp
mov rax, [rip+longs-@02+$08]
@02: ret
@03: lea rsp, [rsp-$08]
fistp qword [rsp+$00]
pop rax
end;
class function RealRepresenter.pow10(value: real; power: int): real;
begin
if power = CoInt.MIN_VALUE then begin
result := value * real(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) * CoReal.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) * real(0);
exit;
end;
result := value / tab_04_00(power) / tab_08_05(power) / tab_12_09(power);
exit;
end;
result := value;
end;
function RealRepresenter.parse(const str: AnsiString): real;
var
negative: boolean;
character: char;
idx: int;
len: int;
frac: int;
order: int;
temp: long;
digit: long;
intValue: long;
parsed: real;
begin
len := str.length;
if 0 >= len then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
negative := false;
idx := 0;
frac := 0;
order := 0;
intValue := 0;
character := str[1];
case character of
' ', '-', '+': begin
if character = '-' then begin
negative := true;
end;
inc(idx);
if idx >= len then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
character := str[idx + 1];
end;
end;
if ((character < '0') or (character > '9')) and (character <> '.') then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
if character <> '.' then begin
intValue := int(character) - int('0');
repeat
inc(idx);
if idx >= len then break;
character := str[idx + 1];
if (character < '0') or (character > '9') then break;
digit := int(character) - int('0');
temp := intValue * 10;
if (intValue > MUL_MIN) or (temp > CoLong.MAX_VALUE - digit) then begin
dec(frac);
end else begin
intValue := temp + digit;
end;
until false;
end;
if (idx < len) and (str[idx + 1] = '.') then begin
repeat
inc(idx);
if idx >= len then break;
character := str[idx + 1];
if (character < '0') or (character > '9') then break;
digit := int(character) - int('0');
temp := intValue * 10;
if (intValue <= MUL_MIN) and (temp <= CoLong.MAX_VALUE - digit) then begin
inc(frac);
intValue := temp + digit;
end;
until false;
end;
if intValue > 0 then while (frac > 0) and (intValue mod 10 = 0) do begin
dec(frac);
intValue := intValue div 10;
end;
parsed := CoLong.toReal(intValue);
if negative then begin
negative := false;
parsed := parsed / real(-1);
end;
if idx < len then begin
character := str[idx + 1];
if (character = 'E') or (character = 'e') then begin
inc(idx);
if idx >= len then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
character := str[idx + 1];
case character of
'-', '+': begin
if character = '-' then begin
negative := true;
end;
inc(idx);
if idx >= len then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
character := str[idx + 1];
end;
end;
if (character < '0') or (character > '9') then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
order := int(character) - int('0');
repeat
inc(idx);
if idx >= len then break;
character := str[idx + 1];
if (character < '0') or (character > '9') then break;
order := 10 * order + int(character) - int('0');
if order > 9999 then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
until false;
if negative then order := -order;
end;
end;
if idx < len then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
result := pow10(parsed, order - frac);
end;
function RealRepresenter.represent(value: real): char_Array1d;
var
expForm: boolean;
character: char;
idx: int;
len: int;
order: int;
dotIdx: int;
ordDigits: int;
ordLength: int;
sigDigits: int;
intVal: long;
maxVal: long;
minVal: real;
bits: RealStruct;
buf: char_Array1d;
cpy: char_Array1d;
begin
buf := &Array.newChar1d(32);
&Array.fillPrimitives(buf, 0, 32, '0');
bits.value := value;
len := 0;
if bits.exponent < 0 then begin
buf[len] := '-';
inc(len);
value := value / real(-1);
end else
if fldSigSign then begin
buf[len] := '+';
inc(len);
end;
if (bits.exponent and $7fff = 0) and (bits.significand = 0) then begin
buf[len + 1] := '.';
if fldSigAll then begin
inc(len, fldSigDigits + 1);
end else begin
inc(len, 3);
end;
if fldExpForm then begin
buf[len] := 'E';
inc(len);
if fldOrdSign then begin
buf[len] := '+';
inc(len);
end;
if fldOrdAll then begin
inc(len, fldOrdDigits);
end else begin
inc(len);
end;
end;
end else begin
sigDigits := fldSigDigits;
minVal := pow10(1, -CoInt.min(6, sigDigits));
order := CoReal.toInt(Math.floor(Math.log10(value)));
expForm := fldExpForm or (value < minVal) or (value >= fldLimitValueWithoutExponent);
if expForm then begin
intVal := round(pow10(value, sigDigits - order - 1));
if intVal < fldMinRepresentValue then begin
intVal := intVal * 10;
dec(order);
end;
if intVal > fldMaxRepresentValue then begin
intVal := intVal div 10;
inc(order);
end;
dotIdx := len + 1;
end else
if value < 1 then begin
intVal := round(pow10(value, sigDigits - 1));
dotIdx := len + 1;
end else
if value < fldLimitValueWithFractialPart then begin
intVal := round(pow10(value, sigDigits - order - 1));
if intVal < fldMinRepresentValue then begin
intVal := intVal * 10;
dec(order);
end;
if intVal > fldMaxRepresentValue then begin
intVal := intVal div 10;
inc(order);
end;
dotIdx := len + order + 1;
end else begin
intVal := round(value);
maxVal := fldMaxRepresentValue;
if intVal > maxVal then intVal := maxVal;
dotIdx := len + sigDigits;
end;
buf[dotIdx] := '.';
for idx := len + sigDigits - 1 downto len do begin
if idx < dotIdx then begin
buf[idx] := char((intVal mod 10) + int('0'));
end else begin
buf[idx + 1] := char((intVal mod 10) + int('0'));
end;
intVal := intVal div 10;
end;
inc(len, sigDigits + 1);
if not fldSigAll then repeat
character := buf[len - 1];
if (character <> '0') and (character <> '.') then break;
dec(len);
if character = '.' 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] := '-';
inc(len);
order := -order;
end else
if fldOrdSign then begin
buf[len] := '+';
inc(len);
end;
if fldOrdAll then begin
ordDigits := fldOrdDigits;
end else begin
ordDigits := 1;
end;
if (ordDigits = 1) and (order >= 10) then inc(ordDigits);
if (ordDigits = 2) and (order >= 100) then inc(ordDigits);
if (ordDigits = 3) and (order >= 1000) then inc(ordDigits);
ordLength := len + ordDigits;
for idx := ordLength - 1 downto len do begin
buf[idx] := char((order mod 10) + int('0'));
order := order div 10;
end;
len := ordLength;
end;
end;
if len >= 32 then begin
result := buf;
exit;
end;
cpy := &Array.newChar1d(len);
&Array.copyPrimitives(buf, 0, cpy, 0, len);
result := cpy;
end;
constructor RealRepresenter.create(sigDigits, ordDigits: int; sigAll, ordAll, expForm, sigSign, ordSign: boolean);
var
idx: int;
maxValue: long;
begin
inherited create();
if sigDigits < MIN_SIGNIFICAND_DIGITS then sigDigits := MIN_SIGNIFICAND_DIGITS;
if sigDigits > MAX_SIGNIFICAND_DIGITS then sigDigits := MAX_SIGNIFICAND_DIGITS;
if ordDigits < MIN_ORDER_DIGITS then ordDigits := MIN_ORDER_DIGITS;
if ordDigits > MAX_ORDER_DIGITS then ordDigits := MAX_ORDER_DIGITS;
maxValue := 1;
for idx := sigDigits - 2 downto 0 do maxValue := maxValue * 10;
fldSigAll := sigAll;
fldOrdAll := ordAll;
fldSigSign := sigSign;
fldOrdSign := ordSign;
fldExpForm := expForm;
fldSigDigits := sigDigits;
fldOrdDigits := ordDigits;
fldMinRepresentValue := maxValue;
fldMaxRepresentValue := maxValue * 10 - 1;
fldLimitValueWithFractialPart := pow10(1, sigDigits - 1);
fldLimitValueWithoutExponent := pow10(1, sigDigits);
end;
function RealRepresenter.equals(anot: TObject): boolean;
var
repr: RealRepresenter;
begin
if anot = self then begin
result := true;
exit;
end;
if not(anot is RealRepresenter) then begin
result := false;
exit;
end;
repr := RealRepresenter(anot);
result :=
(repr.fldSigAll = fldSigAll) and
(repr.fldOrdAll = fldOrdAll) and
(repr.fldSigSign = fldSigSign) and
(repr.fldOrdSign = fldOrdSign) and
(repr.fldExpForm = fldExpForm) and
(repr.fldSigDigits = fldSigDigits) and
(repr.fldOrdDigits = fldOrdDigits)
;
end;
function RealRepresenter.getHashCode(): long;
begin
result := 0;
if fldSigAll then inc(result, $01);
if fldOrdAll then inc(result, $02);
if fldSigSign then inc(result, $04);
if fldOrdSign then inc(result, $08);
if fldExpForm then inc(result, $10);
inc(result, ((fldSigDigits - MIN_SIGNIFICAND_DIGITS) shl 8) + ((fldOrdDigits - MIN_ORDER_DIGITS) shl 16));
end;
function RealRepresenter.writeTo(const dst: char_Array1d; offset: int; value: real): int;
var
length: int;
repr: char_Array1d;
begin
repr := toCharArray(value);
length := system.length(repr);
&Array.copyPrimitives(repr, 0, dst, offset, length);
result := offset + length;
end;
function RealRepresenter.parseFloat(const str: AnsiString): float;
var
value: real;
begin
if (str = '+Infinity') or (str = 'Infinity') then begin
result := CoFloat.POSITIVE_INFINITY;
exit;
end;
if (str = '-Infinity') then begin
result := CoFloat.NEGATIVE_INFINITY;
exit;
end;
if (str = 'NaN') then begin
result := CoFloat.NAN;
exit;
end;
value := parse(str);
if (value < -CoFloat.MAX_VALUE) or (value > CoFloat.MAX_VALUE) then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
result := CoReal.toFloat(value);
end;
function RealRepresenter.parseDouble(const str: AnsiString): double;
var
value: real;
begin
if (str = '+Infinity') or (str = 'Infinity') then begin
result := CoDouble.POSITIVE_INFINITY;
exit;
end;
if (str = '-Infinity') then begin
result := CoDouble.NEGATIVE_INFINITY;
exit;
end;
if (str = 'NaN') then begin
result := CoDouble.NAN;
exit;
end;
value := parse(str);
if (value < -CoDouble.MAX_VALUE) or (value > CoDouble.MAX_VALUE) then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
result := CoReal.toDouble(value);
end;
function RealRepresenter.parseReal(const str: AnsiString): real;
var
value: real;
begin
if (str = '+Infinity') or (str = 'Infinity') then begin
result := CoReal.POSITIVE_INFINITY;
exit;
end;
if (str = '-Infinity') then begin
result := CoReal.NEGATIVE_INFINITY;
exit;
end;
if (str = 'NaN') then begin
result := CoReal.NAN;
exit;
end;
value := parse(str);
if (value < -CoReal.MAX_VALUE) or (value > CoReal.MAX_VALUE) then begin
raise NumberFormatException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.number-format'));
end;
result := value;
end;
function RealRepresenter.toString(value: real): AnsiString;
begin
if CoReal.isNaN(value) then begin
result := 'NaN';
exit;
end;
if value = CoReal.POSITIVE_INFINITY then begin
result := 'Infinity';
exit;
end;
if value = CoReal.NEGATIVE_INFINITY then begin
result := '-Infinity';
exit;
end;
result := AnsiString.create(represent(value));
end;
function RealRepresenter.toCharArray(value: real): char_Array1d;
begin
if CoReal.isNaN(value) then begin
result := AnsiString('NaN').toCharArray();
exit;
end;
if value = CoReal.POSITIVE_INFINITY then begin
result := AnsiString('Infinity').toCharArray();
exit;
end;
if value = CoReal.NEGATIVE_INFINITY then begin
result := AnsiString('-Infinity').toCharArray();
exit;
end;
result := represent(value);
end;
{%endregion}
{%region Mutex}
constructor Mutex.create();
begin
inherited create();
mutexCreate(@fldMutex);
end;
destructor Mutex.destroy;
begin
mutexDestroy(@fldMutex);
inherited destroy;
end;
procedure Mutex.beginSynchronized();
begin
mutexLock(@fldMutex);
end;
procedure Mutex.endSynchronized();
begin
mutexUnlock(@fldMutex);
end;
function Mutex.isHold(): boolean;
begin
result := mutexIsHold(@fldMutex);
end;
{%endregion}
{%region Monitor}
class function Monitor.newThreadStateEntryArray1d(length: int): ThreadStateEntry_Array1d;
begin
result := nil;
setLength(result, length);
end;
procedure Monitor.resume(const entry: ThreadStateEntry; needSignal: boolean);
begin
with fldOwnedBy do begin
state := OWNEDBY;
threadId := entry.threadId;
lockCount := entry.lockCount;
if needSignal then eventSetSignalled(threadGetEvent(threadId));
end;
end;
procedure Monitor.extractEntry();
var
index: int;
length: int;
entries: ThreadStateEntry_Array1d;
entry: ThreadStateEntry;
label
break_label0;
begin
entries := fldEntries;
if entries = nil then with fldOwnedBy do begin
state := 0;
threadId := 0;
lockCount := 0;
exit;
end;
length := fldLength;
begin
for index := 0 to length - 1 do with entries[index] do if state = BLOCKED then begin
entry.threadId := threadId;
entry.lockCount := lockCount;
goto break_label0;
end;
with fldOwnedBy do begin
state := 0;
threadId := 0;
lockCount := 0;
exit;
end;
end;
break_label0:
dec(length);
&Array.copyRaw(entries[index + 1], entries[index], (length - index) * sizeof(ThreadStateEntry));
with entries[length] do begin
state := 0;
threadId := 0;
lockCount := 0;
end;
fldLength := length;
resume(entry, true);
end;
procedure Monitor.extractEntry(threadId: long);
var
index: int;
length: int;
threadIdArgument: long absolute threadId;
entries: ThreadStateEntry_Array1d;
entry: ThreadStateEntry;
label
break_label0;
begin
entries := fldEntries;
if entries = nil then with fldOwnedBy do begin
state := 0;
threadId := 0;
lockCount := 0;
exit;
end;
length := fldLength;
begin
for index := 0 to length - 1 do with entries[index] do if threadId = threadIdArgument then begin
entry.threadId := threadId;
entry.lockCount := lockCount;
goto break_label0;
end;
with fldOwnedBy do begin
state := 0;
threadId := 0;
lockCount := 0;
exit;
end;
end;
break_label0:
dec(length);
&Array.copyRaw(entries[index + 1], entries[index], (length - index) * sizeof(ThreadStateEntry));
with entries[length] do begin
state := 0;
threadId := 0;
lockCount := 0;
end;
fldLength := length;
resume(entry, false);
end;
procedure Monitor.appendEntry(const entry: ThreadStateEntry);
var
length: int;
entriesData: ThreadStateEntry_Array1d;
entriesCopy: ThreadStateEntry_Array1d;
begin
entriesData := fldEntries;
if entriesData = nil then begin
entriesData := newThreadStateEntryArray1d($0f);
fldEntries := entriesData;
with entriesData[0] do begin
state := entry.state;
threadId := entry.threadId;
lockCount := entry.lockCount;
end;
fldLength := 1;
exit;
end;
length := fldLength;
if length = system.length(entriesData) then begin
entriesCopy := newThreadStateEntryArray1d((length shl 1) or 1);
&Array.copyRaw(entriesData[0], entriesCopy[0], length * sizeof(ThreadStateEntry));
entriesData := entriesCopy;
fldEntries := entriesData;
end;
with entriesData[length] do begin
state := entry.state;
threadId := entry.threadId;
lockCount := entry.lockCount;
end;
fldLength := length + 1;
end;
function Monitor.getEntryIndexByState(state: long): int;
var
index: int;
length: int;
entries: ThreadStateEntry_Array1d;
label
break_label0;
begin
entries := fldEntries;
if entries = nil then begin
result := -1;
exit;
end;
length := fldLength;
begin
for index := 0 to length - 1 do if entries[index].state = state then goto break_label0;
result := -1;
exit;
end;
break_label0:
result := index;
end;
function Monitor.getEntryIndexByThreadId(threadId: long): int;
var
index: int;
length: int;
entries: ThreadStateEntry_Array1d;
label
break_label0;
begin
entries := fldEntries;
if entries = nil then begin
result := -1;
exit;
end;
length := fldLength;
begin
for index := 0 to length - 1 do if entries[index].threadId = threadId then goto break_label0;
result := -1;
exit;
end;
break_label0:
result := index;
end;
procedure Monitor.beginSynchronized();
var
isBlocked: boolean;
currentId: long;
entry: ThreadStateEntry;
begin
isBlocked := false;
currentId := threadGetCurrentId();
inherited beginSynchronized();
try
with fldOwnedBy do begin
entry.state := state;
entry.threadId := threadId;
entry.lockCount := lockCount;
end;
if entry.state = 0 then with fldOwnedBy do begin
state := OWNEDBY;
threadId := currentId;
lockCount := 1;
end else
if entry.threadId = currentId then with fldOwnedBy do begin
lockCount := entry.lockCount + 1;
end else begin
entry.state := BLOCKED;
entry.threadId := currentId;
entry.lockCount := 1;
appendEntry(entry);
isBlocked := true;
end;
finally
inherited endSynchronized();
end;
if isBlocked then begin
eventWaitSignalled(threadGetEvent(currentId), 0, 0);
end;
end;
procedure Monitor.endSynchronized();
var
isNotOwnedBy: boolean;
currentId: long;
entry: ThreadStateEntry;
begin
isNotOwnedBy := false;
currentId := threadGetCurrentId();
inherited beginSynchronized();
try
with fldOwnedBy do begin
entry.state := state;
entry.threadId := threadId;
entry.lockCount := lockCount;
end;
if (entry.state = 0) or (entry.threadId <> currentId) then begin
isNotOwnedBy := true;
end else
with fldOwnedBy do begin
lockCount := entry.lockCount - 1;
if lockCount = 0 then extractEntry();
end;
finally
inherited endSynchronized();
end;
if isNotOwnedBy then begin
raise IllegalMonitorStateException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-state.monitor'));
end;
end;
procedure Monitor.notify();
var
isNotOwnedBy: boolean;
index: int;
currentId: long;
entry: ThreadStateEntry;
begin
isNotOwnedBy := false;
currentId := threadGetCurrentId();
inherited beginSynchronized();
try
with fldOwnedBy do begin
entry.state := state;
entry.threadId := threadId;
end;
if (entry.state = 0) or (entry.threadId <> currentId) then begin
isNotOwnedBy := true;
end else begin
index := getEntryIndexByState(WAITING);
if index < 0 then begin
inc(fldNotifies);
end else begin
fldEntries[index].state := BLOCKED;
end;
end;
finally
inherited endSynchronized();
end;
if isNotOwnedBy then begin
raise IllegalMonitorStateException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-state.monitor'));
end;
end;
procedure Monitor.notifyAll();
var
isNotOwnedBy: boolean;
isNotBlocked: boolean;
index: int;
currentId: long;
entries: ThreadStateEntry_Array1d;
entry: ThreadStateEntry;
begin
isNotOwnedBy := false;
currentId := threadGetCurrentId();
inherited beginSynchronized();
try
with fldOwnedBy do begin
entry.state := state;
entry.threadId := threadId;
end;
if (entry.state = 0) or (entry.threadId <> currentId) then begin
isNotOwnedBy := true;
end else begin
entries := fldEntries;
isNotBlocked := true;
for index := fldLength - 1 downto 0 do with entries[index] do if state <> BLOCKED then begin
isNotBlocked := false;
state := BLOCKED;
end;
if isNotBlocked then begin
inc(fldNotifies);
end;
end;
finally
inherited endSynchronized();
end;
if isNotOwnedBy then begin
raise IllegalMonitorStateException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-state.monitor'));
end;
end;
procedure Monitor.wait();
begin
wait(0, 0);
end;
procedure Monitor.wait(timeInMillis: long);
begin
wait(timeInMillis, 0);
end;
procedure Monitor.wait(timeInMillis: long; timeInNanos: int);
var
isWaiting: boolean;
isNotOwnedBy: boolean;
index: int;
currentId: long;
notifies: long;
event: long;
entry: ThreadStateEntry;
begin
if timeInMillis < 0 then begin
raise IllegalArgumentException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument'), [ CoAnsiString.create('timeInMillis') ]));
end;
if (timeInNanos < 0) or (timeInNanos > 999999) then begin
raise IllegalArgumentException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument'), [ CoAnsiString.create('timeInNanos') ]));
end;
isWaiting := false;
isNotOwnedBy := false;
currentId := threadGetCurrentId();
inherited beginSynchronized();
try
with fldOwnedBy do begin
entry.state := state;
entry.threadId := threadId;
entry.lockCount := lockCount;
end;
if (entry.state = 0) or (entry.threadId <> currentId) then begin
isNotOwnedBy := true;
end else begin
notifies := fldNotifies;
if notifies <> 0 then begin
fldNotifies := notifies - 1;
end else begin
extractEntry();
entry.state := WAITING;
appendEntry(entry);
isWaiting := true;
end;
end;
finally
inherited endSynchronized();
end;
if isNotOwnedBy then begin
raise IllegalMonitorStateException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-state.monitor'));
end;
if isWaiting then begin
event := threadGetEvent(currentId);
eventWaitSignalled(event, timeInMillis, timeInNanos);
repeat
inherited beginSynchronized();
try
with fldOwnedBy do begin
entry.state := state;
entry.threadId := threadId;
end;
if entry.state = 0 then begin
extractEntry(currentId);
isWaiting := false;
end else
if entry.threadId = currentId then begin
isWaiting := false;
end else begin
index := getEntryIndexByThreadId(currentId);
fldEntries[index].state := BLOCKED;
end;
finally
inherited endSynchronized();
end;
if not isWaiting then break;
eventWaitSignalled(event, 0, 0);
until false;
end;
end;
function Monitor.isHold(): boolean;
begin
result := fldOwnedBy.state <> 0;
end;
{%endregion}
{%region Thread}
class procedure Thread.yield();
begin
threadSleep(0, 0);
end;
class procedure Thread.sleep(timeInMillis: long);
begin
if timeInMillis < 0 then begin
raise IllegalArgumentException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument'), [ CoAnsiString.create('timeInMillis') ]));
end;
threadSleep(timeInMillis, 0);
end;
class procedure Thread.sleep(timeInMillis: long; timeInNanos: int);
begin
if timeInMillis < 0 then begin
raise IllegalArgumentException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument'), [ CoAnsiString.create('timeInMillis') ]));
end;
if (timeInNanos < 0) or (timeInNanos > 999999) then begin
raise IllegalArgumentException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument'), [ CoAnsiString.create('timeInNanos') ]));
end;
threadSleep(timeInMillis, timeInNanos);
end;
class function Thread.activeCount(): int;
begin
result := threadGetActiveCount();
end;
{$IFNDEF LIBRARY}
class function Thread.enumerate(): Thread_Collection1d;
var
idx: int;
len: int;
threadIds: long_Array1d;
threadRefs: Thread_Array1d;
begin
threadIds := threadEnumerateIds1();
len := length(threadIds);
threadRefs := Thread_Array1d(&Array.newTObject1d(len));
for idx := len - 1 downto 0 do begin
threadRefs[idx] := threadGet(threadIds[idx], true);
end;
result := ThreadCollection.create(threadRefs);
end;
{$ENDIF}
class function Thread.current(): Thread;
begin
result := threadGet(threadGetCurrentId());
end;
constructor Thread.create(threadId1, threadId2: long; external: boolean);
var
flags: byte;
begin
inherited create();
flags := FLAG_AUTO_FREE;
if external then inc(flags, FLAG_EXTERNAL);
if threadId2 = -2 then threadId2 := threadId1;
fldStarted := true;
fldCreated := false;
fldTerminated := false;
fldFlags := flags;
fldPriority := threadGetPriority(threadId2);
fldStackSize := 0;
fldThreadId1 := threadId1;
fldThreadId2 := threadId2;
fldEnumerated := 0;
fldDescription := threadGetDescription(threadId2);
fldTarget := nil;
fldJoinMonitor := nil;
end;
procedure Thread.notifyJoined();
begin
with fldJoinMonitor do begin
beginSynchronized();
try
fldTerminated := true;
notifyAll();
finally
endSynchronized();
end;
end;
end;
procedure Thread.freeIfNecessary();
begin
if (self <> nil) and (fldEnumerated = 0) and (fldFlags <> 0) then destroy;
end;
procedure Thread.setDescription(const newDescription: AnsiString);
begin
if getFlag(FLAG_EXTERNAL) then exit;
fldDescription := newDescription;
threadSetDescription(fldThreadId2, newDescription);
end;
function Thread.isStarted(): boolean; assembler; nostackframe;
asm
mov eax, true
{$IFDEF WINDOWS}
xchg byte [rcx+offset fldStarted], al
{$ELSE}
xchg byte [rdi+offset fldStarted], al
{$ENDIF}
movzx eax, al
end;
function Thread.getFlag(mask: int): boolean;
begin
result := (fldFlags and mask) <> 0;
end;
function Thread.getPriority(): int;
var
locPriority: int;
begin
locPriority := threadGetPriority(fldThreadId2);
if locPriority = UD_PRIORITY then locPriority := fldPriority;
result := locPriority;
end;
function Thread.getDescription(): AnsiString;
var
locDescription: AnsiString;
begin
locDescription := threadGetDescription(fldThreadId2);
if locDescription = '' then locDescription := fldDescription;
result := locDescription;
end;
constructor Thread.create(stackSize: long; freeOnTerminate: boolean);
begin
create(nil, stackSize, freeOnTerminate);
end;
procedure Thread.setPriority(newPriority: int);
begin
if getFlag(FLAG_EXTERNAL) then exit;
if newPriority < MIN_PRIORITY then newPriority := MIN_PRIORITY;
if newPriority > MAX_PRIORITY then newPriority := MAX_PRIORITY;
fldPriority := newPriority;
threadSetPriority(fldThreadId2, newPriority);
end;
constructor Thread.create(target: Runnable; freeOnTerminate: boolean);
begin
create(target, DEFAULT_STACK_SIZE, freeOnTerminate);
end;
constructor Thread.create(target: Runnable; stackSize: long; freeOnTerminate: boolean);
var
flags: byte;
begin
inherited create();
flags := 0;
if freeOnTerminate then inc(flags, FLAG_AUTO_FREE);
if stackSize < MIN_STACK_SIZE then stackSize := MIN_STACK_SIZE;
if stackSize > MAX_STACK_SIZE then stackSize := MAX_STACK_SIZE;
fldStarted := false;
fldCreated := false;
fldTerminated := false;
fldFlags := flags;
fldPriority := NORM_PRIORITY;
fldStackSize := stackSize;
fldThreadId1 := -1;
fldThreadId2 := -1;
fldEnumerated := 0;
fldDescription := '';
fldTarget := target;
fldJoinMonitor := nil;
end;
destructor Thread.destroy;
begin
fldJoinMonitor.free();
inherited destroy;
end;
procedure Thread.run();
begin
end;
procedure Thread.start();
begin
if isStarted() then begin
raise IllegalThreadStateException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-state.thread'));
end;
fldJoinMonitor := Monitor.create();
if not threadCreate(@threadFunction, self, fldStackSize) then begin
raise errorOutOfMemory;
end;
fldCreated := true;
end;
procedure Thread.join();
var
jmon: Monitor;
begin
jmon := fldJoinMonitor;
if jmon = nil then begin
raise IllegalThreadStateException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-state.thread'));
end;
with jmon do begin
beginSynchronized();
try
if not fldTerminated then wait(0, 0);
finally
endSynchronized();
end;
end;
end;
procedure Thread.join(timeInMillis: long);
var
jmon: Monitor;
begin
if timeInMillis < 0 then begin
raise IllegalArgumentException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument'), [ CoAnsiString.create('timeInMillis') ]));
end;
jmon := fldJoinMonitor;
if jmon = nil then begin
raise IllegalThreadStateException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-state.thread'));
end;
with jmon do begin
beginSynchronized();
try
if not fldTerminated then wait(timeInMillis, 0);
finally
endSynchronized();
end;
end;
end;
procedure Thread.join(timeInMillis: long; timeInNanos: int);
var
jmon: Monitor;
begin
if timeInMillis < 0 then begin
raise IllegalArgumentException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument'), [ CoAnsiString.create('timeInMillis') ]));
end;
if (timeInNanos < 0) or (timeInNanos > 999999) then begin
raise IllegalArgumentException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument'), [ CoAnsiString.create('timeInNanos') ]));
end;
jmon := fldJoinMonitor;
if jmon = nil then begin
raise IllegalThreadStateException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-state.thread'));
end;
with jmon do begin
beginSynchronized();
try
if not fldTerminated then wait(timeInMillis, timeInNanos);
finally
endSynchronized();
end;
end;
end;
function Thread._addref(): int; {$IFDEF WINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
begin
result := -1;
end;
function Thread._release(): int; {$IFDEF WINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
begin
result := -1;
end;
function Thread.isAlive(): boolean;
begin
result := fldCreated or threadIsAlive(fldThreadId1, fldThreadId2);
end;
function Thread.isExternal(): boolean;
begin
result := getFlag(FLAG_EXTERNAL);
end;
{%endregion}
{%region Throwable}
constructor Throwable.create(const message: AnsiString; helpContext: int);
var
count: int;
length: int;
buffer: Pointer_Array1d;
stackTrace: Pointer_Array1d;
begin
inherited create();
if self is Error then begin
stackTrace := nil;
end else begin
length := $1f;
stackTrace := &Array.newPointer1d(length);
repeat
count := int(system.captureBackTrace(1, length, Pointer(stackTrace)));
if count < length then begin
buffer := &Array.newPointer1d(count);
&Array.copyRaw(stackTrace[0], buffer[0], long(count) * sizeof(Pointer));
stackTrace := buffer;
break;
end;
if count = CoInt.MAX_VALUE then break;
length := (length shl 1) or 1;
stackTrace := &Array.newPointer1d(length);
until false;
end;
fldMessage := message;
fldHelpContext := helpContext;
fldStackTrace := stackTrace;
end;
procedure Throwable.printStackTrace();
var
index: int;
infol: int;
infoa: AnsiString;
infos: ShortString;
stackTrace: Pointer_Array1d;
element: Pointer;
begin
if isConsole then begin
writeln(system.errOutput, toString(){$IFDEF WINDOWS}.toUTF16(){$ENDIF});
stackTrace := fldStackTrace;
for index := 0 to system.length(stackTrace) - 1 do begin
element := stackTrace[index];
if element <> nil then begin
infos := system.backTraceStrFunc(element);
infol := system.length(infos);
infoa := AnsiString.create(infol);
&Array.copyRaw(infos[1], infoa[1], long(infol) * sizeof(char));
writeln(system.errOutput, infoa{$IFDEF WINDOWS}.toUTF16(){$ENDIF});
end;
end;
end;
end;
function Throwable.toString(): AnsiString;
var
locMessage: AnsiString;
begin
locMessage := fldMessage;
if locMessage.length <= 0 then begin
result := getClass().getCanonicalName();
exit;
end;
result := getClass().getCanonicalName() + ': ' + locMessage;
end;
function Throwable.clone(): Throwable;
var
copy: Throwable;
begin
copy := Throwable(classType().create());
copy.fldHelpContext := fldHelpContext;
copy.fldMessage := fldMessage;
copy.fldStackTrace := fldStackTrace;
result := copy;
end;
{%endregion}
{%region MemoryError}
procedure MemoryError.freeAllow();
begin
fldFreeDisallowed := false;
end;
procedure MemoryError.freeDisallow();
begin
fldFreeDisallowed := true;
end;
procedure MemoryError.freeInstance();
begin
if not fldFreeDisallowed then begin
inherited freeInstance();
end;
end;
{%endregion}
{%region AResource }
class procedure AResource.updateResourceStringReferences();
var
index: long;
address: Pointer;
rlist: PResourceStringInitEntry;
begin
with resourcestringInits^ do for index := 0 to length - 1 do begin
rlist := list[index];
address := rlist^.address;
while address <> nil do begin
AnsiString(address^) := rlist^.data^.value;
inc(rlist);
address := rlist^.address;
end;
end;
end;
class procedure AResource.setResourceString(const __unitName, rstrName, rstrValue: AnsiString);
var
index: long;
unitUpper: AnsiString;
rstrLower: AnsiString;
rfinish: PResourceStringStruct;
rstring: PResourceStringStruct;
begin
unitUpper := __unitName.toUpperCase();
rstrLower := (__unitName + '.' + rstrName).toLowerCase();
with resourcestringTables^ do for index := 0 to length - 1 do with list[index] do begin
rstring := start^;
if rstring^.name = unitUpper then begin
inc(rstring);
rfinish := finish^;
while rstring < rfinish do begin
if rstring^.name = rstrLower then begin
rstring^.value := rstrValue;
break;
end;
inc(rstring);
end;
break;
end;
end;
updateResourceStringReferences();
end;
class function AResource.getResourceString(const __unitName, rstrName: AnsiString): AnsiString;
var
index: long;
unitUpper: AnsiString;
rstrLower: AnsiString;
rfinish: PResourceStringStruct;
rstring: PResourceStringStruct;
begin
unitUpper := __unitName.toUpperCase();
rstrLower := (__unitName + '.' + rstrName).toLowerCase();
with resourcestringTables^ do for index := 0 to length - 1 do with list[index] do begin
rstring := start^;
if rstring^.name = unitUpper then begin
inc(rstring);
rfinish := finish^;
while rstring < rfinish do begin
if rstring^.name = rstrLower then begin
result := rstring^.value;
exit;
end;
inc(rstring);
end;
break;
end;
end;
result := '';
end;
class function AResource.unitToResourceName(const __unitName, rsrcName: AnsiString): AnsiString;
begin
if __unitName.length <= 0 then begin
result := ('/' + rsrcName).toUpperCase();
exit;
end;
result := ('/' + __unitName.replaceAll('.', '/') + '/' + rsrcName).toUpperCase();
end;
class function AResource.unitToTextResourceName(const __unitName, rsrcName: AnsiString): AnsiString;
begin
if __unitName.length <= 0 then begin
result := ('/' + rsrcName + '.TXT').toUpperCase();
exit;
end;
result := ('/' + __unitName.replaceAll('.', '/') + '/' + rsrcName + '.TXT').toUpperCase();
end;
class function AResource.readResourceAsAnsiString(const rsrcName: AnsiString): AnsiString;
var
size: int;
inst: long;
desc: long;
handle: long;
rstring: AnsiString;
data: Pointer;
begin
inst := system.hInstance();
desc := long(system.findResource(inst, rsrcName, system.PAnsiChar({$IFDEF WINDOWS}windows{$ELSE}system{$ENDIF}.RT_RCDATA)));
if desc = 0 then begin
result := '';
exit;
end;
handle := long(system.loadResource(inst, desc));
if handle = 0 then begin
result := '';
exit;
end;
size := int(system.sizeofResource(inst, desc));
data := system.lockResource(handle);
try
rstring := AnsiString.create(size);
&Array.copyRaw(data^, rstring[1], size);
result := rstring;
finally
system.unlockResource(handle);
system.freeResource(handle);
end;
end;
class function AResource.readUnitResourceAsAnsiString(const __unitName, rstrName: AnsiString): AnsiString;
begin
result := readResourceAsAnsiString(unitToTextResourceName(__unitName, rstrName));
end;
{%endregion}
{%region Lang}
class function Lang.getGuidIndex(const guid: system.TGuid; capacity: int): int;
var
gvec: long2 absolute guid;
begin
result := int(((gvec[0] xor gvec[1]) and CoLong.MAX_VALUE) mod capacity);
end;
class procedure Lang.registerInterfaces(const iinfos: array of Pointer);
var
idx: int;
len: int;
oldIdx: int;
oldLen: int;
oldCap: int;
newIdx: int;
newLen: int;
newCap: int;
iinfop: PTypeInfo;
idatap: PTypeData;
iguidp: system.PGuid;
oldEntry: InterfaceEntry;
newEntry: InterfaceEntry;
oldTable: InterfaceEntry_Array1d;
newTable: InterfaceEntry_Array1d;
begin
len := length(iinfos);
if len <= 0 then exit;
oldTable := registeredInterfacesEntries;
oldLen := registeredInterfacesLength;
oldCap := length(oldTable);
newLen := oldLen + len;
if newLen < 0 then begin
raise BufferTooLargeError.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, '!error.buffer-too-large'));
end;
newCap := oldCap;
if newLen > ((newCap shl 1) or 1) then begin
repeat
newCap := (newCap shl 1) or 1;
until newLen <= ((newCap shl 1) or 1);
newTable := InterfaceEntry_Array1d(&Array.newTObject1d(newCap));
for oldIdx := oldCap - 1 downto 0 do begin
oldEntry := oldTable[oldIdx];
while oldEntry <> nil do begin
newIdx := getGuidIndex(oldEntry.guid, newCap);
newEntry := oldEntry;
oldEntry := oldEntry.next;
newEntry.next := newTable[newIdx];
newTable[newIdx] := newEntry;
end;
end;
oldCap := newCap;
oldTable := newTable;
registeredInterfacesEntries := newTable;
end;
for idx := 0 to len - 1 do begin
iinfop := PTypeInfo(iinfos[idx]);
idatap := getTypeData(iinfop);
iguidp := @(idatap^.guid);
oldIdx := getGuidIndex(iguidp^, oldCap);
oldTable[oldIdx] := InterfaceEntry.create(iguidp^, iinfop, oldTable[oldIdx]);
end;
registeredInterfacesLength := newLen;
end;
class function Lang.isType(const typRef, typIID: ShortString): boolean;
var
len: int;
begin
len := length(typIID);
result := (len > 0) and (length(typRef) = len) and (&Array.compfne(typRef[1], typIID[1], 0, len) = &Array.NOT_FOUND);
end;
class function Lang.isType(const typRef, typIID: system.TGuid): boolean;
begin
result := &Array.compfne(typRef, typIID, 3, 2) = &Array.NOT_FOUND;
end;
class function Lang.isInstance(objRef: ISimple; const typIID: ShortString): boolean;
var
tmpIID: system.TGuid;
tmpRef: Pointer;
begin
result := guidTryParse(typIID, tmpIID) and (objRef <> nil) and (objRef.queryInterface(tmpIID, tmpRef) = system.S_OK);
end;
class function Lang.isInstance(objRef: ISimple; const typIID: system.TGuid): boolean;
var
tmpRef: TObject;
begin
result := (objRef <> nil) and (objRef.queryInterface(IObjectInstance, tmpRef) = system.S_OK) and (tmpRef.getInterfaceEntry(typIID) <> nil);
end;
class function Lang.isInstance(objRef: ISimple; const typRef: system.TClass): boolean;
var
tmpRef: TObject;
begin
result := (objRef <> nil) and (objRef.queryInterface(IObjectInstance, tmpRef) = system.S_OK) and tmpRef.inheritsFrom(typRef);
end;
class function Lang.isInstance(objRef: IUnknown; const typIID: ShortString): boolean;
var
tmpIID: system.TGuid;
tmpRef: Pointer;
begin
result := guidTryParse(typIID, tmpIID) and (objRef <> nil) and (objRef.queryInterface(tmpIID, tmpRef) = system.S_OK);
end;
class function Lang.identityHashCode(objRef: TObject): long;
begin
result := long(objRef);
end;
class function Lang.identityHashCode(objRef: ISimple): long;
var
tmpRef: long;
begin
tmpRef := 0;
if (objRef <> nil) and (objRef.queryInterface(IObjectInstance, tmpRef) <> system.S_OK) then begin
result := 0;
exit;
end;
result := tmpRef;
end;
class function Lang.identityHashCode(objRef: IUnknown): long;
var
tmpRef: long;
begin
tmpRef := 0;
if (objRef <> nil) and (objRef.queryInterface(IObjectInstance, tmpRef) <> system.S_OK) then begin
result := 0;
exit;
end;
result := tmpRef;
end;
class function Lang.cast(objRef: ISimple; const typIID: ShortString): ISimple;
var
tmpIID: system.TGuid;
tmpRef: Pointer;
begin
if not guidTryParse(typIID, tmpIID) then begin
system.runError(219);
end;
if objRef = nil then begin
result := nil;
exit;
end;
if objRef.queryInterface(tmpIID, tmpRef) <> system.S_OK then begin
system.runError(219);
end;
result := nil;
Pointer(result) := tmpRef;
end;
class function Lang.cast(objRef: ISimple; const typIID: system.TGuid): IUnknown;
var
tmpRef: Pointer;
begin
if objRef = nil then begin
result := nil;
exit;
end;
if objRef.queryInterface(typIID, tmpRef) <> system.S_OK then begin
system.runError(219);
end;
result := nil;
Pointer(result) := tmpRef;
end;
class function Lang.cast(objRef: ISimple; const typRef: system.TClass): TObject;
var
tmpRef: TObject;
begin
if typRef = nil then begin
system.runError(219);
end;
if objRef = nil then begin
result := nil;
exit;
end;
if (objRef.queryInterface(IObjectInstance, tmpRef) <> System.S_OK) or not tmpRef.inheritsFrom(typRef) then begin
system.runError(219);
end;
result := nil;
Pointer(result) := tmpRef;
end;
class function Lang.cast(objRef: IUnknown; const typIID: ShortString): ISimple;
var
tmpIID: system.TGuid;
tmpRef: Pointer;
begin
if not guidTryParse(typIID, tmpIID) then begin
system.runError(219);
end;
if objRef = nil then begin
result := nil;
exit;
end;
if objRef.queryInterface(tmpIID, tmpRef) <> system.S_OK then begin
system.runError(219);
end;
result := nil;
Pointer(result) := tmpRef;
end;
class function Lang.classFor(const typIID: ShortString): &Class;
var
idx: int;
entry: InterfaceEntry;
tmpIID: system.TGuid;
begin
if not guidTryParse(typIID, tmpIID) then begin
result := nil;
exit;
end;
idx := getGuidIndex(tmpIID, length(registeredInterfacesEntries));
entry := registeredInterfacesEntries[idx];
while entry <> nil do begin
if &Array.compfne(entry.guid, tmpIID, 3, 2) = &Array.NOT_FOUND then begin
result := InterfaceTypeInformation.create(entry.info);
exit;
end;
entry := entry.next;
end;
result := InterfaceTypeInformation.create(PTypeInfo(typeInfo(ISimple)));
end;
class function Lang.classFor(const typIID: system.TGuid): &Class;
var
idx: int;
entry: InterfaceEntry;
begin
idx := getGuidIndex(typIID, length(registeredInterfacesEntries));
entry := registeredInterfacesEntries[idx];
while entry <> nil do begin
if &Array.compfne(entry.guid, typIID, 3, 2) = &Array.NOT_FOUND then begin
result := InterfaceTypeInformation.create(entry.info);
exit;
end;
entry := entry.next;
end;
result := InterfaceTypeInformation.create(PTypeInfo(typeInfo(IUnknown)));
end;
class function Lang.classFor(const typRef: system.TClass): &Class;
begin
if typRef = nil then begin
result := nil;
exit;
end;
result := ClassTypeInformation.create(typRef);
end;
class function Lang.classFor(tinfo: Pointer): &Class;
var
subTypeKind: int;
argTypeKind: int;
argTypeInfo: PTypeInfo absolute tinfo;
typeInstance: &Class;
begin
if tinfo = nil then begin
result := nil;
exit;
end;
{$IFDEF WINDOWS}
if tinfo = typeInfo(real) then begin
result := primitives[TYPE_REAL];
exit;
end;
{$ENDIF}
argTypeKind := int(argTypeInfo^.kind);
case TTypeKind(argTypeKind) of
tkInteger, tkInt64, tkQWord: begin
subTypeKind := int(getTypeData(argTypeInfo)^.ordType);
typeInstance := primitives[subTypeKind + 30];
if typeInstance = nil then begin
typeInstance := primitives[argTypeKind];
end;
result := typeInstance;
end;
tkFloat: begin
subTypeKind := int(getTypeData(argTypeInfo)^.floatType);
typeInstance := primitives[subTypeKind + 38];
if typeInstance = nil then begin
typeInstance := primitives[argTypeKind];
end;
result := typeInstance;
end;
tkChar, tkSString, tkAString, tkWString, tkWChar, tkBool, tkUString, tkPointer: begin
result := primitives[argTypeKind];
end;
tkEnumeration: begin
result := primitives[Lang.TYPE_INT];
end;
tkUChar: begin
result := primitives[Lang.TYPE_UCHAR];
end;
tkClass: begin
result := ClassTypeInformation.create(argTypeInfo);
end;
tkClassRef: begin
result := ClassRefTypeInformation.create(argTypeInfo);
end;
tkInterface, tkInterfaceRaw: begin
result := InterfaceTypeInformation.create(argTypeInfo);
end;
tkDynArray: begin
result := DynamicArrayTypeInformation.create(argTypeInfo);
end;
tkProcVar: begin
result := FunctionTypeInformation.create(argTypeInfo);
end;
else
result := StructuredTypeInformation.create(argTypeInfo);
end;
end;
{%endregion}
{%region Math}
class procedure Math.setRoundMode(mode: int); assembler; nostackframe;
asm
dd $000008c8
fnstcw word [rbp-$08]
and qword [rbp-$08], $0000f3ff
{$IFDEF WINDOWS}
or qword [rbp-$08], rcx
{$ELSE}
or qword [rbp-$08], rdi
{$ENDIF}
fldcw word [rbp-$08]
leave
end;
{$IFDEF WINDOWS}
class function Math.E: real;
begin
result := CoReal.build($4000, $adf85458a2bb4a9b); { e }
end;
class function Math.PI: real;
begin
result := CoReal.build($4000, $c90fdaa22168c235); { π }
end;
class function Math.LOG_2_10: real;
begin
result := CoReal.build($4000, $d49a784bcd1b8afe); { log2(10) }
end;
class function Math.LOG_2_E: real;
begin
result := CoReal.build($3fff, $b8aa3b295c17f0bc); { log2(e) }
end;
class function Math.LOG_10_2: real;
begin
result := CoReal.build($3ffd, $9a209a84fbcff799); { log10(2) }
end;
class function Math.LOG_E_2: real;
begin
result := CoReal.build($3ffe, $b17217f7d1cf79ac); { log(2) }
end;
{$ENDIF}
class function Math.abs(x: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
mov eax, ecx
{$ELSE}
mov eax, edi
{$ENDIF}
test eax, eax
jns @exit
neg eax
@exit:
end;
class function Math.abs(x: long): long; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
mov rax, rcx
{$ELSE}
mov rax, rdi
{$ENDIF}
test rax, rax
jns @exit
neg rax
@exit:
end;
class function Math.abs(x: float): float; assembler; nostackframe;
asm
movdqu xmm1, [rip+int4s-@00+$00]
@00: pand xmm0, xmm1
end;
class function Math.abs(x: double): double; assembler; nostackframe;
asm
movdqu xmm1, [rip+long2s-@00+$00]
@00: pand xmm0, xmm1
end;
class function Math.abs(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
and word [rdx+$08], $7fff
fld tbyte [rdx+$00]
fstp tbyte [rcx+$00]
{$ELSE}
and word [rsp+$10], $7fff
fld tbyte [rsp+$08]
{$ENDIF}
end;
class function Math.sin(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fsin
fnstsw ax
test eax, $00000400
jz @exit
fld tbyte [rip+reals-@00+30] { 2.0 * π }
@00: fxch
@01: fprem
fnstsw ax
test eax, $00000400
jnz @01
fstp st(1)
fsin
@exit:
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.cos(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fcos
fnstsw ax
test eax, $00000400
jz @exit
fld tbyte [rip+reals-@00+30] { 2.0 * π }
@00: fxch
@01: fprem
fnstsw ax
test eax, $00000400
jnz @01
fstp st(1)
fcos
@exit:
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.tan(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fptan
fnstsw ax
test eax, $00000400
jz @exit
fldpi
fxch
@00: fprem
fnstsw ax
test eax, $00000400
jnz @00
fstp st(1)
fptan
@exit: ffree st
fincstp
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.asin(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fld1
fld st(1)
fmul st, st
fsubp st(1), st
fsqrt
fpatan
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.acos(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fld1
fld st(1)
fmul st, st
fsubp st(1), st
fsqrt
fxch
fpatan
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.atan(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fld1
fpatan
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.exp(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fldl2e
fmulp st(1), st
fxam
fnstsw ax
and eax, $00004700
cmp eax, $00000100 { не число }
je @exit
cmp eax, $00000300 { не число }
je @exit
cmp eax, $00000500 { +∞ }
je @exit
cmp eax, $00000700 { –∞ }
jne @00
ffree st
fincstp
fldz
jmp @exit
@00:
{$IFDEF WINDOWS}
lea rdx, [rcx+$00]
mov ecx, ROUND_TOWARD_ZERO
{$ELSE}
mov edi, ROUND_TOWARD_ZERO
{$ENDIF}
call setRoundMode
fld st
fld st
frndint
{$IFDEF WINDOWS}
mov ecx, ROUND_TO_NEAREST
{$ELSE}
mov edi, ROUND_TO_NEAREST
{$ENDIF}
call setRoundMode
{$IFDEF WINDOWS}
lea rcx, [rdx+$00]
{$ENDIF}
fsubp st(1), st
f2xm1
fld1
faddp st(1), st
fscale
fstp st(1)
@exit:
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.exp2(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fxam
fnstsw ax
and eax, $00004700
cmp eax, $00000100 { не число }
je @exit
cmp eax, $00000300 { не число }
je @exit
cmp eax, $00000500 { +∞ }
je @exit
cmp eax, $00000700 { –∞ }
jne @00
ffree st
fincstp
fldz
jmp @exit
@00:
{$IFDEF WINDOWS}
lea rdx, [rcx+$00]
mov ecx, ROUND_TOWARD_ZERO
{$ELSE}
mov edi, ROUND_TOWARD_ZERO
{$ENDIF}
call setRoundMode
fld st
fld st
frndint
{$IFDEF WINDOWS}
mov ecx, ROUND_TO_NEAREST
{$ELSE}
mov edi, ROUND_TO_NEAREST
{$ENDIF}
call setRoundMode
{$IFDEF WINDOWS}
lea rcx, [rdx+$00]
{$ENDIF}
fsubp st(1), st
f2xm1
fld1
faddp st(1), st
fscale
fstp st(1)
@exit:
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.exp10(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fldl2t
fmulp st(1), st
fxam
fnstsw ax
and eax, $00004700
cmp eax, $00000100 { не число }
je @exit
cmp eax, $00000300 { не число }
je @exit
cmp eax, $00000500 { +∞ }
je @exit
cmp eax, $00000700 { –∞ }
jne @00
ffree st
fincstp
fldz
jmp @exit
@00:
{$IFDEF WINDOWS}
lea rdx, [rcx+$00]
mov ecx, ROUND_TOWARD_ZERO
{$ELSE}
mov edi, ROUND_TOWARD_ZERO
{$ENDIF}
call setRoundMode
fld st
fld st
frndint
{$IFDEF WINDOWS}
mov ecx, ROUND_TO_NEAREST
{$ELSE}
mov edi, ROUND_TO_NEAREST
{$ENDIF}
call setRoundMode
{$IFDEF WINDOWS}
lea rcx, [rdx+$00]
{$ENDIF}
fsubp st(1), st
f2xm1
fld1
faddp st(1), st
fscale
fstp st(1)
@exit:
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.log(x: real): real; assembler; nostackframe;
asm
fldln2
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fyl2x
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.log2(x: real): real; assembler; nostackframe;
asm
fld1
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fyl2x
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.log10(x: real): real; assembler; nostackframe;
asm
fldlg2
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fyl2x
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.sqrt(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fsqrt
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.cbrt(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fxam
fnstsw ax
and eax, $00004700
cmp eax, $00000100 { не число }
je @exit
cmp eax, $00000300 { не число }
je @exit
cmp eax, $00004000 { +0 }
je @exit
cmp eax, $00004200 { –0 }
je @exit
cmp eax, $00000500 { +∞ }
je @exit
cmp eax, $00000700 { –∞ }
je @exit
test eax, $00000200
jz @00
fchs
@00: fld tbyte [rip+reals-@01+10] { 1.0 / 3.0 }
@01: fxch
fyl2x
{$IFDEF WINDOWS}
lea rdx, [rcx+$00]
mov ecx, ROUND_TOWARD_ZERO
{$ELSE}
mov edi, ROUND_TOWARD_ZERO
{$ENDIF}
call setRoundMode
fld st
fld st
frndint
{$IFDEF WINDOWS}
mov ecx, ROUND_TO_NEAREST
{$ELSE}
mov edi, ROUND_TO_NEAREST
{$ENDIF}
call setRoundMode
{$IFDEF WINDOWS}
lea rcx, [rdx+$00]
{$ENDIF}
fsubp st(1), st
f2xm1
fld1
faddp st(1), st
fscale
fstp st(1)
test eax, $00000200
jz @exit
fchs
@exit:
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.sinh(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fldl2e
fmulp st(1), st
fxam
fnstsw ax
and eax, $00004700
cmp eax, $00000100 { не число }
je @exit
cmp eax, $00000300 { не число }
je @exit
cmp eax, $00000500 { +∞ }
je @exit
cmp eax, $00000700 { –∞ }
je @exit
{$IFDEF WINDOWS}
lea rdx, [rcx+$00]
mov ecx, ROUND_TOWARD_ZERO
{$ELSE}
mov edi, ROUND_TOWARD_ZERO
{$ENDIF}
call setRoundMode
fld st
fld st
frndint
{$IFDEF WINDOWS}
mov ecx, ROUND_TO_NEAREST
{$ELSE}
mov edi, ROUND_TO_NEAREST
{$ENDIF}
call setRoundMode
{$IFDEF WINDOWS}
lea rcx, [rdx+$00]
{$ENDIF}
fsubp st(1), st
f2xm1
fld1
faddp st(1), st
fscale
fstp st(1)
fld1
fld st(1)
fdivp st(1), st
fsubp st(1), st
fld tbyte [rip+reals-@00+20] { 1.0 / 2.0 }
@00: fmulp st(1), st
@exit:
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.cosh(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fldl2e
fmulp st(1), st
fxam
fnstsw ax
and eax, $00004700
cmp eax, $00000100 { не число }
je @exit
cmp eax, $00000300 { не число }
je @exit
cmp eax, $00000500 { +∞ }
je @exit
cmp eax, $00000700 { –∞ }
jne @00
fchs
jmp @exit
@00:
{$IFDEF WINDOWS}
lea rdx, [rcx+$00]
mov ecx, ROUND_TOWARD_ZERO
{$ELSE}
mov edi, ROUND_TOWARD_ZERO
{$ENDIF}
call setRoundMode
fld st
fld st
frndint
{$IFDEF WINDOWS}
mov ecx, ROUND_TO_NEAREST
{$ELSE}
mov edi, ROUND_TO_NEAREST
{$ENDIF}
call setRoundMode
{$IFDEF WINDOWS}
lea rcx, [rdx+$00]
{$ENDIF}
fsubp st(1), st
f2xm1
fld1
faddp st(1), st
fscale
fstp st(1)
fld1
fld st(1)
fdivp st(1), st
faddp st(1), st
fld tbyte [rip+reals-@01+20] { 1.0 / 2.0 }
@01: fmulp st(1), st
@exit:
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.tanh(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fldl2e
fmulp st(1), st
fxam
fnstsw ax
and eax, $00004700
cmp eax, $00000100 { не число }
je @exit
cmp eax, $00000300 { не число }
je @exit
cmp eax, $00000500 { +∞ }
jne @01
@00: ffree st
fincstp
fld1
jmp @exit
@01: cmp eax, $00000700 { –∞ }
jne @04
@02: ffree st
fincstp
fld tbyte [rip+reals-@03+0] { –1.0 }
@03: jmp @exit
@04: fild dword [rip+ints-@05+$04] { –16384 }
@05: fcomip st, st(1)
jae @02
fild dword [rip+ints-@06+$08] { 16384 }
@06: fcomip st, st(1)
jbe @00
{$IFDEF WINDOWS}
lea rdx, [rcx+$00]
mov ecx, ROUND_TOWARD_ZERO
{$ELSE}
mov edi, ROUND_TOWARD_ZERO
{$ENDIF}
call setRoundMode
fld st
fld st
frndint
{$IFDEF WINDOWS}
mov ecx, ROUND_TO_NEAREST
{$ELSE}
mov edi, ROUND_TO_NEAREST
{$ENDIF}
call setRoundMode
{$IFDEF WINDOWS}
lea rcx, [rdx+$00]
{$ENDIF}
fsubp st(1), st
f2xm1
fld1
faddp st(1), st
fscale
fstp st(1)
fld1
fld st(1)
fdivp st(1), st
fld st(1)
fld st(1)
fsubp st(1), st
fxch st(2)
fxch st(1)
faddp st(1), st
fdivp st(1), st
@exit:
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.asinh(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fxam
fnstsw ax
and eax, $00004700
cmp eax, $00000100 { не число }
je @exit
cmp eax, $00000300 { не число }
je @exit
cmp eax, $00000500 { +∞ }
je @exit
cmp eax, $00000700 { –∞ }
je @exit
fldln2
fxch st(1)
fild qword [rip+longs-@00+$20] { –2^31 }
@00: fcomip st, st(1)
jbe @01
fchs
fyl2x
fldln2
faddp st(1), st
fchs
jmp @exit
@01: fild qword [rip+longs-@02+$28] { 2^31 }
@02: fcomip st, st(1)
jae @03
fyl2x
fldln2
faddp st(1), st
jmp @exit
@03: fld st
fmul st, st
fld1
faddp st(1), st
fsqrt
faddp st(1), st
fyl2x
@exit:
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.acosh(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fxam
fnstsw ax
and eax, $00004700
cmp eax, $00000100 { не число }
je @exit
cmp eax, $00000300 { не число }
je @exit
cmp eax, $00000500 { +∞ }
je @exit
fld1
fcomip st, st(1)
jbe @01
ffree st
fincstp
fld dword [rip+floats-@00+$08] { не число }
@00: jmp @exit
@01: fldln2
fxch st(1)
fild qword [rip+longs-@02+$28] { 2^31 }
@02: fcomip st, st(1)
jae @03
fyl2x
fldln2
faddp st(1), st
jmp @exit
@03: fld st
fmul st, st
fld1
fsubp st(1), st
fsqrt
faddp st(1), st
fyl2x
@exit:
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.atanh(x: real): real; assembler; nostackframe;
asm
fld tbyte [rip+reals-@00+20] { 1.0 / 2.0 }
@00: fldln2
fld1
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
fld1
fld st(1)
faddp st(1), st
fxch st(2)
fxch st(1)
fsubp st(1), st
fdivp st(1), st
fyl2x
fmulp st(1), st
@exit:
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.ceil(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
lea rdx, [rcx+$00]
mov ecx, ROUND_UP
{$ELSE}
fld tbyte [rsp+$08]
mov edi, ROUND_UP
{$ENDIF}
call setRoundMode
frndint
{$IFDEF WINDOWS}
mov ecx, ROUND_TO_NEAREST
{$ELSE}
mov edi, ROUND_TO_NEAREST
{$ENDIF}
call setRoundMode
{$IFDEF WINDOWS}
lea rcx, [rdx+$00]
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.floor(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
lea rdx, [rcx+$00]
mov ecx, ROUND_DOWN
{$ELSE}
fld tbyte [rsp+$08]
mov edi, ROUND_DOWN
{$ENDIF}
call setRoundMode
frndint
{$IFDEF WINDOWS}
mov ecx, ROUND_TO_NEAREST
{$ELSE}
mov edi, ROUND_TO_NEAREST
{$ENDIF}
call setRoundMode
{$IFDEF WINDOWS}
lea rcx, [rdx+$00]
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.round(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
{$ELSE}
fld tbyte [rsp+$08]
{$ENDIF}
frndint
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.intPart(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
lea rdx, [rcx+$00]
mov ecx, ROUND_TOWARD_ZERO
{$ELSE}
fld tbyte [rsp+$08]
mov edi, ROUND_TOWARD_ZERO
{$ENDIF}
call setRoundMode
frndint
{$IFDEF WINDOWS}
mov ecx, ROUND_TO_NEAREST
{$ELSE}
mov edi, ROUND_TO_NEAREST
{$ENDIF}
call setRoundMode
{$IFDEF WINDOWS}
lea rcx, [rdx+$00]
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.fracPart(x: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [rdx+$00]
lea rdx, [rcx+$00]
mov ecx, ROUND_TOWARD_ZERO
{$ELSE}
fld tbyte [rsp+$08]
mov edi, ROUND_TOWARD_ZERO
{$ENDIF}
call setRoundMode
fld st
frndint
{$IFDEF WINDOWS}
mov ecx, ROUND_TO_NEAREST
{$ELSE}
mov edi, ROUND_TO_NEAREST
{$ENDIF}
call setRoundMode
{$IFDEF WINDOWS}
lea rcx, [rdx+$00]
{$ENDIF}
fsubp st(1), st
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.atan2(x, y: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [r8+$00] { y }
fld tbyte [rdx+$00] { x }
{$ELSE}
fld tbyte [rsp+$18] { y }
fld tbyte [rsp+$08] { x }
{$ENDIF}
fpatan
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.pow(x, y: real): real; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
fld tbyte [r8+$00] { y }
fld tbyte [rdx+$00] { x }
{$ELSE}
fld tbyte [rsp+$18] { y }
fld tbyte [rsp+$08] { x }
{$ENDIF}
fyl2x
fxam
fnstsw ax
and eax, $00004700
cmp eax, $00000100 { не число }
je @exit
cmp eax, $00000300 { не число }
je @exit
cmp eax, $00000500 { +∞ }
je @exit
cmp eax, $00000700 { –∞ }
jne @00
ffree st
fincstp
fldz
jmp @exit
@00:
{$IFDEF WINDOWS}
lea rdx, [rcx+$00]
mov ecx, ROUND_TOWARD_ZERO
{$ELSE}
mov edi, ROUND_TOWARD_ZERO
{$ENDIF}
call setRoundMode
fld st
fld st
frndint
{$IFDEF WINDOWS}
mov ecx, ROUND_TO_NEAREST
{$ELSE}
mov edi, ROUND_TO_NEAREST
{$ENDIF}
call setRoundMode
{$IFDEF WINDOWS}
lea rcx, [rdx+$00]
{$ENDIF}
fsubp st(1), st
f2xm1
fld1
faddp st(1), st
fscale
fstp st(1)
@exit:
{$IFDEF WINDOWS}
fstp tbyte [rcx+$00]
{$ENDIF}
end;
class function Math.toRadians(angleInDegrees: real): real;
begin
result := angleInDegrees / reals[4].value;
end;
class function Math.toDegrees(angleInRadians: real): real;
begin
result := angleInRadians * reals[4].value;
end;
{%endregion}
{%region &Array}
class procedure &Array.copyBy1(const src; var dst; length: long); assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000010c8
mov qword [rbp-$10], rsi
mov qword [rbp-$08], rdi
lea rsi, [rcx+$00]
lea rdi, [rdx+$00]
lea rcx, [r8+$00]
{$ELSE}
xchg rsi, rdi
lea rcx, [rdx+$00]
{$ENDIF}
cmp rsi, rdi
jl @back
cld
rep movsb
jmp @exit
@back: lea rsi, [rsi+rcx*1-$01]
lea rdi, [rdi+rcx*1-$01]
std
rep movsb
cld
@exit:
{$IFDEF WINDOWS}
mov rsi, [rbp-$10]
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class procedure &Array.copyBy2(const src; var dst; length: long); assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000010c8
mov qword [rbp-$10], rsi
mov qword [rbp-$08], rdi
lea rsi, [rcx+$00]
lea rdi, [rdx+$00]
lea rcx, [r8+$00]
{$ELSE}
xchg rsi, rdi
lea rcx, [rdx+$00]
{$ENDIF}
cmp rsi, rdi
jl @back
cld
rep movsw
jmp @exit
@back: lea rsi, [rsi+rcx*2-$02]
lea rdi, [rdi+rcx*2-$02]
std
rep movsw
cld
@exit:
{$IFDEF WINDOWS}
mov rsi, [rbp-$10]
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class procedure &Array.copyBy4(const src; var dst; length: long); assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000010c8
mov qword [rbp-$10], rsi
mov qword [rbp-$08], rdi
lea rsi, [rcx+$00]
lea rdi, [rdx+$00]
lea rcx, [r8+$00]
{$ELSE}
xchg rsi, rdi
lea rcx, [rdx+$00]
{$ENDIF}
cmp rsi, rdi
jl @back
cld
rep movsd
jmp @exit
@back: lea rsi, [rsi+rcx*4-$04]
lea rdi, [rdi+rcx*4-$04]
std
rep movsd
cld
@exit:
{$IFDEF WINDOWS}
mov rsi, [rbp-$10]
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class procedure &Array.copyBy8(const src; var dst; length: long); assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000010c8
mov qword [rbp-$10], rsi
mov qword [rbp-$08], rdi
lea rsi, [rcx+$00]
lea rdi, [rdx+$00]
lea rcx, [r8+$00]
{$ELSE}
xchg rsi, rdi
lea rcx, [rdx+$00]
{$ENDIF}
cmp rsi, rdi
jl @back
cld
rep movsq
jmp @exit
@back: lea rsi, [rsi+rcx*8-$08]
lea rdi, [rdi+rcx*8-$08]
std
rep movsq
cld
@exit:
{$IFDEF WINDOWS}
mov rsi, [rbp-$10]
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class procedure &Array.fillReal(var dst; length: int; const value: real); assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000008c8
mov qword [rbp-$08], rdi
lea rdi, [rcx+$00]
movsxd rcx, edx
mov rax, qword [r8+$00]
movsx rdx, word [r8+$08]
{$ELSE}
movsxd rcx, esi
mov rax, qword [rsp+$08]
movsx rdx, word [rsp+$10]
{$ENDIF}
@00: mov qword [rdi+$00], rax
mov word [rdi+$08], dx
lea rdi, [rdi+$0a]
loop @00
{$IFDEF WINDOWS}
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class procedure &Array.fillLong(var dst; size, length: int; value: long); assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000008c8
mov qword [rbp-$08], rdi
lea rdi, [rcx+$00]
lea rax, [r9+$00]
movsxd rcx, r8d
movsxd rdx, edx
{$ELSE}
lea rax, [rcx+$00]
movsxd rcx, edx
movsxd rdx, esi
{$ENDIF}
lea r10, [rip+@01-@00]
@00: movsxd r11, [r10+rdx*4+$00]
lea r10, [r10+r11*1+$00]
jmp r10
align $08
@01: dd $00000010 { @S0-@01 }
dd $00000018 { @S1-@01 }
dd $00000020 { @S2-@01 }
dd $00000028 { @S3-@01 }
@S0: cld
rep stosb
jmp @exit
align $08
@S1: cld
rep stosw
jmp @exit
align $08
@S2: cld
rep stosd
jmp @exit
align $08
@S3: cld
rep stosq
jmp @exit
align $08
@exit:
{$IFDEF WINDOWS}
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class function &Array.findfeq(const src; size, length: int; value: long): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000008c8
mov qword [rbp-$08], rdi
lea rdi, [rcx+$00]
lea rax, [r9+$00]
movsxd rcx, r8d
movsxd rdx, edx
{$ELSE}
lea rax, [rcx+$00]
movsxd rcx, edx
movsxd rdx, esi
{$ENDIF}
lea r9, [rcx-$01]
lea r10, [rip+@01-@00]
@00: movsxd r11, [r10+rdx*4+$00]
lea r10, [r10+r11*1+$00]
jmp r10
align $08
@01: dd $00000010 { @S0-@01 }
dd $00000018 { @S1-@01 }
dd $00000020 { @S2-@01 }
dd $00000028 { @S3-@01 }
@S0: cld
repne scasb
je @rpos
jmp @rneg
align $08
@S1: cld
repne scasw
je @rpos
jmp @rneg
align $08
@S2: cld
repne scasd
je @rpos
jmp @rneg
align $08
@S3: cld
repne scasq
je @rpos
jmp @rneg
align $08
@rneg: mov eax, NOT_FOUND
jmp @exit
@rpos: sub r9d, ecx
mov eax, r9d
@exit:
{$IFDEF WINDOWS}
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class function &Array.findfne(const src; size, length: int; value: long): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000008c8
mov qword [rbp-$08], rdi
lea rdi, [rcx+$00]
lea rax, [r9+$00]
movsxd rcx, r8d
movsxd rdx, edx
{$ELSE}
lea rax, [rcx+$00]
movsxd rcx, edx
movsxd rdx, esi
{$ENDIF}
lea r9, [rcx-$01]
lea r10, [rip+@01-@00]
@00: movsxd r11, [r10+rdx*4+$00]
lea r10, [r10+r11*1+$00]
jmp r10
align $08
@01: dd $00000010 { @S0-@01 }
dd $00000018 { @S1-@01 }
dd $00000020 { @S2-@01 }
dd $00000028 { @S3-@01 }
@S0: cld
repe scasb
jne @rpos
jmp @rneg
align $08
@S1: cld
repe scasw
jne @rpos
jmp @rneg
align $08
@S2: cld
repe scasd
jne @rpos
jmp @rneg
align $08
@S3: cld
repe scasq
jne @rpos
jmp @rneg
align $08
@rneg: mov eax, NOT_FOUND
jmp @exit
@rpos: sub r9d, ecx
mov eax, r9d
@exit:
{$IFDEF WINDOWS}
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class function &Array.findbeq(const src; size, length: int; value: long): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000008c8
mov qword [rbp-$08], rdi
lea rdi, [rcx+$00]
lea rax, [r9+$00]
movsxd rcx, r8d
movsxd rdx, edx
{$ELSE}
lea rax, [rcx+$00]
movsxd rcx, edx
movsxd rdx, esi
{$ENDIF}
lea r9, [rcx-$01]
lea r10, [rip+@01-@00]
@00: movsxd r11, [r10+rdx*4+$00]
lea r10, [r10+r11*1+$00]
jmp r10
align $08
@01: dd $00000010 { @S0-@01 }
dd $00000018 { @S1-@01 }
dd $00000020 { @S2-@01 }
dd $00000028 { @S3-@01 }
@S0: std
repne scasb
je @rpos
jmp @rneg
align $08
@S1: std
repne scasw
je @rpos
jmp @rneg
align $08
@S2: std
repne scasd
je @rpos
jmp @rneg
align $08
@S3: std
repne scasq
je @rpos
jmp @rneg
align $08
@rneg: mov eax, NOT_FOUND
jmp @exit
@rpos: sub ecx, r9d
mov eax, ecx
@exit: cld
{$IFDEF WINDOWS}
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class function &Array.findbne(const src; size, length: int; value: long): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000008c8
mov qword [rbp-$08], rdi
lea rdi, [rcx+$00]
lea rax, [r9+$00]
movsxd rcx, r8d
movsxd rdx, edx
{$ELSE}
lea rax, [rcx+$00]
movsxd rcx, edx
movsxd rdx, esi
{$ENDIF}
lea r9, [rcx-$01]
lea r10, [rip+@01-@00]
@00: movsxd r11, [r10+rdx*4+$00]
lea r10, [r10+r11*1+$00]
jmp r10
align $08
@01: dd $00000010 { @S0-@01 }
dd $00000018 { @S1-@01 }
dd $00000020 { @S2-@01 }
dd $00000028 { @S3-@01 }
@S0: std
repe scasb
jne @rpos
jmp @rneg
align $08
@S1: std
repe scasw
jne @rpos
jmp @rneg
align $08
@S2: std
repe scasd
jne @rpos
jmp @rneg
align $08
@S3: std
repe scasq
jne @rpos
jmp @rneg
align $08
@rneg: mov eax, NOT_FOUND
jmp @exit
@rpos: sub ecx, r9d
mov eax, ecx
@exit: cld
{$IFDEF WINDOWS}
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class function &Array.compfeq(const src1, src2; size, length: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000010c8
mov qword [rbp-$10], rsi
mov qword [rbp-$08], rdi
lea rsi, [rcx+$00]
lea rdi, [rdx+$00]
movsxd rcx, r9d
movsxd rdx, r8d
{$ELSE}
xchg rsi, rdi
movsxd rcx, ecx
movsxd rdx, edx
{$ENDIF}
lea r9, [rcx-$01]
lea r10, [rip+@01-@00]
@00: movsxd r11, [r10+rdx*4+$00]
lea r10, [r10+r11*1+$00]
jmp r10
align $08
@01: dd $00000010 { @S0-@01 }
dd $00000018 { @S1-@01 }
dd $00000020 { @S2-@01 }
dd $00000028 { @S3-@01 }
@S0: cld
repne cmpsb
je @rpos
jmp @rneg
align $08
@S1: cld
repne cmpsw
je @rpos
jmp @rneg
align $08
@S2: cld
repne cmpsd
je @rpos
jmp @rneg
align $08
@S3: cld
repne cmpsq
je @rpos
jmp @rneg
align $08
@rneg: mov eax, NOT_FOUND
jmp @exit
@rpos: sub r9d, ecx
mov eax, r9d
@exit:
{$IFDEF WINDOWS}
mov rsi, [rbp-$10]
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class function &Array.compfne(const src1, src2; size, length: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000010c8
mov qword [rbp-$10], rsi
mov qword [rbp-$08], rdi
lea rsi, [rcx+$00]
lea rdi, [rdx+$00]
movsxd rcx, r9d
movsxd rdx, r8d
{$ELSE}
xchg rsi, rdi
movsxd rcx, ecx
movsxd rdx, edx
{$ENDIF}
lea r9, [rcx-$01]
lea r10, [rip+@01-@00]
@00: movsxd r11, [r10+rdx*4+$00]
lea r10, [r10+r11*1+$00]
jmp r10
align $08
@01: dd $00000010 { @S0-@01 }
dd $00000018 { @S1-@01 }
dd $00000020 { @S2-@01 }
dd $00000028 { @S3-@01 }
@S0: cld
repe cmpsb
jne @rpos
jmp @rneg
align $08
@S1: cld
repe cmpsw
jne @rpos
jmp @rneg
align $08
@S2: cld
repe cmpsd
jne @rpos
jmp @rneg
align $08
@S3: cld
repe cmpsq
jne @rpos
jmp @rneg
align $08
@rneg: mov eax, NOT_FOUND
jmp @exit
@rpos: sub r9d, ecx
mov eax, r9d
@exit:
{$IFDEF WINDOWS}
mov rsi, [rbp-$10]
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class function &Array.compbeq(const src1, src2; size, length: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000010c8
mov qword [rbp-$10], rsi
mov qword [rbp-$08], rdi
lea rsi, [rcx+$00]
lea rdi, [rdx+$00]
movsxd rcx, r9d
movsxd rdx, r8d
{$ELSE}
xchg rsi, rdi
movsxd rcx, ecx
movsxd rdx, edx
{$ENDIF}
lea r9, [rcx-$01]
lea r10, [rip+@01-@00]
@00: movsxd r11, [r10+rdx*4+$00]
lea r10, [r10+r11*1+$00]
jmp r10
align $08
@01: dd $00000010 { @S0-@01 }
dd $00000018 { @S1-@01 }
dd $00000020 { @S2-@01 }
dd $00000028 { @S3-@01 }
@S0: std
repne cmpsb
je @rpos
jmp @rneg
align $08
@S1: std
repne cmpsw
je @rpos
jmp @rneg
align $08
@S2: std
repne cmpsd
je @rpos
jmp @rneg
align $08
@S3: std
repne cmpsq
je @rpos
jmp @rneg
align $08
@rneg: mov eax, NOT_FOUND
jmp @exit
@rpos: sub ecx, r9d
mov eax, ecx
@exit: cld
{$IFDEF WINDOWS}
mov rsi, [rbp-$10]
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class function &Array.compbne(const src1, src2; size, length: int): int; assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000010c8
mov qword [rbp-$10], rsi
mov qword [rbp-$08], rdi
lea rsi, [rcx+$00]
lea rdi, [rdx+$00]
movsxd rcx, r9d
movsxd rdx, r8d
{$ELSE}
xchg rsi, rdi
movsxd rcx, ecx
movsxd rdx, edx
{$ENDIF}
lea r9, [rcx-$01]
lea r10, [rip+@01-@00]
@00: movsxd r11, [r10+rdx*4+$00]
lea r10, [r10+r11*1+$00]
jmp r10
align $08
@01: dd $00000010 { @S0-@01 }
dd $00000018 { @S1-@01 }
dd $00000020 { @S2-@01 }
dd $00000028 { @S3-@01 }
@S0: std
repe cmpsb
jne @rpos
jmp @rneg
align $08
@S1: std
repe cmpsw
jne @rpos
jmp @rneg
align $08
@S2: std
repe cmpsd
jne @rpos
jmp @rneg
align $08
@S3: std
repe cmpsq
jne @rpos
jmp @rneg
align $08
@rneg: mov eax, NOT_FOUND
jmp @exit
@rpos: sub ecx, r9d
mov eax, ecx
@exit: cld
{$IFDEF WINDOWS}
mov rsi, [rbp-$10]
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class procedure &Array.checkBounds(const aarray; offset, length: int);
var
lim: int;
len: int;
begin
lim := offset + length;
len := system.length(boolean_Array1d(aarray));
if (lim < offset) or (lim > len) or (offset < 0) or (offset > len) then begin
raise ArrayIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.array-index'));
end;
end;
class procedure &Array.copyRaw(const src; var dst; length: long); assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000010c8
mov qword [rbp-$10], rsi
mov qword [rbp-$08], rdi
lea rsi, [rcx-$00]
lea rdi, [rdx-$00]
lea rcx, [r8-$00]
{$ELSE}
xchg rsi, rdi
lea rcx, [rdx-$00]
{$ENDIF}
cmp rcx, $00
jle @exit
cmp rsi, rdi
jl @back
mov rdx, rcx
{$IFDEF USE_AVX2}
sar rcx, $05
and rdx, $1f
jrcxz @01
@00: vmovdqu ymm0, [rsi+$00]
vmovdqu ymmword [rdi+$00], ymm0
lea rsi, [rsi+$20]
lea rdi, [rdi+$20]
{$ELSE}
sar rcx, $04
and rdx, $0f
jrcxz @01
@00: movdqu xmm0, [rsi+$00]
movdqu xmmword [rdi+$00], xmm0
lea rsi, [rsi+$10]
lea rdi, [rdi+$10]
{$ENDIF}
loop @00
@01: mov rcx, rdx
jrcxz @exit
cld
rep movsb
jmp @exit
@back: lea rsi, [rsi+rcx*1-$00]
lea rdi, [rdi+rcx*1-$00]
mov rdx, rcx
{$IFDEF USE_AVX2}
sar rcx, $05
and rdx, $1f
jrcxz @03
@02: lea rsi, [rsi-$20]
lea rdi, [rdi-$20]
vmovdqu ymm0, [rsi-$00]
vmovdqu ymmword [rdi-$00], ymm0
{$ELSE}
sar rcx, $04
and rdx, $0f
jrcxz @03
@02: lea rsi, [rsi-$10]
lea rdi, [rdi-$10]
movdqu xmm0, [rsi-$00]
movdqu xmmword [rdi-$00], xmm0
{$ENDIF}
loop @02
@03: mov rcx, rdx
jrcxz @exit
lea rsi, [rsi-$01]
lea rdi, [rdi-$01]
std
rep movsb
cld
@exit:
{$IFDEF WINDOWS}
mov rsi, [rbp-$10]
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class procedure &Array.copyPrimitives(const srcArray: boolean_Array1d; srcOffset: int; const dstArray: boolean_Array1d; dstOffset: int; length: int);
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
copyRaw(srcArray[srcOffset], dstArray[dstOffset], long(length) * sizeof(boolean));
end;
end;
class procedure &Array.copyPrimitives(const srcArray: char_Array1d; srcOffset: int; const dstArray: char_Array1d; dstOffset: int; length: int);
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
copyRaw(srcArray[srcOffset], dstArray[dstOffset], long(length) * sizeof(char));
end;
end;
class procedure &Array.copyPrimitives(const srcArray: uchar_Array1d; srcOffset: int; const dstArray: uchar_Array1d; dstOffset: int; length: int);
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
copyRaw(srcArray[srcOffset], dstArray[dstOffset], long(length) * sizeof(uchar));
end;
end;
class procedure &Array.copyPrimitives(const srcArray: byte_Array1d; srcOffset: int; const dstArray: byte_Array1d; dstOffset: int; length: int);
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
copyRaw(srcArray[srcOffset], dstArray[dstOffset], long(length) * sizeof(byte));
end;
end;
class procedure &Array.copyPrimitives(const srcArray: short_Array1d; srcOffset: int; const dstArray: short_Array1d; dstOffset: int; length: int);
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
copyRaw(srcArray[srcOffset], dstArray[dstOffset], long(length) * sizeof(short));
end;
end;
class procedure &Array.copyPrimitives(const srcArray: int_Array1d; srcOffset: int; const dstArray: int_Array1d; dstOffset: int; length: int);
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
copyRaw(srcArray[srcOffset], dstArray[dstOffset], long(length) * sizeof(int));
end;
end;
class procedure &Array.copyPrimitives(const srcArray: long_Array1d; srcOffset: int; const dstArray: long_Array1d; dstOffset: int; length: int);
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
copyRaw(srcArray[srcOffset], dstArray[dstOffset], long(length) * sizeof(long));
end;
end;
class procedure &Array.copyPrimitives(const srcArray: float_Array1d; srcOffset: int; const dstArray: float_Array1d; dstOffset: int; length: int);
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
copyRaw(srcArray[srcOffset], dstArray[dstOffset], long(length) * sizeof(float));
end;
end;
class procedure &Array.copyPrimitives(const srcArray: double_Array1d; srcOffset: int; const dstArray: double_Array1d; dstOffset: int; length: int);
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
copyRaw(srcArray[srcOffset], dstArray[dstOffset], long(length) * sizeof(double));
end;
end;
class procedure &Array.copyPrimitives(const srcArray: real_Array1d; srcOffset: int; const dstArray: real_Array1d; dstOffset: int; length: int);
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
copyRaw(srcArray[srcOffset], dstArray[dstOffset], long(length) * sizeof(real));
end;
end;
class procedure &Array.copyStrings(const srcArray: AnsiString_Array1d; srcOffset: int; const dstArray: AnsiString_Array1d; dstOffset: int; length: int);
var
idx: int;
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
if (srcArray = dstArray) and (srcOffset < dstOffset) then begin
inc(srcOffset, length);
inc(dstOffset, length);
for idx := length - 1 downto 0 do begin
dec(srcOffset);
dec(dstOffset);
dstArray[dstOffset] := srcArray[srcOffset];
end;
end else begin
for idx := length - 1 downto 0 do begin
dstArray[dstOffset] := srcArray[srcOffset];
inc(srcOffset);
inc(dstOffset);
end;
end;
end;
end;
class procedure &Array.copyStrings(const srcArray: UnicodeString_Array1d; srcOffset: int; const dstArray: UnicodeString_Array1d; dstOffset: int; length: int);
var
idx: int;
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
if (srcArray = dstArray) and (srcOffset < dstOffset) then begin
inc(srcOffset, length);
inc(dstOffset, length);
for idx := length - 1 downto 0 do begin
dec(srcOffset);
dec(dstOffset);
dstArray[dstOffset] := srcArray[srcOffset];
end;
end else begin
for idx := length - 1 downto 0 do begin
dstArray[dstOffset] := srcArray[srcOffset];
inc(srcOffset);
inc(dstOffset);
end;
end;
end;
end;
class procedure &Array.copyObjects(const srcArray; srcOffset: int; const dstArray; dstOffset: int; length: int);
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
copyRaw(TObject_Array1d(srcArray)[srcOffset], TObject_Array1d(dstArray)[dstOffset], long(length) * sizeof(TObject));
end;
end;
class procedure &Array.copySimples(const srcArray; srcOffset: int; const dstArray; dstOffset: int; length: int);
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
copyRaw(ISimple_Array1d(srcArray)[srcOffset], ISimple_Array1d(dstArray)[dstOffset], long(length) * sizeof(ISimple));
end;
end;
class procedure &Array.copyUnknowns(const srcArray; srcOffset: int; const dstArray; dstOffset: int; length: int);
var
idx: int;
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
if (IUnknown_Array1d(srcArray) = IUnknown_Array1d(dstArray)) and (srcOffset < dstOffset) then begin
inc(srcOffset, length);
inc(dstOffset, length);
for idx := length - 1 downto 0 do begin
dec(srcOffset);
dec(dstOffset);
IUnknown_Array1d(dstArray)[dstOffset] := IUnknown_Array1d(srcArray)[srcOffset];
end;
end else begin
for idx := length - 1 downto 0 do begin
IUnknown_Array1d(dstArray)[dstOffset] := IUnknown_Array1d(srcArray)[srcOffset];
inc(srcOffset);
inc(dstOffset);
end;
end;
end;
end;
class procedure &Array.copyArrays(const srcArray; srcOffset: int; const dstArray; dstOffset: int; length: int);
var
idx: int;
begin
if length > 0 then begin
checkBounds(srcArray, srcOffset, length);
checkBounds(dstArray, dstOffset, length);
if (boolean_Array2d(srcArray) = boolean_Array2d(dstArray)) and (srcOffset < dstOffset) then begin
inc(srcOffset, length);
inc(dstOffset, length);
for idx := length - 1 downto 0 do begin
dec(srcOffset);
dec(dstOffset);
boolean_Array2d(dstArray)[dstOffset] := boolean_Array2d(srcArray)[srcOffset];
end;
end else begin
for idx := length - 1 downto 0 do begin
boolean_Array2d(dstArray)[dstOffset] := boolean_Array2d(srcArray)[srcOffset];
inc(srcOffset);
inc(dstOffset);
end;
end;
end;
end;
class procedure &Array.zeroRaw(out dst; length: long); assembler; nostackframe;
asm
{$IFDEF WINDOWS}
dd $000008c8
mov qword [rbp-$08], rdi
lea rdi, [rcx+$00]
lea rcx, [rdx+$00]
{$ELSE}
lea rcx, [rsi+$00]
{$ENDIF}
cmp rcx, $00
jle @exit
mov rdx, rcx
{$IFDEF USE_AVX2}
sar rcx, $05
and rdx, $1f
jrcxz @01
vpxor ymm0, ymm0, ymm0
@00: vmovdqu ymmword [rdi+$00], ymm0
lea rdi, [rdi+$20]
{$ELSE}
sar rcx, $04
and rdx, $0f
jrcxz @01
pxor xmm0, xmm0
@00: movdqu xmmword [rdi+$00], xmm0
lea rdi, [rdi+$00]
{$ENDIF}
loop @00
@01: mov rcx, rdx
jrcxz @exit
xor eax, eax
cld
rep stosb
@exit:
{$IFDEF WINDOWS}
mov rdi, [rbp-$08]
leave
{$ENDIF}
end;
class procedure &Array.fillPrimitives(const dstArray: boolean_Array1d; dstOffset: int; length: int; value: boolean);
var
intvl: byte absolute value;
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
fillLong(dstArray[dstOffset], 0, length, intvl);
end;
end;
class procedure &Array.fillPrimitives(const dstArray: char_Array1d; dstOffset: int; length: int; value: char);
var
intvl: byte absolute value;
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
fillLong(dstArray[dstOffset], 0, length, intvl);
end;
end;
class procedure &Array.fillPrimitives(const dstArray: uchar_Array1d; dstOffset: int; length: int; value: uchar);
var
intvl: short absolute value;
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
fillLong(dstArray[dstOffset], 1, length, intvl);
end;
end;
class procedure &Array.fillPrimitives(const dstArray: byte_Array1d; dstOffset: int; length: int; value: byte);
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
fillLong(dstArray[dstOffset], 0, length, value);
end;
end;
class procedure &Array.fillPrimitives(const dstArray: short_Array1d; dstOffset: int; length: int; value: short);
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
fillLong(dstArray[dstOffset], 1, length, value);
end;
end;
class procedure &Array.fillPrimitives(const dstArray: int_Array1d; dstOffset: int; length: int; value: int);
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
fillLong(dstArray[dstOffset], 2, length, value);
end;
end;
class procedure &Array.fillPrimitives(const dstArray: long_Array1d; dstOffset: int; length: int; value: long);
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
fillLong(dstArray[dstOffset], 3, length, value);
end;
end;
class procedure &Array.fillPrimitives(const dstArray: float_Array1d; dstOffset: int; length: int; value: float);
var
intvl: int absolute value;
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
fillLong(dstArray[dstOffset], 2, length, intvl);
end;
end;
class procedure &Array.fillPrimitives(const dstArray: double_Array1d; dstOffset: int; length: int; value: double);
var
intvl: long absolute value;
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
fillLong(dstArray[dstOffset], 3, length, intvl);
end;
end;
class procedure &Array.fillPrimitives(const dstArray: real_Array1d; dstOffset: int; length: int; value: real);
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
fillReal(dstArray[dstOffset], length, value);
end;
end;
class procedure &Array.fillStrings(const dstArray: AnsiString_Array1d; dstOffset: int; length: int; const value: AnsiString);
var
index: int;
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
for index := dstOffset to dstOffset + length - 1 do dstArray[index] := value;
end;
end;
class procedure &Array.fillStrings(const dstArray: UnicodeString_Array1d; dstOffset: int; length: int; const value: UnicodeString);
var
index: int;
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
for index := dstOffset to dstOffset + length - 1 do dstArray[index] := value;
end;
end;
class procedure &Array.fillObjects(const dstArray; dstOffset: int; length: int; value: TObject);
var
intvl: long absolute value;
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
fillLong(TObject_Array1d(dstArray)[dstOffset], 3, length, intvl);
end;
end;
class procedure &Array.fillSimples(const dstArray; dstOffset: int; length: int; value: ISimple);
var
intvl: long absolute value;
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
fillLong(ISimple_Array1d(dstArray)[dstOffset], 3, length, intvl);
end;
end;
class procedure &Array.fillUnknowns(const dstArray; dstOffset: int; length: int; value: IUnknown);
var
index: int;
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
for index := dstOffset to dstOffset + length - 1 do IUnknown_Array1d(dstArray)[index] := value;
end;
end;
class procedure &Array.fillArrays(const dstArray; dstOffset: int; length: int; const value);
var
index: int;
begin
if length > 0 then begin
checkBounds(dstArray, dstOffset, length);
for index := dstOffset to dstOffset + length - 1 do boolean_Array2d(dstArray)[index] := boolean_Array1d(value);
end;
end;
class function &Array.indexOf(value: boolean; const aarray: boolean_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
intvl: byte absolute value;
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfeq(aarray[startFromIndex], 0, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.indexOf(value: char; const aarray: char_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
intvl: byte absolute value;
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfeq(aarray[startFromIndex], 0, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.indexOf(value: uchar; const aarray: uchar_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
intvl: short absolute value;
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfeq(aarray[startFromIndex], 1, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.indexOf(value: int; const aarray: byte_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfeq(aarray[startFromIndex], 0, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.indexOf(value: int; const aarray: short_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfeq(aarray[startFromIndex], 1, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.indexOf(value: int; const aarray: int_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfeq(aarray[startFromIndex], 2, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.indexOf(value: long; const aarray: long_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfeq(aarray[startFromIndex], 3, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.indexOf(value: Pointer; const aarray; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
intvl: long absolute value;
parray: Pointer_Array1d absolute aarray;
begin
if parray <> nil then begin
arrayLength := length(parray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfeq(parray[startFromIndex], 3, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOf(value: boolean; const aarray: boolean_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
intvl: byte absolute value;
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbeq(aarray[startFromIndex], 0, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOf(value: char; const aarray: char_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
intvl: byte absolute value;
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbeq(aarray[startFromIndex], 0, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOf(value: uchar; const aarray: uchar_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
intvl: short absolute value;
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbeq(aarray[startFromIndex], 1, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOf(value: int; const aarray: byte_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbeq(aarray[startFromIndex], 0, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOf(value: int; const aarray: short_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbeq(aarray[startFromIndex], 1, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOf(value: int; const aarray: int_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbeq(aarray[startFromIndex], 2, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOf(value: long; const aarray: long_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbeq(aarray[startFromIndex], 3, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOf(value: Pointer; const aarray; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
intvl: long absolute value;
parray: Pointer_Array1d absolute aarray;
begin
if parray <> nil then begin
arrayLength := length(parray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbeq(parray[startFromIndex], 3, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.indexOfNon(value: boolean; const aarray: boolean_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
intvl: byte absolute value;
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfne(aarray[startFromIndex], 0, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.indexOfNon(value: char; const aarray: char_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
intvl: byte absolute value;
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfne(aarray[startFromIndex], 0, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.indexOfNon(value: uchar; const aarray: uchar_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
intvl: short absolute value;
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfne(aarray[startFromIndex], 1, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.indexOfNon(value: int; const aarray: byte_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfne(aarray[startFromIndex], 0, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.indexOfNon(value: int; const aarray: short_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfne(aarray[startFromIndex], 1, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.indexOfNon(value: int; const aarray: int_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfne(aarray[startFromIndex], 2, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.indexOfNon(value: long; const aarray: long_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfne(aarray[startFromIndex], 3, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.indexOfNon(value: Pointer; const aarray; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
intvl: long absolute value;
parray: Pointer_Array1d absolute aarray;
begin
if parray <> nil then begin
arrayLength := length(parray);
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex < arrayLength then begin
limitScanLength := arrayLength - startFromIndex;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findfne(parray[startFromIndex], 3, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOfNon(value: boolean; const aarray: boolean_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
intvl: byte absolute value;
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbne(aarray[startFromIndex], 0, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOfNon(value: char; const aarray: char_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
intvl: byte absolute value;
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbne(aarray[startFromIndex], 0, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOfNon(value: uchar; const aarray: uchar_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
intvl: short absolute value;
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbne(aarray[startFromIndex], 1, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOfNon(value: int; const aarray: byte_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbne(aarray[startFromIndex], 0, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOfNon(value: int; const aarray: short_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbne(aarray[startFromIndex], 1, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOfNon(value: int; const aarray: int_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbne(aarray[startFromIndex], 2, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOfNon(value: long; const aarray: long_Array1d; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
begin
if aarray <> nil then begin
arrayLength := length(aarray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbne(aarray[startFromIndex], 3, limitScanLength, value);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.lastIndexOfNon(value: Pointer; const aarray; startFromIndex: int; maximumScanLength: int): int;
var
found: int;
arrayLength: int;
limitScanLength: int;
intvl: long absolute value;
parray: Pointer_Array1d absolute aarray;
begin
if parray <> nil then begin
arrayLength := length(parray);
if startFromIndex >= arrayLength then begin
startFromIndex := arrayLength - 1;
end;
if startFromIndex >= 0 then begin
limitScanLength := startFromIndex + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
found := findbne(parray[startFromIndex], 3, limitScanLength, intvl);
if found <> NOT_FOUND then begin
result := startFromIndex + found;
exit;
end;
end;
end;
result := -1;
end;
class function &Array.offsetOfEqual(const array1: boolean_Array1d; array1StartFromIndex: int; const array2: boolean_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: boolean_Array1d absolute array1;
array2Instance: boolean_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 0, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.offsetOfEqual(const array1: char_Array1d; array1StartFromIndex: int; const array2: char_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: char_Array1d absolute array1;
array2Instance: char_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 0, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.offsetOfEqual(const array1: uchar_Array1d; array1StartFromIndex: int; const array2: uchar_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: uchar_Array1d absolute array1;
array2Instance: uchar_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 1, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.offsetOfEqual(const array1: byte_Array1d; array1StartFromIndex: int; const array2: byte_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: byte_Array1d absolute array1;
array2Instance: byte_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 0, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.offsetOfEqual(const array1: short_Array1d; array1StartFromIndex: int; const array2: short_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: short_Array1d absolute array1;
array2Instance: short_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 1, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.offsetOfEqual(const array1: int_Array1d; array1StartFromIndex: int; const array2: int_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: int_Array1d absolute array1;
array2Instance: int_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 2, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.offsetOfEqual(const array1: long_Array1d; array1StartFromIndex: int; const array2: long_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: long_Array1d absolute array1;
array2Instance: long_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 3, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.offsetOfEqualPtr(const array1; array1StartFromIndex: int; const array2; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: Pointer_Array1d absolute array1;
array2Instance: Pointer_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 3, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.offsetOfNonEqual(const array1: boolean_Array1d; array1StartFromIndex: int; const array2: boolean_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: boolean_Array1d absolute array1;
array2Instance: boolean_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 0, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.offsetOfNonEqual(const array1: char_Array1d; array1StartFromIndex: int; const array2: char_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: char_Array1d absolute array1;
array2Instance: char_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 0, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.offsetOfNonEqual(const array1: uchar_Array1d; array1StartFromIndex: int; const array2: uchar_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: uchar_Array1d absolute array1;
array2Instance: uchar_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 1, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.offsetOfNonEqual(const array1: byte_Array1d; array1StartFromIndex: int; const array2: byte_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: byte_Array1d absolute array1;
array2Instance: byte_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 0, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.offsetOfNonEqual(const array1: short_Array1d; array1StartFromIndex: int; const array2: short_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: short_Array1d absolute array1;
array2Instance: short_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 1, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.offsetOfNonEqual(const array1: int_Array1d; array1StartFromIndex: int; const array2: int_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: int_Array1d absolute array1;
array2Instance: int_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 2, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.offsetOfNonEqual(const array1: long_Array1d; array1StartFromIndex: int; const array2: long_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: long_Array1d absolute array1;
array2Instance: long_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 3, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.offsetOfNonEqualPtr(const array1; array1StartFromIndex: int; const array2; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: Pointer_Array1d absolute array1;
array2Instance: Pointer_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex < 0 then begin
array1StartFromIndex := 0;
end;
if array1StartFromIndex < array1Length then begin
array2Length := length(array2Instance);
if array2StartFromIndex < 0 then begin
array2StartFromIndex := 0;
end;
if array2StartFromIndex < array2Length then begin
limitScanLength := CoInt.min(array1Length - array1StartFromIndex, array2Length - array2StartFromIndex);
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compfne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 3, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfEqual(const array1: boolean_Array1d; array1StartFromIndex: int; const array2: boolean_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: boolean_Array1d absolute array1;
array2Instance: boolean_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 0, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfEqual(const array1: char_Array1d; array1StartFromIndex: int; const array2: char_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: char_Array1d absolute array1;
array2Instance: char_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 0, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfEqual(const array1: uchar_Array1d; array1StartFromIndex: int; const array2: uchar_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: uchar_Array1d absolute array1;
array2Instance: uchar_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 1, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfEqual(const array1: byte_Array1d; array1StartFromIndex: int; const array2: byte_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: byte_Array1d absolute array1;
array2Instance: byte_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 0, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfEqual(const array1: short_Array1d; array1StartFromIndex: int; const array2: short_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: short_Array1d absolute array1;
array2Instance: short_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 1, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfEqual(const array1: int_Array1d; array1StartFromIndex: int; const array2: int_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: int_Array1d absolute array1;
array2Instance: int_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 2, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfEqual(const array1: long_Array1d; array1StartFromIndex: int; const array2: long_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: long_Array1d absolute array1;
array2Instance: long_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 3, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfEqualPtr(const array1; array1StartFromIndex: int; const array2; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: Pointer_Array1d absolute array1;
array2Instance: Pointer_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbeq(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 3, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfNonEqual(const array1: boolean_Array1d; array1StartFromIndex: int; const array2: boolean_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: boolean_Array1d absolute array1;
array2Instance: boolean_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 0, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfNonEqual(const array1: char_Array1d; array1StartFromIndex: int; const array2: char_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: char_Array1d absolute array1;
array2Instance: char_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 0, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfNonEqual(const array1: uchar_Array1d; array1StartFromIndex: int; const array2: uchar_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: uchar_Array1d absolute array1;
array2Instance: uchar_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 1, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfNonEqual(const array1: byte_Array1d; array1StartFromIndex: int; const array2: byte_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: byte_Array1d absolute array1;
array2Instance: byte_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 0, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfNonEqual(const array1: short_Array1d; array1StartFromIndex: int; const array2: short_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: short_Array1d absolute array1;
array2Instance: short_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 1, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfNonEqual(const array1: int_Array1d; array1StartFromIndex: int; const array2: int_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: int_Array1d absolute array1;
array2Instance: int_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 2, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfNonEqual(const array1: long_Array1d; array1StartFromIndex: int; const array2: long_Array1d; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: long_Array1d absolute array1;
array2Instance: long_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 3, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.negOffsetOfNonEqualPtr(const array1; array1StartFromIndex: int; const array2; array2StartFromIndex: int; maximumScanLength: int): int;
var
array1Length: int;
array2Length: int;
limitScanLength: int;
array1Instance: Pointer_Array1d absolute array1;
array2Instance: Pointer_Array1d absolute array2;
begin
if (array1Instance <> nil) and (array2Instance <> nil) then begin
array1Length := length(array1Instance);
if array1StartFromIndex >= array1Length then begin
array1StartFromIndex := array1Length - 1;
end;
if array1StartFromIndex >= 0 then begin
array2Length := length(array2Instance);
if array2StartFromIndex >= array2Length then begin
array2StartFromIndex := array2Length - 1;
end;
if array2StartFromIndex >= 0 then begin
limitScanLength := CoInt.min(array1StartFromIndex, array2StartFromIndex) + 1;
if (maximumScanLength > 0) and (limitScanLength > maximumScanLength) then limitScanLength := maximumScanLength;
result := compbne(array1Instance[array1StartFromIndex], array2Instance[array2StartFromIndex], 3, limitScanLength);
exit;
end;
end;
end;
result := NOT_FOUND;
end;
class function &Array.newBoolean1d(length: int): boolean_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newBoolean1d(const components: array of boolean): boolean_Array1d;
var
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
copyBy1(components[0], result[0], long(len));
end;
end;
class function &Array.newChar1d(length: int): char_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newChar1d(const components: array of char): char_Array1d;
var
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
copyBy1(components[0], result[0], long(len));
end;
end;
class function &Array.newUChar1d(length: int): uchar_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newUChar1d(const components: array of uchar): uchar_Array1d;
var
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
copyBy2(components[0], result[0], long(len));
end;
end;
class function &Array.newByte1d(length: int): byte_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newByte1d(const components: array of byte): byte_Array1d;
var
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
copyBy1(components[0], result[0], long(len));
end;
end;
class function &Array.newShort1d(length: int): short_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newShort1d(const components: array of short): short_Array1d;
var
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
copyBy2(components[0], result[0], long(len));
end;
end;
class function &Array.newInt1d(length: int): int_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newInt1d(const components: array of int): int_Array1d;
var
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
copyBy4(components[0], result[0], long(len));
end;
end;
class function &Array.newLong1d(length: int): long_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newLong1d(const components: array of long): long_Array1d;
var
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
copyBy8(components[0], result[0], long(len));
end;
end;
class function &Array.newFloat1d(length: int): float_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newFloat1d(const components: array of float): float_Array1d;
var
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
copyBy4(components[0], result[0], long(len));
end;
end;
class function &Array.newDouble1d(length: int): double_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newDouble1d(const components: array of double): double_Array1d;
var
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
copyBy8(components[0], result[0], long(len));
end;
end;
class function &Array.newReal1d(length: int): real_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newReal1d(const components: array of real): real_Array1d;
var
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
copyBy2(components[0], result[0], long(len) * 5);
end;
end;
class function &Array.newAnsiString1d(length: int): AnsiString_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newAnsiString1d(const components: array of AnsiString): AnsiString_Array1d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newUnicodeString1d(length: int): UnicodeString_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newUnicodeString1d(const components: array of UnicodeString): UnicodeString_Array1d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newPointer1d(length: int): Pointer_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newPointer1d(const components: array of Pointer): Pointer_Array1d;
var
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
copyBy8(components[0], result[0], long(len));
end;
end;
class function &Array.newTObject1d(length: int): TObject_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newTObject1d(const components: array of TObject): TObject_Array1d;
var
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
copyBy8(components[0], result[0], long(len));
end;
end;
class function &Array.newISimple1d(length: int): ISimple_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newISimple1d(const components: array of ISimple): ISimple_Array1d;
var
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
copyBy8(components[0], result[0], long(len));
end;
end;
class function &Array.newIUnknown1d(length: int): IUnknown_Array1d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newIUnknown1d(const components: array of IUnknown): IUnknown_Array1d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newBoolean2d(length: int): boolean_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newBoolean2d(length1, length2: int): boolean_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newBoolean2d(const components: array of boolean_Array1d): boolean_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newChar2d(length: int): char_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newChar2d(length1, length2: int): char_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newChar2d(const components: array of char_Array1d): char_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newUChar2d(length: int): uchar_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newUChar2d(length1, length2: int): uchar_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newUChar2d(const components: array of uchar_Array1d): uchar_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newByte2d(length: int): byte_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newByte2d(length1, length2: int): byte_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newByte2d(const components: array of byte_Array1d): byte_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newShort2d(length: int): short_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newShort2d(length1, length2: int): short_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newShort2d(const components: array of short_Array1d): short_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newInt2d(length: int): int_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newInt2d(length1, length2: int): int_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newInt2d(const components: array of int_Array1d): int_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newLong2d(length: int): long_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newLong2d(length1, length2: int): long_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newLong2d(const components: array of long_Array1d): long_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newFloat2d(length: int): float_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newFloat2d(length1, length2: int): float_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newFloat2d(const components: array of float_Array1d): float_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newDouble2d(length: int): double_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newDouble2d(length1, length2: int): double_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newDouble2d(const components: array of double_Array1d): double_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newReal2d(length: int): real_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newReal2d(length1, length2: int): real_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newReal2d(const components: array of real_Array1d): real_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newAnsiString2d(length: int): AnsiString_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newAnsiString2d(length1, length2: int): AnsiString_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newAnsiString2d(const components: array of AnsiString_Array1d): AnsiString_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newUnicodeString2d(length: int): UnicodeString_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newUnicodeString2d(length1, length2: int): UnicodeString_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newUnicodeString2d(const components: array of UnicodeString_Array1d): UnicodeString_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newPointer2d(length: int): Pointer_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newPointer2d(length1, length2: int): Pointer_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newPointer2d(const components: array of Pointer_Array1d): Pointer_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newTObject2d(length: int): TObject_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newTObject2d(length1, length2: int): TObject_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newTObject2d(const components: array of TObject_Array1d): TObject_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newISimple2d(length: int): ISimple_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newISimple2d(length1, length2: int): ISimple_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newISimple2d(const components: array of ISimple_Array1d): ISimple_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
class function &Array.newIUnknown2d(length: int): IUnknown_Array2d;
begin
if length < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
setLength(result, length);
end;
class function &Array.newIUnknown2d(length1, length2: int): IUnknown_Array2d;
var
idx: int;
begin
if (length1 or length2) < 0 then begin
raise NegativeArraySizeException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'negative-array-length'));
end;
result := nil;
if length1 > 0 then begin
setLength(result, length1);
if length2 > 0 then begin
for idx := length1 - 1 downto 0 do setLength(result[idx], length2);
end;
end;
end;
class function &Array.newIUnknown2d(const components: array of IUnknown_Array1d): IUnknown_Array2d;
var
idx: int;
len: int;
begin
result := nil;
len := length(components);
if len > 0 then begin
setLength(result, len);
for idx := len - 1 downto 0 do result[idx] := components[idx];
end;
end;
{%endregion}
{%region TObjectExtended}
class function TObjectExtended.getPropertyInfo(const name: AnsiString): PPropInfo;
var
idx: int;
len: int;
lennm: int;
lownm: AnsiString;
prpnm: AnsiString;
pinfo: PPropInfo;
tinfo: PTypeInfo;
tdata: PTypeData;
begin
lownm := name.toLowerCase();
lennm := lownm.length;
tinfo := PTypeInfo(classInfo());
while tinfo <> nil do begin
tdata := getTypeData(tinfo);
pinfo := PPropInfo(Pointer(@(tdata^.unitName[1])) + int(tdata^.unitName[0]));
len := system.PUInt16(pinfo)^;
pinfo := Pointer(pinfo) + 2;
for idx := len - 1 downto 0 do begin
prpnm := pinfo^.name;
if (prpnm.length = lennm) and (prpnm.toLowerCase() = lownm) then begin
result := pinfo;
exit;
end;
pinfo := PPropInfo(Pointer(@(pinfo^.name[1])) + int(pinfo^.name[0]));
end;
tinfo := tdata^.parentInfo;
end;
result := nil;
end;
procedure TObjectExtended.writePropertyOfBoolean(const name: AnsiString; const value: boolean);
type
ProcedureWriteIndexedValueOfBoolean = procedure(index: int; value: boolean) of object;
ProcedureWriteValueOfBoolean = procedure(value: boolean) of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
access := pinfo^.setProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(pinfo^.propType);
case propertyTypeKind of
Lang.TYPE_BOOLEAN: begin
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := (transferDataKind shr 2) and $03;
case transferDataKind of
TM_FIELD: begin
address := Pointer(self) + offset;
boolean(address^) := value;
end;
TM_SPECIAL, TM_VIRTUAL: begin
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
ProcedureWriteIndexedValueOfBoolean(method)(pinfo^.index, value);
exit;
end;
ProcedureWriteValueOfBoolean(method)(value);
end;
end;
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
procedure TObjectExtended.writePropertyOfLong(const name: AnsiString; const value: long);
type
ProcedureWriteIndexedValueOfUByte = procedure(index: int; value: system.UInt8) of object;
ProcedureWriteIndexedValueOfUShort = procedure(index: int; value: system.UInt16) of object;
ProcedureWriteIndexedValueOfUInt = procedure(index: int; value: system.UInt32) of object;
ProcedureWriteIndexedValueOfByte = procedure(index: int; value: byte) of object;
ProcedureWriteIndexedValueOfShort = procedure(index: int; value: short) of object;
ProcedureWriteIndexedValueOfInt = procedure(index: int; value: int) of object;
ProcedureWriteIndexedValueOfLong = procedure(index: int; value: long) of object;
ProcedureWriteValueOfUByte = procedure(value: system.UInt8) of object;
ProcedureWriteValueOfUShort = procedure(value: system.UInt16) of object;
ProcedureWriteValueOfUInt = procedure(value: system.UInt32) of object;
ProcedureWriteValueOfByte = procedure(value: byte) of object;
ProcedureWriteValueOfShort = procedure(value: short) of object;
ProcedureWriteValueOfInt = procedure(value: int) of object;
ProcedureWriteValueOfLong = procedure(value: long) of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
access := pinfo^.setProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(pinfo^.propType);
case propertyTypeKind of
Lang.TYPE_CHAR, Lang.TYPE_BYTE, Lang.TYPE_SHORT, Lang.TYPE_INT, Lang.TYPE_LONG, Lang.TYPE_UCHAR, Lang.TYPE_UBYTE, Lang.TYPE_USHORT, Lang.TYPE_UINT, Lang.TYPE_ULONG: begin
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := (transferDataKind shr 2) and $03;
case transferDataKind of
TM_FIELD: begin
address := Pointer(self) + offset;
case propertyTypeKind of
Lang.TYPE_BYTE, Lang.TYPE_UBYTE, Lang.TYPE_CHAR:
byte(address^) := byte(value);
Lang.TYPE_SHORT, Lang.TYPE_USHORT, Lang.TYPE_UCHAR:
short(address^) := short(value);
Lang.TYPE_INT, Lang.TYPE_UINT:
int(address^) := int(value);
else
long(address^) := value;
end;
end;
TM_SPECIAL, TM_VIRTUAL: begin
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
case propertyTypeKind of
Lang.TYPE_UBYTE, Lang.TYPE_CHAR:
ProcedureWriteIndexedValueOfUByte(method)(pinfo^.index, system.UInt8(value));
Lang.TYPE_USHORT, Lang.TYPE_UCHAR:
ProcedureWriteIndexedValueOfUShort(method)(pinfo^.index, system.UInt16(value));
Lang.TYPE_UINT:
ProcedureWriteIndexedValueOfUInt(method)(pinfo^.index, system.UInt32(value));
Lang.TYPE_BYTE:
ProcedureWriteIndexedValueOfByte(method)(pinfo^.index, byte(value));
Lang.TYPE_SHORT:
ProcedureWriteIndexedValueOfShort(method)(pinfo^.index, short(value));
Lang.TYPE_INT:
ProcedureWriteIndexedValueOfInt(method)(pinfo^.index, int(value));
else
ProcedureWriteIndexedValueOfLong(method)(pinfo^.index, value);
end;
exit;
end;
case propertyTypeKind of
Lang.TYPE_UBYTE, Lang.TYPE_CHAR:
ProcedureWriteValueOfUByte(method)(system.UInt8(value));
Lang.TYPE_USHORT, Lang.TYPE_UCHAR:
ProcedureWriteValueOfUShort(method)(system.UInt16(value));
Lang.TYPE_UINT:
ProcedureWriteValueOfUInt(method)(system.UInt32(value));
Lang.TYPE_BYTE:
ProcedureWriteValueOfByte(method)(byte(value));
Lang.TYPE_SHORT:
ProcedureWriteValueOfShort(method)(short(value));
Lang.TYPE_INT:
ProcedureWriteValueOfInt(method)(int(value));
else
ProcedureWriteValueOfLong(method)(value);
end;
end;
end;
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
procedure TObjectExtended.writePropertyOfDouble(const name: AnsiString; const value: double);
type
ProcedureWriteIndexedValueOfFloat = procedure(index: int; value: float) of object;
ProcedureWriteIndexedValueOfDouble = procedure(index: int; value: double) of object;
ProcedureWriteValueOfFloat = procedure(value: float) of object;
ProcedureWriteValueOfDouble = procedure(value: double) of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
access := pinfo^.setProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(pinfo^.propType);
case propertyTypeKind of
Lang.TYPE_FLOAT, Lang.TYPE_DOUBLE: begin
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := (transferDataKind shr 2) and $03;
case transferDataKind of
TM_FIELD: begin
address := Pointer(self) + offset;
case propertyTypeKind of
Lang.TYPE_FLOAT:
float(address^) := CoDouble.toFloat(value);
else
double(address^) := value;
end;
end;
TM_SPECIAL, TM_VIRTUAL: begin
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
case propertyTypeKind of
Lang.TYPE_FLOAT:
ProcedureWriteIndexedValueOfFloat(method)(pinfo^.index, CoDouble.toFloat(value));
else
ProcedureWriteIndexedValueOfDouble(method)(pinfo^.index, value);
end;
exit;
end;
case propertyTypeKind of
Lang.TYPE_FLOAT:
ProcedureWriteValueOfFloat(method)(CoDouble.toFloat(value));
else
ProcedureWriteValueOfDouble(method)(value);
end;
end;
end;
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
procedure TObjectExtended.writePropertyOfAnsiString(const name: AnsiString; const value: AnsiString);
type
ProcedureWriteIndexedValueOfAnsiString = procedure(index: int; value: AnsiString) of object;
ProcedureWriteValueOfAnsiString = procedure(value: AnsiString) of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
access := pinfo^.setProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(pinfo^.propType);
case propertyTypeKind of
Lang.TYPE_ANSISTRING: begin
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := (transferDataKind shr 2) and $03;
case transferDataKind of
TM_FIELD: begin
address := Pointer(self) + offset;
AnsiString(address^) := value;
end;
TM_SPECIAL, TM_VIRTUAL: begin
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
ProcedureWriteIndexedValueOfAnsiString(method)(pinfo^.index, value);
exit;
end;
ProcedureWriteValueOfAnsiString(method)(value);
end;
end;
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
procedure TObjectExtended.writePropertyOfUnicodeString(const name: AnsiString; const value: UnicodeString);
type
ProcedureWriteIndexedValueOfUnicodeString = procedure(index: int; value: UnicodeString) of object;
ProcedureWriteValueOfUnicodeString = procedure(value: UnicodeString) of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
access := pinfo^.setProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(pinfo^.propType);
case propertyTypeKind of
Lang.TYPE_UNICODESTRING: begin
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := (transferDataKind shr 2) and $03;
case transferDataKind of
TM_FIELD: begin
address := Pointer(self) + offset;
UnicodeString(address^) := value;
end;
TM_SPECIAL, TM_VIRTUAL: begin
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
ProcedureWriteIndexedValueOfUnicodeString(method)(pinfo^.index, value);
exit;
end;
ProcedureWriteValueOfUnicodeString(method)(value);
end;
end;
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
procedure TObjectExtended.writePropertyOfObject(const name: AnsiString; const value: TObject);
type
ProcedureWriteIndexedValueOfObject = procedure(index: int; value: TObject) of object;
ProcedureWriteValueOfObject = procedure(value: TObject) of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
propertyTypeInfo: PTypeInfo;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
access := pinfo^.setProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeInfo := pinfo^.propType;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(propertyTypeInfo);
case propertyTypeKind of
Lang.TYPE_CLASS: begin
if (value <> nil) and not (ClassTypeInformation.create(propertyTypeInfo) as &Class).isAssignableFrom(value.getClass()) then begin
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := (transferDataKind shr 2) and $03;
case transferDataKind of
TM_FIELD: begin
address := Pointer(self) + offset;
TObject(address^) := value;
end;
TM_SPECIAL, TM_VIRTUAL: begin
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
ProcedureWriteIndexedValueOfObject(method)(pinfo^.index, value);
exit;
end;
ProcedureWriteValueOfObject(method)(value);
end;
end;
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
procedure TObjectExtended.writePropertyOfSimple(const name: AnsiString; const value: ISimple);
type
ProcedureWriteIndexedValueOfInterface = procedure(index: int; value: ISimple) of object;
ProcedureWriteValueOfInterface = procedure(value: ISimple) of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
propertyTypeInfo: PTypeInfo;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
vtemp: ISimple;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
access := pinfo^.setProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeInfo := pinfo^.propType;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(propertyTypeInfo);
case propertyTypeKind of
Lang.TYPE_INTERFACE_RAW: begin
vtemp := nil;
if (value <> nil) and (value.queryInterface(getTypeData(propertyTypeInfo)^.guid, vtemp) <> system.S_OK) then begin
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := (transferDataKind shr 2) and $03;
case transferDataKind of
TM_FIELD: begin
address := Pointer(self) + offset;
ISimple(address^) := vtemp;
end;
TM_SPECIAL, TM_VIRTUAL: begin
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
ProcedureWriteIndexedValueOfInterface(method)(pinfo^.index, vtemp);
exit;
end;
ProcedureWriteValueOfInterface(method)(vtemp);
end;
end;
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
procedure TObjectExtended.writePropertyOfUnknown(const name: AnsiString; const value: IUnknown);
type
ProcedureWriteIndexedValueOfInterface = procedure(index: int; value: IUnknown) of object;
ProcedureWriteValueOfInterface = procedure(value: IUnknown) of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
propertyTypeInfo: PTypeInfo;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
vtemp: IUnknown;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
access := pinfo^.setProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeInfo := pinfo^.propType;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(propertyTypeInfo);
case propertyTypeKind of
Lang.TYPE_INTERFACE_RC: begin
vtemp := nil;
if (value <> nil) and (value.queryInterface(getTypeData(propertyTypeInfo)^.guid, vtemp) <> system.S_OK) then begin
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := (transferDataKind shr 2) and $03;
case transferDataKind of
TM_FIELD: begin
address := Pointer(self) + offset;
IUnknown(address^) := vtemp;
end;
TM_SPECIAL, TM_VIRTUAL: begin
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
ProcedureWriteIndexedValueOfInterface(method)(pinfo^.index, vtemp);
exit;
end;
ProcedureWriteValueOfInterface(method)(vtemp);
end;
end;
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
function TObjectExtended.isStoredProperty(const name: AnsiString): boolean;
type
FunctionIsStoredIndexed = function(index: int): boolean of object;
FunctionIsStoredVoid = function(): boolean of object;
var
isIndexed: boolean;
transferDataKind: int;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := (transferDataKind shr 4) and $03;
case transferDataKind of
TM_FIELD: begin
access := pinfo^.storedProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
address := Pointer(self) + offset;
end;
TM_CONST: begin
address := @(pinfo^.storedProc);
end;
else
access := pinfo^.storedProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
result := FunctionIsStoredIndexed(method)(pinfo^.index);
exit;
end;
result := FunctionIsStoredVoid(method)();
exit;
end;
result := byte(address^) <> 0;
end;
function TObjectExtended.readPropertyOfBoolean(const name: AnsiString): boolean;
type
FunctionReadIndexedValueOfBoolean = function(index: int): boolean of object;
FunctionReadValueOfBoolean = function(): boolean of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(pinfo^.propType);
case propertyTypeKind of
Lang.TYPE_BOOLEAN: begin
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := transferDataKind and $03;
case transferDataKind of
TM_FIELD: begin
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
address := Pointer(self) + offset;
end;
TM_CONST: begin
address := @(pinfo^.getProc);
end;
else
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
result := FunctionReadIndexedValueOfBoolean(method)(pinfo^.index);
exit;
end;
result := FunctionReadValueOfBoolean(method)();
exit;
end;
result := byte(address^) <> 0;
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
function TObjectExtended.readPropertyOfLong(const name: AnsiString): long;
type
FunctionReadIndexedValueOfUByte = function(index: int): system.UInt8 of object;
FunctionReadIndexedValueOfUShort = function(index: int): system.UInt16 of object;
FunctionReadIndexedValueOfUInt = function(index: int): system.UInt32 of object;
FunctionReadIndexedValueOfByte = function(index: int): byte of object;
FunctionReadIndexedValueOfShort = function(index: int): short of object;
FunctionReadIndexedValueOfInt = function(index: int): int of object;
FunctionReadIndexedValueOfLong = function(index: int): long of object;
FunctionReadValueOfUByte = function(): system.UInt8 of object;
FunctionReadValueOfUShort = function(): system.UInt16 of object;
FunctionReadValueOfUInt = function(): system.UInt32 of object;
FunctionReadValueOfByte = function(): byte of object;
FunctionReadValueOfShort = function(): short of object;
FunctionReadValueOfInt = function(): int of object;
FunctionReadValueOfLong = function(): long of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(pinfo^.propType);
case propertyTypeKind of
Lang.TYPE_CHAR, Lang.TYPE_BYTE, Lang.TYPE_SHORT, Lang.TYPE_INT, Lang.TYPE_LONG, Lang.TYPE_UCHAR, Lang.TYPE_UBYTE, Lang.TYPE_USHORT, Lang.TYPE_UINT, Lang.TYPE_ULONG: begin
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := transferDataKind and $03;
case transferDataKind of
TM_FIELD: begin
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
address := Pointer(self) + offset;
end;
TM_CONST: begin
address := @(pinfo^.getProc);
end;
else
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
case propertyTypeKind of
Lang.TYPE_UBYTE, Lang.TYPE_CHAR:
result := FunctionReadIndexedValueOfUByte(method)(pinfo^.index);
Lang.TYPE_USHORT, Lang.TYPE_UCHAR:
result := FunctionReadIndexedValueOfUShort(method)(pinfo^.index);
Lang.TYPE_UINT:
result := FunctionReadIndexedValueOfUInt(method)(pinfo^.index);
Lang.TYPE_BYTE:
result := FunctionReadIndexedValueOfByte(method)(pinfo^.index);
Lang.TYPE_SHORT:
result := FunctionReadIndexedValueOfShort(method)(pinfo^.index);
Lang.TYPE_INT:
result := FunctionReadIndexedValueOfInt(method)(pinfo^.index);
else
result := FunctionReadIndexedValueOfLong(method)(pinfo^.index);
end;
exit;
end;
case propertyTypeKind of
Lang.TYPE_UBYTE, Lang.TYPE_CHAR:
result := FunctionReadValueOfUByte(method)();
Lang.TYPE_USHORT, Lang.TYPE_UCHAR:
result := FunctionReadValueOfUShort(method)();
Lang.TYPE_UINT:
result := FunctionReadValueOfUInt(method)();
Lang.TYPE_BYTE:
result := FunctionReadValueOfByte(method)();
Lang.TYPE_SHORT:
result := FunctionReadValueOfShort(method)();
Lang.TYPE_INT:
result := FunctionReadValueOfInt(method)();
else
result := FunctionReadValueOfLong(method)();
end;
exit;
end;
case propertyTypeKind of
Lang.TYPE_UBYTE, Lang.TYPE_CHAR:
result := system.UInt8(address^);
Lang.TYPE_USHORT, Lang.TYPE_UCHAR:
result := system.UInt16(address^);
Lang.TYPE_UINT:
result := system.UInt32(address^);
Lang.TYPE_BYTE:
result := byte(address^);
Lang.TYPE_SHORT:
result := short(address^);
Lang.TYPE_INT:
result := int(address^);
else
result := long(address^);
end;
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
function TObjectExtended.readPropertyOfDouble(const name: AnsiString): double;
type
FunctionReadIndexedValueOfFloat = function(index: int): float of object;
FunctionReadIndexedValueOfDouble = function(index: int): double of object;
FunctionReadValueOfFloat = function(): float of object;
FunctionReadValueOfDouble = function(): double of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(pinfo^.propType);
case propertyTypeKind of
Lang.TYPE_FLOAT, Lang.TYPE_DOUBLE: begin
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := transferDataKind and $03;
case transferDataKind of
TM_FIELD: begin
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
address := Pointer(self) + offset;
end;
TM_CONST: begin
address := @(pinfo^.getProc);
end;
else
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
case propertyTypeKind of
Lang.TYPE_FLOAT:
result := FunctionReadIndexedValueOfFloat(method)(pinfo^.index);
else
result := FunctionReadIndexedValueOfDouble(method)(pinfo^.index);
end;
exit;
end;
case propertyTypeKind of
Lang.TYPE_FLOAT:
result := FunctionReadValueOfFloat(method)();
else
result := FunctionReadValueOfDouble(method)();
end;
exit;
end;
case propertyTypeKind of
Lang.TYPE_FLOAT:
result := float(address^);
else
result := double(address^);
end;
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
function TObjectExtended.readPropertyOfAnsiString(const name: AnsiString): AnsiString;
type
FunctionReadIndexedValueOfAnsiString = function(index: int): AnsiString of object;
FunctionReadValueOfAnsiString = function(): AnsiString of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(pinfo^.propType);
case propertyTypeKind of
Lang.TYPE_ANSISTRING: begin
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := transferDataKind and $03;
case transferDataKind of
TM_FIELD: begin
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
address := Pointer(self) + offset;
end;
TM_CONST: begin
address := @(pinfo^.getProc);
end;
else
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
result := FunctionReadIndexedValueOfAnsiString(method)(pinfo^.index);
exit;
end;
result := FunctionReadValueOfAnsiString(method)();
exit;
end;
result := AnsiString(address^);
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
function TObjectExtended.readPropertyOfUnicodeString(const name: AnsiString): UnicodeString;
type
FunctionReadIndexedValueOfUnicodeString = function(index: int): UnicodeString of object;
FunctionReadValueOfUnicodeString = function(): UnicodeString of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(pinfo^.propType);
case propertyTypeKind of
Lang.TYPE_UNICODESTRING: begin
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := transferDataKind and $03;
case transferDataKind of
TM_FIELD: begin
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
address := Pointer(self) + offset;
end;
TM_CONST: begin
address := @(pinfo^.getProc);
end;
else
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
result := FunctionReadIndexedValueOfUnicodeString(method)(pinfo^.index);
exit;
end;
result := FunctionReadValueOfUnicodeString(method)();
exit;
end;
result := UnicodeString(address^);
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
function TObjectExtended.readPropertyOfObject(const name: AnsiString): TObject;
type
FunctionReadIndexedValueOfObject = function(index: int): TObject of object;
FunctionReadValueOfObject = function(): TObject of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(pinfo^.propType);
case propertyTypeKind of
Lang.TYPE_CLASS: begin
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := transferDataKind and $03;
case transferDataKind of
TM_FIELD: begin
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
address := Pointer(self) + offset;
end;
TM_CONST: begin
address := @(pinfo^.getProc);
end;
else
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
result := FunctionReadIndexedValueOfObject(method)(pinfo^.index);
exit;
end;
result := FunctionReadValueOfObject(method)();
exit;
end;
result := TObject(address^);
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
function TObjectExtended.readPropertyOfSimple(const name: AnsiString): ISimple;
type
FunctionReadIndexedValueOfInterface = function(index: int): ISimple of object;
FunctionReadValueOfInterface = function(): ISimple of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(pinfo^.propType);
case propertyTypeKind of
Lang.TYPE_INTERFACE_RAW: begin
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := transferDataKind and $03;
case transferDataKind of
TM_FIELD: begin
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
address := Pointer(self) + offset;
end;
TM_CONST: begin
address := @(pinfo^.getProc);
end;
else
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
result := FunctionReadIndexedValueOfInterface(method)(pinfo^.index);
exit;
end;
result := FunctionReadValueOfInterface(method)();
exit;
end;
result := ISimple(address^);
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
function TObjectExtended.readPropertyOfUnknown(const name: AnsiString): IUnknown;
type
FunctionReadIndexedValueOfInterface = function(index: int): IUnknown of object;
FunctionReadValueOfInterface = function(): IUnknown of object;
var
isIndexed: boolean;
transferDataKind: int;
propertyTypeKind: int;
offset: long;
access: CodePointer absolute offset;
pinfo: PPropInfo;
address: Pointer;
method: TMethod;
begin
pinfo := getPropertyInfo(name);
if pinfo = nil then begin
raise PropertyNotFoundException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'not-found.property'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
propertyTypeKind := ClassTypeInformation.typeInfoToLangType(pinfo^.propType);
case propertyTypeKind of
Lang.TYPE_INTERFACE_RC: begin
transferDataKind := pinfo^.propProcs;
isIndexed := (transferDataKind and $40) <> 0;
transferDataKind := transferDataKind and $03;
case transferDataKind of
TM_FIELD: begin
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
address := Pointer(self) + offset;
end;
TM_CONST: begin
address := @(pinfo^.getProc);
end;
else
access := pinfo^.getProc;
if access = nil then begin
raise IllegalPropertyAccessException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.access'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
if transferDataKind = TM_SPECIAL then begin
method.code := access;
end else begin
method.code := CodePointer((Pointer(classType()) + offset)^);
end;
method.data := self;
if isIndexed then begin
result := FunctionReadIndexedValueOfInterface(method)(pinfo^.index);
exit;
end;
result := FunctionReadValueOfInterface(method)();
exit;
end;
result := IUnknown(address^);
end;
else
raise IllegalPropertyTypeException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'property-operation.type'), [
CoAnsiString.create(name), CoAnsiString.create(getClass().getCanonicalName())
]));
end;
end;
function TObjectExtended.getClass(): &Class;
begin
result := ClassTypeInformation.create(classType());
end;
{%endregion}
{%region ISimpleExtended}
function ISimpleExtended.getClass(): &Class;
var
asObject: TObject;
begin
if queryInterface(IObjectInstance, asObject) <> system.S_OK then begin
result := InterfaceTypeInformation.create(PTypeInfo(typeInfo(ISimple)));
exit;
end;
result := ClassTypeInformation.create(asObject.classType());
end;
{%endregion}
{%region IUnknownExtended}
function IUnknownExtended.getClass(): &Class;
var
asObject: TObject;
begin
if queryInterface(IObjectInstance, asObject) <> system.S_OK then begin
result := InterfaceTypeInformation.create(PTypeInfo(typeInfo(IUnknown)));
exit;
end;
result := ClassTypeInformation.create(asObject.classType());
end;
{%endregion}
{%region AnsiStringExtended}
class function AnsiStringExtended.create(length: int): AnsiString;
begin
if length < 0 then length := 0;
result := '';
setLength(result, length);
end;
class function AnsiStringExtended.create(const src: byte_Array1d): AnsiString;
var
len: int;
begin
len := system.length(src);
result := '';
setLength(result, len);
&Array.copyRaw(src[0], result[1], len);
end;
class function AnsiStringExtended.create(const src: char_Array1d): AnsiString;
var
len: int;
begin
len := system.length(src);
result := '';
setLength(result, len);
&Array.copyRaw(src[0], result[1], len);
end;
class function AnsiStringExtended.create(const src: byte_Array1d; offset, length: int): AnsiString;
begin
&Array.checkBounds(src, offset, length);
result := '';
setLength(result, length);
&Array.copyRaw(src[offset], result[1], length);
end;
class function AnsiStringExtended.create(const src: char_Array1d; offset, length: int): AnsiString;
begin
&Array.checkBounds(src, offset, length);
result := '';
setLength(result, length);
&Array.copyRaw(src[offset], result[1], length);
end;
class function AnsiStringExtended.create(const charCodes: int_Array1d; offset, length: int): AnsiString;
var
idx: int;
cap: int;
len: int;
ccd: int;
buf: byte_Array1d;
begin
&Array.checkBounds(charCodes, offset, length);
len := 0;
cap := int(CoLong.min(long(length) * 6, CoInt.MAX_VALUE));
buf := &Array.newByte1d(cap);
for idx := offset to offset + length - 1 do begin
ccd := charCodes[idx];
if (ccd >= $00000001) and (ccd < $00000080) then begin
if len >= cap then break;
buf[len] := byte(ccd);
inc(len);
end else
if (ccd >= $00000000) and (ccd < $00000800) then begin
if len >= cap - 1 then break;
buf[len] := byte($c0 + (ccd shr 6));
buf[len + 1] := byte($80 + (ccd and $3f));
inc(len, 2);
end else
if (ccd >= $00000800) and (ccd < $00010000) then begin
if len >= cap - 2 then break;
buf[len] := byte($e0 + (ccd shr 12));
buf[len + 1] := byte($80 + ((ccd shr 6) and $3f));
buf[len + 2] := byte($80 + (ccd and $3f));
inc(len, 3);
end else
if (ccd >= $00010000) and (ccd < $00200000) then begin
if len >= cap - 3 then break;
buf[len] := byte($f0 + (ccd shr 18));
buf[len + 1] := byte($80 + ((ccd shr 12) and $3f));
buf[len + 2] := byte($80 + ((ccd shr 6) and $3f));
buf[len + 3] := byte($80 + (ccd and $3f));
inc(len, 4);
end else
if (ccd >= $00200000) and (ccd < $04000000) then begin
if len >= cap - 4 then break;
buf[len] := byte($f8 + (ccd shr 24));
buf[len + 1] := byte($80 + ((ccd shr 18) and $3f));
buf[len + 2] := byte($80 + ((ccd shr 12) and $3f));
buf[len + 3] := byte($80 + ((ccd shr 6) and $3f));
buf[len + 4] := byte($80 + (ccd and $3f));
inc(len, 5);
end else begin
if len >= cap - 5 then break;
buf[len] := byte($fc + (ccd shr 30));
buf[len + 1] := byte($80 + ((ccd shr 24) and $3f));
buf[len + 2] := byte($80 + ((ccd shr 18) and $3f));
buf[len + 3] := byte($80 + ((ccd shr 12) and $3f));
buf[len + 4] := byte($80 + ((ccd shr 6) and $3f));
buf[len + 5] := byte($80 + (ccd and $3f));
inc(len, 6);
end;
end;
result := create(buf, 0, len);
end;
class function AnsiStringExtended.format(const form: AnsiString; const data: array of Value): AnsiString;
var
isReal: boolean;
isString: boolean;
isExpForm: boolean;
significandAll: boolean;
significandSign: boolean;
orderSign: boolean;
leadZeroOutput: boolean;
formChar: char;
formDigit: int;
beginIndex: int;
endIndex: int;
formIndex: int;
dataIndex: int;
formLength: int;
dataLimit: int absolute high(data);
significandDigits: int;
orderDigits: int;
leadZeroWidth: int;
fieldWidth: int;
formattedWidth: int;
count: int;
number: long;
formattedInstance: AnsiString;
formInstance: AnsiString absolute form;
dataArray: array [0..0] of Value absolute data;
dataComponent: Value;
label
break_label0,
continue_label0;
begin
formLength := formInstance.length;
if formLength <= 0 then begin
result := '';
exit;
end;
result := '';
beginIndex := 1;
endIndex := formInstance.indexOf('%');
while endIndex - 1 >= 0 do begin
result := result + formInstance.substring(beginIndex, endIndex);
beginIndex := endIndex;
formIndex := beginIndex + 1;
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if formChar = '%' then begin
endIndex := formIndex + 1;
result := result + '%';
goto continue_label0;
end;
if (formChar < '0') or (formChar > '9') then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
dataIndex := int(formChar) - int('0');
repeat
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if (formChar < '0') or (formChar > '9') then break;
formDigit := int(formChar) - int('0');
if dataIndex > CoInt.MAX_VALUE div 10 then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
dataIndex := dataIndex * 10;
if dataIndex > CoInt.MAX_VALUE - formDigit then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
dataIndex := dataIndex + formDigit;
until false;
isReal := false;
isString := true;
isExpForm := false;
significandAll := false;
significandSign := false;
orderSign := true;
leadZeroOutput := false;
significandDigits := 1;
orderDigits := 0;
leadZeroWidth := 0;
if formChar = '#' then begin
isString := false;
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if formChar = '+' then begin
significandSign := true;
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
end;
if formChar = '0' then begin
leadZeroOutput := true;
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if (formChar < '0') or (formChar > '9') then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
leadZeroWidth := int(formChar) - int('0');
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if (formChar >= '0') and (formChar <= '9') then begin
leadZeroWidth := (leadZeroWidth * 10) + (int(formChar) - int('0'));
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
end;
end else begin
if formChar <> '1' then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if formChar = '.' then begin
isReal := true;
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if (formChar < '0') or (formChar > '9') then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
significandDigits := int(formChar) - int('0');
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if (formChar >= '0') and (formChar <= '9') then begin
significandDigits := (significandDigits * 10) + (int(formChar) - int('0'));
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
end;
if significandDigits < 1 then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
inc(significandDigits);
if (formChar = 'A') or (formChar = 'a') then begin
significandAll := true;
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
end;
end;
isExpForm := formChar = 'E';
if isExpForm or (formChar = 'e') then begin
isReal := true;
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if formChar <> '+' then begin
orderSign := false;
end else begin
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
end;
if (formChar < '0') or (formChar > '4') then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
orderDigits := int(formChar) - int('0');
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
end;
end;
end;
fieldWidth := 0;
if formChar = ':' then begin
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if (formChar < '0') or (formChar > '9') then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
fieldWidth := int(formChar) - int('0');
repeat
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if (formChar < '0') or (formChar > '9') then break;
formDigit := int(formChar) - int('0');
fieldWidth := fieldWidth * 10;
if fieldWidth > 1024 - formDigit then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
fieldWidth := fieldWidth + formDigit;
until false;
end;
if formChar <> '%' then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
if (dataIndex < 0) or (dataIndex > dataLimit) then begin
raise ArrayIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.array-index'));
end;
dataComponent := dataArray[dataIndex];
if dataComponent = nil then begin
raise NullPointerException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'null-pointer'));
end;
if isString then begin
formattedInstance := dataComponent.toString();
end else
if isReal then begin
if significandDigits <= 1 then significandDigits := RealRepresenter.MAX_SIGNIFICAND_DIGITS;
formattedInstance := CoReal.toString(dataComponent.asReal(), significandDigits, orderDigits, significandAll, orderDigits > 0, isExpForm, significandSign, orderSign);
end else begin
number := dataComponent.asLong();
if leadZeroOutput then begin
formattedInstance := CoLong.toLeadZeroString(number, leadZeroWidth);
end else begin
formattedInstance := CoLong.toString(number);
end;
if significandSign and (number >= 0) then formattedInstance := '+' + formattedInstance;
end;
formattedWidth := formattedInstance.length;
if fieldWidth > formattedWidth then for count := fieldWidth - formattedWidth - 1 downto 0 do result := result + ' ';
endIndex := formIndex + 1;
result := result + formattedInstance;
continue_label0:
beginIndex := endIndex;
endIndex := formInstance.indexOf('%', beginIndex);
end;
break_label0:
result := result + formInstance.substring(beginIndex);
end;
function AnsiStringExtended.getLength(): int;
begin
result := system.length(self);
end;
procedure AnsiStringExtended.getChars(beginIndex, endIndex: int; const dst: char_Array1d; offset: int);
var
thisLength: int;
begin
dec(endIndex);
dec(beginIndex);
thisLength := length;
if ((beginIndex or endIndex) < 0) or (beginIndex > thisLength) or (endIndex > thisLength) or (beginIndex > endIndex) then begin
raise StringIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.string-index'));
end;
thisLength := endIndex - beginIndex;
&Array.checkBounds(dst, offset, thisLength);
&Array.copyRaw(self[beginIndex + 1], dst[offset], thisLength);
end;
function AnsiStringExtended.startsWith(const prefix: AnsiString; position: int): boolean;
var
anotLength: int;
begin
dec(position);
anotLength := prefix.length;
if (position < 0) or (position > length - anotLength) then begin
result := false;
exit;
end;
result := (anotLength <= 0) or (&Array.compfne(self[position + 1], prefix[1], 0, anotLength) = &Array.NOT_FOUND);
end;
function AnsiStringExtended.endsWith(const suffix: AnsiString): boolean;
var
position: int;
anotLength: int;
begin
anotLength := suffix.length;
position := length - anotLength;
if position < 0 then begin
result := false;
exit;
end;
result := (anotLength <= 0) or (&Array.compfne(self[position + 1], suffix[1], 0, anotLength) = &Array.NOT_FOUND);
end;
function AnsiStringExtended.indexOf(const prefix: AnsiString; startFromIndex: int): int;
var
anotLength: int;
thisLength: int;
thisOffset: int;
firstCharValue: long;
begin
dec(startFromIndex);
anotLength := prefix.length;
thisLength := length - anotLength;
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex > thisLength then begin
result := 0;
exit;
end;
if anotLength <= 0 then begin
result := startFromIndex + 1;
exit;
end;
dec(anotLength);
inc(thisLength);
firstCharValue := long(prefix[1]);
repeat
thisOffset := &Array.findfeq(self[startFromIndex + 1], 0, thisLength - startFromIndex, firstCharValue);
if thisOffset = &Array.NOT_FOUND then break;
inc(startFromIndex, thisOffset);
if (anotLength <= 0) or (&Array.compfne(self[startFromIndex + 2], prefix[2], 0, anotLength) = &Array.NOT_FOUND) then begin
result := startFromIndex + 1;
exit;
end;
inc(startFromIndex);
until startFromIndex >= thisLength;
result := 0;
end;
function AnsiStringExtended.lastIndexOf(const prefix: AnsiString; startFromIndex: int): int;
var
anotLength: int;
thisLength: int;
thisOffset: int;
firstCharValue: long;
begin
dec(startFromIndex);
anotLength := prefix.length;
thisLength := length - anotLength;
if startFromIndex > thisLength then begin
startFromIndex := thisLength;
end;
if startFromIndex < 0 then begin
result := 0;
exit;
end;
if anotLength <= 0 then begin
result := startFromIndex + 1;
exit;
end;
dec(anotLength);
firstCharValue := long(prefix[1]);
repeat
thisOffset := &Array.findbeq(self[startFromIndex + 1], 0, startFromIndex + 1, firstCharValue);
if thisOffset = &Array.NOT_FOUND then break;
inc(startFromIndex, thisOffset);
if (anotLength <= 0) or (&Array.compfne(self[startFromIndex + 2], prefix[2], 0, anotLength) = &Array.NOT_FOUND) then begin
result := startFromIndex + 1;
exit;
end;
dec(startFromIndex);
until startFromIndex < 0;
result := 0;
end;
function AnsiStringExtended.replaceAll(oldCharacter, newCharacter: char): AnsiString;
var
chi: int;
chj: int;
thisOffset: int;
thisLength: int;
oldCharValue: long;
begin
thisLength := length;
if (thisLength <= 0) or (oldCharacter = newCharacter) then begin
result := self;
exit;
end;
oldCharValue := long(oldCharacter);
thisOffset := &Array.findfeq(self[1], 0, thisLength, oldCharValue);
if thisOffset = &Array.NOT_FOUND then begin
result := self;
exit;
end;
result := create(thisLength);
chi := 0;
chj := thisOffset;
repeat
&Array.copyRaw(self[chi + 1], result[chi + 1], chj - chi);
if chj >= thisLength then break;
result[chj + 1] := newCharacter;
chi := chj + 1;
if chi >= thisLength then break;
thisOffset := &Array.findfeq(self[chi + 1], 0, thisLength - chi, oldCharValue);
if thisOffset = &Array.NOT_FOUND then begin
chj := thisLength;
continue;
end;
chj := chi + thisOffset;
until false;
end;
function AnsiStringExtended.copy(): AnsiString;
var
thisLength: int;
begin
thisLength := length;
result := create(thisLength);
&Array.copyRaw(self[1], result[1], thisLength);
end;
function AnsiStringExtended.copy(beginIndex: int): AnsiString;
var
thisLength: int;
rsltLength: int;
begin
dec(beginIndex);
thisLength := length;
if (beginIndex < 0) or (beginIndex > thisLength) then begin
raise StringIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.string-index'));
end;
rsltLength := thisLength - beginIndex;
result := create(rsltLength);
&Array.copyRaw(self[beginIndex + 1], result[1], rsltLength);
end;
function AnsiStringExtended.copy(beginIndex, endIndex: int): AnsiString;
var
thisLength: int;
rsltLength: int;
begin
dec(endIndex);
dec(beginIndex);
thisLength := length;
if ((beginIndex or endIndex) < 0) or (beginIndex > thisLength) or (endIndex > thisLength) or (beginIndex > endIndex) then begin
raise StringIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.string-index'));
end;
rsltLength := endIndex - beginIndex;
result := create(rsltLength);
&Array.copyRaw(self[beginIndex + 1], result[1], rsltLength);
end;
function AnsiStringExtended.trim(): AnsiString;
var
chi: int;
chj: int;
endIndex: int;
thisLength: int;
rsltLength: int;
begin
thisLength := length;
if thisLength <= 0 then begin
result := '';
exit;
end;
chi := 0;
chj := thisLength - 1;
endIndex := chj;
while (chi <= chj) and (self[chi + 1] <= #$20) do begin
inc(chi);
end;
while (chi <= chj) and (self[chj + 1] <= #$20) do begin
dec(chj);
end;
if chi > chj then begin
result := '';
exit;
end;
if (chi = 0) and (chj = endIndex) then begin
result := self;
exit;
end;
rsltLength := chj - chi + 1;
result := create(rsltLength);
&Array.copyRaw(self[chi + 1], result[1], rsltLength);
end;
function AnsiStringExtended.substring(beginIndex: int): AnsiString;
var
thisLength: int;
rsltLength: int;
begin
dec(beginIndex);
thisLength := length;
if (beginIndex < 0) or (beginIndex > thisLength) then begin
raise StringIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.string-index'));
end;
if beginIndex = thisLength then begin
result := '';
exit;
end;
if beginIndex = 0 then begin
result := self;
exit;
end;
rsltLength := thisLength - beginIndex;
result := create(rsltLength);
&Array.copyRaw(self[beginIndex + 1], result[1], rsltLength);
end;
function AnsiStringExtended.substring(beginIndex, endIndex: int): AnsiString;
var
thisLength: int;
rsltLength: int;
begin
dec(endIndex);
dec(beginIndex);
thisLength := length;
if ((beginIndex or endIndex) < 0) or (beginIndex > thisLength) or (endIndex > thisLength) or (beginIndex > endIndex) then begin
raise StringIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.string-index'));
end;
if beginIndex = endIndex then begin
result := '';
exit;
end;
if beginIndex = endIndex - thisLength then begin
result := self;
exit;
end;
rsltLength := endIndex - beginIndex;
result := create(rsltLength);
&Array.copyRaw(self[beginIndex + 1], result[1], rsltLength);
end;
function AnsiStringExtended.toLowerCase(): AnsiString;
var
character: char;
thisLength: int;
idx: int;
label
break_label0;
begin
thisLength := length;
idx := 0;
begin
while idx < thisLength do begin
character := self[idx + 1];
if character <> CoChar.toLowerCase(character) then goto break_label0;
inc(idx);
end;
result := self;
exit;
end;
break_label0:
result := create(thisLength);
&Array.copyRaw(self[1], result[1], idx);
while idx < thisLength do begin
result[idx + 1] := CoChar.toLowerCase(self[idx + 1]);
inc(idx);
end;
end;
function AnsiStringExtended.toUpperCase(): AnsiString;
var
character: char;
thisLength: int;
idx: int;
label
break_label0;
begin
thisLength := length;
idx := 0;
begin
while idx < thisLength do begin
character := self[idx + 1];
if character <> CoChar.toUpperCase(character) then goto break_label0;
inc(idx);
end;
result := self;
exit;
end;
break_label0:
result := create(thisLength);
&Array.copyRaw(self[1], result[1], idx);
while idx < thisLength do begin
result[idx + 1] := CoChar.toUpperCase(self[idx + 1]);
inc(idx);
end;
end;
function AnsiStringExtended.toUTF16(): UnicodeString;
var
idx: int;
cap: int;
slen: int;
rlen: int;
code: int;
char1: int;
char2: int;
char3: int;
char4: int;
buf: short_Array1d;
begin
slen := length;
if slen <= 0 then begin
result := '';
exit;
end;
rlen := 0;
cap := int(CoLong.min(long(slen) shl 1, CoInt.MAX_VALUE));
buf := &Array.newShort1d(cap);
idx := 0;
while idx < slen do begin
char1 := int(self[idx + 1]);
inc(idx);
if (char1 >= $00) and (char1 < $80) then begin
if rlen >= cap then break;
buf[rlen] := short(char1);
inc(rlen);
end else
if (char1 >= $c0) and (char1 < $e0) then begin
if rlen >= cap then break;
char2 := 0;
if idx < slen then begin
char2 := int(self[idx + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(idx);
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 idx < slen then begin
char2 := int(self[idx + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(idx);
end;
end;
if idx < slen then begin
char3 := int(self[idx + 1]);
if (char3 and $c0) <> $80 then begin
char3 := 0;
end else begin
inc(idx);
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 >= cap 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 idx < slen then begin
char2 := int(self[idx + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(idx);
end;
end;
if idx < slen then begin
char3 := int(self[idx + 1]);
if (char3 and $c0) <> $80 then begin
char3 := 0;
end else begin
inc(idx);
end;
end;
if idx < slen then begin
char4 := int(self[idx + 1]);
if (char4 and $c0) <> $80 then begin
char4 := 0;
end else begin
inc(idx);
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 >= cap then break;
buf[rlen] := short(code);
inc(rlen);
end else
if (code >= $010000) and (code < $110000) then begin
if rlen >= cap - 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 AnsiStringExtended.toByteArray(): byte_Array1d;
var
thisLength: int;
begin
thisLength := length;
result := &Array.newByte1d(thisLength);
&Array.copyRaw(self[1], result[0], thisLength);
end;
function AnsiStringExtended.toCharArray(): char_Array1d;
var
thisLength: int;
begin
thisLength := length;
result := &Array.newChar1d(thisLength);
&Array.copyRaw(self[1], result[0], thisLength);
end;
function AnsiStringExtended.toCharCodes(): int_Array1d;
var
idx: int;
slen: int;
rlen: int;
char1: int;
char2: int;
char3: int;
char4: int;
char5: int;
char6: int;
buf: int_Array1d;
cpy: int_Array1d;
begin
slen := length;
if slen <= 0 then begin
result := &Array.newInt1d(0);
exit;
end;
rlen := 0;
buf := &Array.newInt1d(slen);
idx := 0;
while idx < slen do begin
char1 := int(self[idx + 1]);
inc(idx);
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 idx < slen then begin
char2 := int(self[idx + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(idx);
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 idx < slen then begin
char2 := int(self[idx + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(idx);
end;
end;
if idx < slen then begin
char3 := int(self[idx + 1]);
if (char3 and $c0) <> $80 then begin
char3 := 0;
end else begin
inc(idx);
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 idx < slen then begin
char2 := int(self[idx + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(idx);
end;
end;
if idx < slen then begin
char3 := int(self[idx + 1]);
if (char3 and $c0) <> $80 then begin
char3 := 0;
end else begin
inc(idx);
end;
end;
if idx < slen then begin
char4 := int(self[idx + 1]);
if (char4 and $c0) <> $80 then begin
char4 := 0;
end else begin
inc(idx);
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 idx < slen then begin
char2 := int(self[idx + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(idx);
end;
end;
if idx < slen then begin
char3 := int(self[idx + 1]);
if (char3 and $c0) <> $80 then begin
char3 := 0;
end else begin
inc(idx);
end;
end;
if idx < slen then begin
char4 := int(self[idx + 1]);
if (char4 and $c0) <> $80 then begin
char4 := 0;
end else begin
inc(idx);
end;
end;
if idx < slen then begin
char5 := int(self[idx + 1]);
if (char5 and $c0) <> $80 then begin
char5 := 0;
end else begin
inc(idx);
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 idx < slen then begin
char2 := int(self[idx + 1]);
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(idx);
end;
end;
if idx < slen then begin
char3 := int(self[idx + 1]);
if (char3 and $c0) <> $80 then begin
char3 := 0;
end else begin
inc(idx);
end;
end;
if idx < slen then begin
char4 := int(self[idx + 1]);
if (char4 and $c0) <> $80 then begin
char4 := 0;
end else begin
inc(idx);
end;
end;
if idx < slen then begin
char5 := int(self[idx + 1]);
if (char5 and $c0) <> $80 then begin
char5 := 0;
end else begin
inc(idx);
end;
end;
if idx < slen then begin
char6 := int(self[idx + 1]);
if (char6 and $c0) <> $80 then begin
char6 := 0;
end else begin
inc(idx);
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;
cpy := &Array.newInt1d(rlen);
&Array.copyPrimitives(buf, 0, cpy, 0, rlen);
result := cpy;
end;
function AnsiStringExtended.split(): AnsiString_Array1d;
var
findLimit: int;
endOffset0: int;
endOffset1: int;
beginIndex: int;
thisLength: int;
boundsLength: int;
substringLength: int;
substringInstance: AnsiString;
substringBounds: int2;
boundsData: int2_Array1d;
boundsCopy: int2_Array1d;
begin
thisLength := length;
boundsLength := 0;
boundsData := newInt2Array1d($0f);
beginIndex := 0;
while (beginIndex <= thisLength) and (beginIndex >= 0) do begin
if beginIndex >= thisLength then begin
endOffset0 := 0;
endOffset1 := 0;
end else begin
findLimit := thisLength - beginIndex;
endOffset0 := &Array.findfeq(self[beginIndex + 1], 0, findLimit, $0a);
endOffset1 := &Array.findfeq(self[beginIndex + 1], 0, findLimit, $0d);
if endOffset0 = &Array.NOT_FOUND then endOffset0 := findLimit;
if endOffset1 = &Array.NOT_FOUND then endOffset1 := findLimit;
end;
if endOffset0 >= endOffset1 then begin
endOffset0 := endOffset1;
end;
if boundsLength = system.length(boundsData) then begin
boundsCopy := newInt2Array1d((boundsLength shl 1) or 1);
&Array.copyRaw(boundsData[0], boundsCopy[0], boundsLength * sizeof(int2));
boundsData := boundsCopy;
end;
boundsData[boundsLength] := newInt2(beginIndex, endOffset0);
inc(boundsLength);
inc(beginIndex, endOffset0 + 1);
if (beginIndex < thisLength) and (self[beginIndex] = #$0d) and (self[beginIndex + 1] = #$0a) then inc(beginIndex);
end;
result := &Array.newAnsiString1d(boundsLength);
while boundsLength > 0 do begin
dec(boundsLength);
substringBounds := boundsData[boundsLength];
substringLength := substringBounds[1];
if substringLength <= 0 then begin
substringInstance := '';
end else
if substringLength >= thisLength then begin
substringInstance := self;
end else begin
substringInstance := create(substringLength);
&Array.copyRaw(self[substringBounds[0] + 1], substringInstance[1], substringLength);
end;
result[boundsLength] := substringInstance;
end;
end;
{%endregion}
{%region UnicodeStringExtended}
class function UnicodeStringExtended.create(length: int): UnicodeString;
begin
if length < 0 then length := 0;
result := '';
setLength(result, length);
end;
class function UnicodeStringExtended.create(const src: short_Array1d): UnicodeString;
var
len: int;
begin
len := system.length(src);
result := '';
setLength(result, len);
&Array.copyRaw(src[0], result[1], long(len) * sizeof(uchar));
end;
class function UnicodeStringExtended.create(const src: uchar_Array1d): UnicodeString;
var
len: int;
begin
len := system.length(src);
result := '';
setLength(result, len);
&Array.copyRaw(src[0], result[1], long(len) * sizeof(uchar));
end;
class function UnicodeStringExtended.create(const src: short_Array1d; offset, length: int): UnicodeString;
begin
&Array.checkBounds(src, offset, length);
result := '';
setLength(result, length);
&Array.copyRaw(src[offset], result[1], long(length) * sizeof(uchar));
end;
class function UnicodeStringExtended.create(const src: uchar_Array1d; offset, length: int): UnicodeString;
begin
&Array.checkBounds(src, offset, length);
result := '';
setLength(result, length);
&Array.copyRaw(src[offset], result[1], long(length) * sizeof(uchar));
end;
class function UnicodeStringExtended.create(const charCodes: int_Array1d; offset, length: int): UnicodeString;
var
idx: int;
cap: int;
len: int;
ccd: int;
buf: short_Array1d;
begin
&Array.checkBounds(charCodes, offset, length);
len := 0;
cap := int(CoLong.min(long(length) * 2, CoInt.MAX_VALUE));
buf := &Array.newShort1d(cap);
for idx := offset to offset + length - 1 do begin
ccd := charCodes[idx];
if (ccd >= $000000) and (ccd < $00d800) or (ccd >= $00e000) and (ccd < $010000) then begin
if len >= cap then break;
buf[len] := short(ccd);
inc(len);
end else
if (ccd >= $010000) and (ccd < $110000) then begin
if len >= cap - 1 then break;
dec(ccd, $010000);
buf[len] := short($d800 + (ccd shr 10));
buf[len + 1] := short($dc00 + (ccd and $03ff));
inc(len, 2);
end;
end;
result := create(buf, 0, len);
end;
class function UnicodeStringExtended.format(const form: UnicodeString; const data: array of Value): UnicodeString;
var
isReal: boolean;
isString: boolean;
isExpForm: boolean;
significandAll: boolean;
significandSign: boolean;
orderSign: boolean;
leadZeroOutput: boolean;
formChar: uchar;
formDigit: int;
beginIndex: int;
endIndex: int;
formIndex: int;
dataIndex: int;
formLength: int;
dataLimit: int absolute high(data);
significandDigits: int;
orderDigits: int;
leadZeroWidth: int;
fieldWidth: int;
formattedWidth: int;
count: int;
number: long;
formattedInstance: AnsiString;
formInstance: UnicodeString absolute form;
dataArray: array [0..0] of Value absolute data;
dataComponent: Value;
label
break_label0,
continue_label0;
begin
formLength := formInstance.length;
if formLength <= 0 then begin
result := '';
exit;
end;
result := '';
beginIndex := 1;
endIndex := formInstance.indexOf('%');
while endIndex - 1 >= 0 do begin
result := result + formInstance.substring(beginIndex, endIndex);
beginIndex := endIndex;
formIndex := beginIndex + 1;
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if formChar = '%' then begin
endIndex := formIndex + 1;
result := result + '%';
goto continue_label0;
end;
if (formChar < '0') or (formChar > '9') then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
dataIndex := int(formChar) - int('0');
repeat
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if (formChar < '0') or (formChar > '9') then break;
formDigit := int(formChar) - int('0');
if dataIndex > CoInt.MAX_VALUE div 10 then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
dataIndex := dataIndex * 10;
if dataIndex > CoInt.MAX_VALUE - formDigit then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
dataIndex := dataIndex + formDigit;
until false;
isReal := false;
isString := true;
isExpForm := false;
significandAll := false;
significandSign := false;
orderSign := true;
leadZeroOutput := false;
significandDigits := 1;
orderDigits := 0;
leadZeroWidth := 0;
if formChar = '#' then begin
isString := false;
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if formChar = '+' then begin
significandSign := true;
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
end;
if formChar = '0' then begin
leadZeroOutput := true;
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if (formChar < '0') or (formChar > '9') then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
leadZeroWidth := int(formChar) - int('0');
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if (formChar >= '0') and (formChar <= '9') then begin
leadZeroWidth := (leadZeroWidth * 10) + (int(formChar) - int('0'));
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
end;
end else begin
if formChar <> '1' then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if formChar = '.' then begin
isReal := true;
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if (formChar < '0') or (formChar > '9') then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
significandDigits := int(formChar) - int('0');
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if (formChar >= '0') and (formChar <= '9') then begin
significandDigits := (significandDigits * 10) + (int(formChar) - int('0'));
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
end;
if significandDigits < 1 then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
inc(significandDigits);
if (formChar = 'A') or (formChar = 'a') then begin
significandAll := true;
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
end;
end;
isExpForm := formChar = 'E';
if isExpForm or (formChar = 'e') then begin
isReal := true;
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if formChar <> '+' then begin
orderSign := false;
end else begin
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
end;
if (formChar < '0') or (formChar > '4') then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
orderDigits := int(formChar) - int('0');
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
end;
end;
end;
fieldWidth := 0;
if formChar = ':' then begin
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if (formChar < '0') or (formChar > '9') then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
fieldWidth := int(formChar) - int('0');
repeat
inc(formIndex);
if formIndex - 1 >= formLength then goto break_label0;
formChar := formInstance[formIndex];
if (formChar < '0') or (formChar > '9') then break;
formDigit := int(formChar) - int('0');
fieldWidth := fieldWidth * 10;
if fieldWidth > 1024 - formDigit then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
fieldWidth := fieldWidth + formDigit;
until false;
end;
if formChar <> '%' then begin
endIndex := formIndex + 1;
result := result + formInstance.substring(beginIndex, endIndex);
goto continue_label0;
end;
if (dataIndex < 0) or (dataIndex > dataLimit) then begin
raise ArrayIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.array-index'));
end;
dataComponent := dataArray[dataIndex];
if dataComponent = nil then begin
raise NullPointerException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'null-pointer'));
end;
if isString then begin
formattedInstance := dataComponent.toString();
end else
if isReal then begin
if significandDigits <= 1 then significandDigits := RealRepresenter.MAX_SIGNIFICAND_DIGITS;
formattedInstance := CoReal.toString(dataComponent.asReal(), significandDigits, orderDigits, significandAll, orderDigits > 0, isExpForm, significandSign, orderSign);
end else begin
number := dataComponent.asLong();
if leadZeroOutput then begin
formattedInstance := CoLong.toLeadZeroString(number, leadZeroWidth);
end else begin
formattedInstance := CoLong.toString(number);
end;
if significandSign and (number >= 0) then formattedInstance := '+' + formattedInstance;
end;
formattedWidth := formattedInstance.length;
if fieldWidth > formattedWidth then for count := fieldWidth - formattedWidth - 1 downto 0 do result := result + ' ';
endIndex := formIndex + 1;
result := result + formattedInstance.toUTF16();
continue_label0:
beginIndex := endIndex;
endIndex := formInstance.indexOf('%', beginIndex);
end;
break_label0:
result := result + formInstance.substring(beginIndex);
end;
function UnicodeStringExtended.getLength(): int;
begin
result := system.length(self);
end;
procedure UnicodeStringExtended.getChars(beginIndex, endIndex: int; const dst: uchar_Array1d; offset: int);
var
thisLength: int;
begin
dec(endIndex);
dec(beginIndex);
thisLength := length;
if ((beginIndex or endIndex) < 0) or (beginIndex > thisLength) or (endIndex > thisLength) or (beginIndex > endIndex) then begin
raise StringIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.string-index'));
end;
thisLength := endIndex - beginIndex;
&Array.checkBounds(dst, offset, thisLength);
&Array.copyRaw(self[beginIndex + 1], dst[offset], long(thisLength) * sizeof(uchar));
end;
function UnicodeStringExtended.equalsIgnoreCase(const anot: UnicodeString): boolean;
var
idx: int;
len: int;
begin
len := length;
if anot.length <> len then begin
result := false;
exit;
end;
for idx := len - 1 downto 0 do if CoUChar.toLowerCase(self[idx + 1]) <> CoUChar.toLowerCase(anot[idx + 1]) then begin
result := false;
exit;
end;
result := true;
end;
function UnicodeStringExtended.startsWith(const prefix: UnicodeString; position: int): boolean;
var
anotLength: int;
begin
dec(position);
anotLength := prefix.length;
if (position < 0) or (position > length - anotLength) then begin
result := false;
exit;
end;
result := (anotLength <= 0) or (&Array.compfne(self[position + 1], prefix[1], 1, anotLength) = &Array.NOT_FOUND);
end;
function UnicodeStringExtended.endsWith(const suffix: UnicodeString): boolean;
var
position: int;
anotLength: int;
begin
anotLength := suffix.length;
position := length - anotLength;
if position < 0 then begin
result := false;
exit;
end;
result := (anotLength <= 0) or (&Array.compfne(self[position + 1], suffix[1], 1, anotLength) = &Array.NOT_FOUND);
end;
function UnicodeStringExtended.indexOf(const prefix: UnicodeString; startFromIndex: int): int;
var
anotLength: int;
thisLength: int;
thisOffset: int;
firstCharValue: long;
begin
dec(startFromIndex);
anotLength := prefix.length;
thisLength := length - anotLength;
if startFromIndex < 0 then begin
startFromIndex := 0;
end;
if startFromIndex > thisLength then begin
result := 0;
exit;
end;
if anotLength <= 0 then begin
result := startFromIndex + 1;
exit;
end;
dec(anotLength);
inc(thisLength);
firstCharValue := long(prefix[1]);
repeat
thisOffset := &Array.findfeq(self[startFromIndex + 1], 1, thisLength - startFromIndex, firstCharValue);
if thisOffset = &Array.NOT_FOUND then break;
inc(startFromIndex, thisOffset);
if (anotLength <= 0) or (&Array.compfne(self[startFromIndex + 2], prefix[2], 1, anotLength) = &Array.NOT_FOUND) then begin
result := startFromIndex + 1;
exit;
end;
inc(startFromIndex);
until startFromIndex >= thisLength;
result := 0;
end;
function UnicodeStringExtended.lastIndexOf(const prefix: UnicodeString; startFromIndex: int): int;
var
anotLength: int;
thisLength: int;
thisOffset: int;
firstCharValue: long;
begin
dec(startFromIndex);
anotLength := prefix.length;
thisLength := length - anotLength;
if startFromIndex > thisLength then begin
startFromIndex := thisLength;
end;
if startFromIndex < 0 then begin
result := 0;
exit;
end;
if anotLength <= 0 then begin
result := startFromIndex + 1;
exit;
end;
dec(anotLength);
firstCharValue := long(prefix[1]);
repeat
thisOffset := &Array.findbeq(self[startFromIndex + 1], 1, startFromIndex + 1, firstCharValue);
if thisOffset = &Array.NOT_FOUND then break;
inc(startFromIndex, thisOffset);
if (anotLength <= 0) or (&Array.compfne(self[startFromIndex + 2], prefix[2], 1, anotLength) = &Array.NOT_FOUND) then begin
result := startFromIndex + 1;
exit;
end;
dec(startFromIndex);
until startFromIndex < 0;
result := 0;
end;
function UnicodeStringExtended.replaceAll(oldCharacter, newCharacter: uchar): UnicodeString;
var
chi: int;
chj: int;
thisOffset: int;
thisLength: int;
oldCharValue: long;
begin
thisLength := length;
if (thisLength <= 0) or (oldCharacter = newCharacter) then begin
result := self;
exit;
end;
oldCharValue := long(oldCharacter);
thisOffset := &Array.findfeq(self[1], 1, thisLength, oldCharValue);
if thisOffset = &Array.NOT_FOUND then begin
result := self;
exit;
end;
result := create(thisLength);
chi := 0;
chj := thisOffset;
repeat
&Array.copyRaw(self[chi + 1], result[chi + 1], long(chj - chi) * sizeof(uchar));
if chj >= thisLength then break;
result[chj + 1] := newCharacter;
chi := chj + 1;
if chi >= thisLength then break;
thisOffset := &Array.findfeq(self[chi + 1], 1, thisLength - chi, oldCharValue);
if thisOffset = &Array.NOT_FOUND then begin
chj := thisLength;
continue;
end;
chj := chi + thisOffset;
until false;
end;
function UnicodeStringExtended.copy(): UnicodeString;
var
thisLength: int;
begin
thisLength := length;
result := create(thisLength);
&Array.copyRaw(self[1], result[1], long(thisLength) * sizeof(uchar));
end;
function UnicodeStringExtended.copy(beginIndex: int): UnicodeString;
var
thisLength: int;
rsltLength: int;
begin
dec(beginIndex);
thisLength := length;
if (beginIndex < 0) or (beginIndex > thisLength) then begin
raise StringIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.string-index'));
end;
rsltLength := thisLength - beginIndex;
result := create(rsltLength);
&Array.copyRaw(self[beginIndex + 1], result[1], long(rsltLength) * sizeof(uchar));
end;
function UnicodeStringExtended.copy(beginIndex, endIndex: int): UnicodeString;
var
thisLength: int;
rsltLength: int;
begin
dec(endIndex);
dec(beginIndex);
thisLength := length;
if ((beginIndex or endIndex) < 0) or (beginIndex > thisLength) or (endIndex > thisLength) or (beginIndex > endIndex) then begin
raise StringIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.string-index'));
end;
rsltLength := endIndex - beginIndex;
result := create(rsltLength);
&Array.copyRaw(self[beginIndex + 1], result[1], long(rsltLength) * sizeof(uchar));
end;
function UnicodeStringExtended.trim(): UnicodeString;
var
chi: int;
chj: int;
endIndex: int;
thisLength: int;
rsltLength: int;
begin
thisLength := length;
if thisLength <= 0 then begin
result := '';
exit;
end;
chi := 0;
chj := thisLength - 1;
endIndex := chj;
while (chi <= chj) and (self[chi + 1] <= #$0020) do begin
inc(chi);
end;
while (chi <= chj) and (self[chj + 1] <= #$0020) do begin
dec(chj);
end;
if chi > chj then begin
result := '';
exit;
end;
if (chi = 0) and (chj = endIndex) then begin
result := self;
exit;
end;
rsltLength := chj - chi + 1;
result := create(rsltLength);
&Array.copyRaw(self[chi + 1], result[1], long(rsltLength) * sizeof(uchar));
end;
function UnicodeStringExtended.substring(beginIndex: int): UnicodeString;
var
thisLength: int;
rsltLength: int;
begin
dec(beginIndex);
thisLength := length;
if (beginIndex < 0) or (beginIndex > thisLength) then begin
raise StringIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.string-index'));
end;
if beginIndex = thisLength then begin
result := '';
exit;
end;
if beginIndex = 0 then begin
result := self;
exit;
end;
rsltLength := thisLength - beginIndex;
result := create(rsltLength);
&Array.copyRaw(self[beginIndex + 1], result[1], long(rsltLength) * sizeof(uchar));
end;
function UnicodeStringExtended.substring(beginIndex, endIndex: int): UnicodeString;
var
thisLength: int;
rsltLength: int;
begin
dec(endIndex);
dec(beginIndex);
thisLength := length;
if ((beginIndex or endIndex) < 0) or (beginIndex > thisLength) or (endIndex > thisLength) or (beginIndex > endIndex) then begin
raise StringIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.string-index'));
end;
if beginIndex = endIndex then begin
result := '';
exit;
end;
if beginIndex = endIndex - thisLength then begin
result := self;
exit;
end;
rsltLength := endIndex - beginIndex;
result := create(rsltLength);
&Array.copyRaw(self[beginIndex + 1], result[1], long(rsltLength) * sizeof(uchar));
end;
function UnicodeStringExtended.toLowerCase(): UnicodeString;
var
character: uchar;
thisLength: int;
idx: int;
label
break_label0;
begin
thisLength := length;
idx := 0;
begin
while idx < thisLength do begin
character := self[idx + 1];
if character <> CoUChar.toLowerCase(character) then goto break_label0;
inc(idx);
end;
result := self;
exit;
end;
break_label0:
result := create(thisLength);
&Array.copyRaw(self[1], result[1], long(idx) * sizeof(uchar));
while idx < thisLength do begin
result[idx + 1] := CoUChar.toLowerCase(self[idx + 1]);
inc(idx);
end;
end;
function UnicodeStringExtended.toUpperCase(): UnicodeString;
var
character: uchar;
thisLength: int;
idx: int;
label
break_label0;
begin
thisLength := length;
idx := 0;
begin
while idx < thisLength do begin
character := self[idx + 1];
if character <> CoUChar.toUpperCase(character) then goto break_label0;
inc(idx);
end;
result := self;
exit;
end;
break_label0:
result := create(thisLength);
&Array.copyRaw(self[1], result[1], long(idx) * sizeof(uchar));
while idx < thisLength do begin
result[idx + 1] := CoUChar.toUpperCase(self[idx + 1]);
inc(idx);
end;
end;
function UnicodeStringExtended.toUTF8(): AnsiString;
var
idx: int;
cap: int;
slen: int;
rlen: int;
code: int;
char1: int;
char2: int;
buf: byte_Array1d;
begin
slen := length;
if slen <= 0 then begin
result := '';
exit;
end;
rlen := 0;
cap := int(CoLong.min(long(slen) * 4, CoInt.MAX_VALUE));
buf := &Array.newByte1d(cap);
idx := 0;
while idx < slen do begin
char1 := int(self[idx + 1]);
inc(idx);
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 idx < slen then begin
char2 := int(self[idx + 1]);
if (char2 < $dc00) or (char2 >= $e000) then begin
char2 := 0;
end else begin
inc(idx);
end;
end;
code := ((char1 and $03ff) shl 10) + (char2 and $03ff) + $010000;
end;
if (code >= $000001) and (code < $000080) then begin
if rlen >= cap then break;
buf[rlen] := byte(code);
inc(rlen);
end else
if (code >= $000000) and (code < $000800) then begin
if rlen >= cap - 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 >= cap - 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 >= cap - 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 UnicodeStringExtended.toShortArray(): short_Array1d;
var
thisLength: int;
begin
thisLength := length;
result := &Array.newShort1d(thisLength);
&Array.copyRaw(self[1], result[0], long(thisLength) * sizeof(uchar));
end;
function UnicodeStringExtended.toUCharArray(): uchar_Array1d;
var
thisLength: int;
begin
thisLength := length;
result := &Array.newUChar1d(thisLength);
&Array.copyRaw(self[1], result[0], long(thisLength) * sizeof(uchar));
end;
function UnicodeStringExtended.toCharCodes(): int_Array1d;
var
idx: int;
slen: int;
rlen: int;
code: int;
char1: int;
char2: int;
buf: int_Array1d;
cpy: int_Array1d;
begin
slen := length;
if slen <= 0 then begin
result := &Array.newInt1d(0);
exit;
end;
rlen := 0;
buf := &Array.newInt1d(slen);
idx := 0;
while idx < slen do begin
char1 := int(self[idx + 1]);
inc(idx);
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 idx < slen then begin
char2 := int(self[idx + 1]);
if (char2 < $dc00) or (char2 >= $e000) then begin
char2 := 0;
end else begin
inc(idx);
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;
cpy := &Array.newInt1d(rlen);
&Array.copyPrimitives(buf, 0, cpy, 0, rlen);
result := cpy;
end;
function UnicodeStringExtended.split(): UnicodeString_Array1d;
var
findLimit: int;
endOffset0: int;
endOffset1: int;
beginIndex: int;
thisLength: int;
boundsLength: int;
substringLength: int;
substringInstance: UnicodeString;
substringBounds: int2;
boundsData: int2_Array1d;
boundsCopy: int2_Array1d;
begin
thisLength := length;
boundsLength := 0;
boundsData := newInt2Array1d($0f);
beginIndex := 0;
while (beginIndex <= thisLength) and (beginIndex >= 0) do begin
if beginIndex >= thisLength then begin
endOffset0 := 0;
endOffset1 := 0;
end else begin
findLimit := thisLength - beginIndex;
endOffset0 := &Array.findfeq(self[beginIndex + 1], 1, findLimit, $000a);
endOffset1 := &Array.findfeq(self[beginIndex + 1], 1, findLimit, $000d);
if endOffset0 = &Array.NOT_FOUND then endOffset0 := findLimit;
if endOffset1 = &Array.NOT_FOUND then endOffset1 := findLimit;
end;
if endOffset0 >= endOffset1 then begin
endOffset0 := endOffset1;
end;
if boundsLength = system.length(boundsData) then begin
boundsCopy := newInt2Array1d((boundsLength shl 1) or 1);
&Array.copyRaw(boundsData[0], boundsCopy[0], boundsLength * sizeof(int2));
boundsData := boundsCopy;
end;
boundsData[boundsLength] := newInt2(beginIndex, endOffset0);
inc(boundsLength);
inc(beginIndex, endOffset0 + 1);
if (beginIndex < thisLength) and (self[beginIndex] = #$000d) and (self[beginIndex + 1] = #$000a) then inc(beginIndex);
end;
result := &Array.newUnicodeString1d(boundsLength);
while boundsLength > 0 do begin
dec(boundsLength);
substringBounds := boundsData[boundsLength];
substringLength := substringBounds[1];
if substringLength <= 0 then begin
substringInstance := '';
end else
if substringLength >= thisLength then begin
substringInstance := self;
end else begin
substringInstance := create(substringLength);
&Array.copyRaw(self[substringBounds[0] + 1], substringInstance[1], long(substringLength) * sizeof(uchar));
end;
result[boundsLength] := substringInstance;
end;
end;
{%endregion}
{%region real operators (Windows only)}
{$IFDEF WINDOWS}
operator :=(value: long): real; assembler; nostackframe;
asm
dd $000008c8
mov qword [rbp-$08], rdx
fild qword [rbp-$08]
fstp tbyte [rcx-$00]
leave
end;
operator :=(value: double): real; assembler; nostackframe;
asm
dd $000008c8
movsd qword [rbp-$08], xmm1
fld qword [rbp-$08]
fstp tbyte [rcx-$00]
leave
end;
operator +(const value: real): real; assembler; nostackframe;
asm
fld tbyte [rdx+$00]
fstp tbyte [rcx+$00]
end;
operator -(const value: real): real; assembler; nostackframe;
asm
fld tbyte [rdx+$00]
fchs
fstp tbyte [rcx+$00]
end;
operator +(const value1, value2: real): real; assembler; nostackframe;
asm
fld tbyte [rdx+$00]
fld tbyte [r8+$00]
faddp st(1), st
fstp tbyte [rcx+$00]
end;
operator -(const value1, value2: real): real; assembler; nostackframe;
asm
fld tbyte [rdx+$00]
fld tbyte [r8+$00]
fsubp st(1), st
fstp tbyte [rcx+$00]
end;
operator *(const value1, value2: real): real; assembler; nostackframe;
asm
fld tbyte [rdx+$00]
fld tbyte [r8+$00]
fmulp st(1), st
fstp tbyte [rcx+$00]
end;
operator /(const value1, value2: real): real; assembler; nostackframe;
asm
fld tbyte [rdx+$00]
fld tbyte [r8+$00]
fdivp st(1), st
fstp tbyte [rcx+$00]
end;
operator =(const value1, value2: real): boolean; assembler; nostackframe;
asm
fld tbyte [rdx+$00]
fld tbyte [rcx+$00]
fcomip st, st(1)
ffree st
fincstp
jnp @00
mov al, $ff
or eax, eax
stc
@00: sete al
movzx eax, al
end;
operator >(const value1, value2: real): boolean; assembler; nostackframe;
asm
fld tbyte [rdx+$00]
fld tbyte [rcx+$00]
fcomip st, st(1)
ffree st
fincstp
jnp @00
mov al, $ff
or eax, eax
stc
@00: seta al
movzx eax, al
end;
operator <(const value1, value2: real): boolean; assembler; nostackframe;
asm
fld tbyte [rdx+$00]
fld tbyte [rcx+$00]
fcomip st, st(1)
ffree st
fincstp
jnp @00
mov al, $ff
or eax, eax
@00: setb al
movzx eax, al
end;
operator <>(const value1, value2: real): boolean; assembler; nostackframe;
asm
fld tbyte [rdx+$00]
fld tbyte [rcx+$00]
fcomip st, st(1)
ffree st
fincstp
jnp @00
mov al, $ff
or eax, eax
stc
@00: setne al
movzx eax, al
end;
operator <=(const value1, value2: real): boolean; assembler; nostackframe;
asm
fld tbyte [rdx+$00]
fld tbyte [rcx+$00]
fcomip st, st(1)
ffree st
fincstp
jnp @00
mov al, $ff
or eax, eax
@00: setbe al
movzx eax, al
end;
operator >=(const value1, value2: real): boolean; assembler; nostackframe;
asm
fld tbyte [rdx+$00]
fld tbyte [rcx+$00]
fcomip st, st(1)
ffree st
fincstp
jnp @00
mov al, $ff
or eax, eax
stc
@00: setae al
movzx eax, al
end;
{$ENDIF}
{%endregion}
{%region TypeInformation}
constructor TypeInformation.create(info: PTypeInfo);
begin
inherited create();
fldInfo := info;
fldData := getTypeData(info);
end;
function TypeInformation.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is TypeInformation) and (TypeInformation(anot).fldInfo = fldInfo);
end;
function TypeInformation.getHashCode(): long;
begin
result := long((@fldInfo)^);
end;
function TypeInformation.toString(): AnsiString;
begin
result := AnsiString('type ') + fldInfo^.name;
end;
function TypeInformation.isInstance(ref: TObject): boolean;
begin
result := false;
end;
function TypeInformation.isInstance(ref: ISimple): boolean;
begin
result := false;
end;
function TypeInformation.isInstance(ref: IUnknown): boolean;
begin
result := false;
end;
function TypeInformation.isAssignableFrom(cls: &Class): boolean;
var
anot: TObject;
begin
if (cls = nil) or (cls.queryInterface(IObjectInstance, anot) <> system.S_OK) or not(anot is TypeInformation) then begin
result := false;
exit;
end;
result := TypeInformation(anot).fldInfo = fldInfo;
end;
function TypeInformation.getTypeKind(): int;
begin
result := int(fldInfo^.kind);
end;
function TypeInformation.getUnitName(): AnsiString;
begin
result := getOriginalUnit();
end;
function TypeInformation.getSimpleName(): AnsiString;
begin
result := fldInfo^.name;
end;
function TypeInformation.getOriginalUnit(): AnsiString;
begin
result := '';
end;
function TypeInformation.getOriginalName(): AnsiString;
begin
result := fldInfo^.name;
end;
function TypeInformation.getCanonicalName(): AnsiString;
var
uname: AnsiString;
tname: AnsiString;
begin
uname := getUnitName();
tname := getSimpleName();
if uname.length <= 0 then begin
result := tname;
exit;
end;
result := uname + '.' + tname;
end;
function TypeInformation.getProperties(): Property_Array1d;
begin
result := nil;
end;
function TypeInformation.getInterfaces(): Class_Array1d;
begin
result := nil;
end;
function TypeInformation.getProperty(const name: AnsiString): &Property;
begin
result := nil;
end;
function TypeInformation.getSuperclass(): &Class;
begin
result := nil;
end;
function TypeInformation.getReference(): &Class;
begin
result := nil;
end;
function TypeInformation.getComponentType(): &Class;
begin
result := nil;
end;
{$WARN 5033 OFF} { позволить функции, состоящие только из одной управляющей конструкции raise }
function TypeInformation.createInstance(): DynamicObject;
begin
raise InstantiationException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'instantiation.object'), [ CoAnsiString.create(getCanonicalName()) ]));
end;
{$WARN 5033 ON}
{%endregion}
{%region PrimitiveTypeInformation}
constructor PrimitiveTypeInformation.create(info: PTypeInfo; kind: int; const name: AnsiString);
begin
inherited create(info);
fldKind := kind;
fldName := name;
end;
function PrimitiveTypeInformation.equals(anot: TObject): boolean;
begin
result := (anot = self) or (anot is PrimitiveTypeInformation) and (PrimitiveTypeInformation(anot).fldKind = fldKind);
end;
function PrimitiveTypeInformation.getHashCode(): long;
begin
result := fldKind;
end;
function PrimitiveTypeInformation.toString(): AnsiString;
begin
result := AnsiString('type ') + fldName;
end;
function PrimitiveTypeInformation.isPointer(): boolean;
var
kind: int;
begin
kind := fldKind;
result := (kind >= Lang.TYPE_ANSISTRING) and (kind <= Lang.TYPE_WIDESTRING) or (kind >= Lang.TYPE_UNICODESTRING) and (kind <= Lang.TYPE_POINTER);
end;
function PrimitiveTypeInformation.isPrimitive(): boolean;
var
kind: int;
begin
kind := fldKind;
result := (kind < Lang.TYPE_SHORTSTRING) or (kind > Lang.TYPE_WIDESTRING) and (kind < Lang.TYPE_UNICODESTRING) or (kind > Lang.TYPE_POINTER);
end;
function PrimitiveTypeInformation.isAssignableFrom(cls: &Class): boolean;
var
anot: TObject;
begin
if (cls = nil) or (cls.queryInterface(IObjectInstance, anot) <> system.S_OK) or not(anot is PrimitiveTypeInformation) then begin
result := false;
exit;
end;
result := PrimitiveTypeInformation(anot).fldKind = fldKind;
end;
function PrimitiveTypeInformation.getTypeKind(): int;
begin
result := fldKind;
end;
function PrimitiveTypeInformation.getSimpleName(): AnsiString;
begin
result := fldName;
end;
{%endregion}
{%region PointerTypeInformation}
function PointerTypeInformation.isPointer(): boolean;
begin
result := true;
end;
function PointerTypeInformation.isPrimitive(): boolean;
begin
result := false;
end;
{%endregion}
{%region ClassTypeInformation}
class function ClassTypeInformation.typeInfoToLangType(tinfo: PTypeInfo): int;
var
tdata: PTypeData;
tkind: TTypeKind;
label
break_label0;
begin
{$IFDEF WINDOWS}
if tinfo = typeInfo(real) then begin
result := Lang.TYPE_REAL;
exit;
end;
{$ENDIF}
tdata := getTypeData(tinfo);
tkind := tinfo^.kind;
begin
case tkind of
tkUChar, tkWChar: begin
result := Lang.TYPE_UCHAR;
exit;
end;
tkEnumeration: begin
result := Lang.TYPE_INT;
exit;
end;
tkInteger: begin
case tdata^.ordType of
otSByte:
result := Lang.TYPE_BYTE;
otSWord:
result := Lang.TYPE_SHORT;
otUByte:
result := Lang.TYPE_UBYTE;
otUWord:
result := Lang.TYPE_USHORT;
otULong:
result := Lang.TYPE_UINT;
else
goto break_label0;
end;
exit;
end;
tkFloat: begin
case tdata^.floatType of
ftDouble:
result := Lang.TYPE_DOUBLE;
{$IFNDEF WINDOWS}
ftExtended:
result := Lang.TYPE_REAL;
{$ENDIF}
ftComp:
result := Lang.TYPE_COMP;
ftCurr:
result := Lang.TYPE_CURRENCY;
else
goto break_label0;
end;
exit;
end;
end;
end;
break_label0:
result := int(tkind);
end;
class function ClassTypeInformation.propInfoToProperty(pinfo: PPropInfo): &Property;
var
procs: int;
begin
if pinfo = nil then begin
result := nil;
exit;
end;
procs := pinfo^.propProcs;
result := PropertyInformation.create(
(procs and (3 shl 0)) <> (ptConst shl 0),
(procs and (3 shl 2)) <> (ptConst shl 2),
(procs and (3 shl 4)) <> (ptConst shl 4),
Lang.classFor(pinfo^.propType),
pinfo^.name
);
end;
constructor ClassTypeInformation.create(info: TClass);
begin
inherited create(info.classInfo());
fldType := info;
end;
constructor ClassTypeInformation.create(info: PTypeInfo);
begin
inherited create(info);
fldType := fldData^.classType;
end;
function ClassTypeInformation.toString(): AnsiString;
var
info: TClass;
begin
info := fldType;
result := AnsiString('class ') + info.unitName().toLowerCase() + '.' + info.className();
end;
function ClassTypeInformation.isInstance(ref: TObject): boolean;
var
info: TClass;
anot: TClass;
begin
if ref = nil then begin
result := false;
exit;
end;
info := fldType;
anot := ref.classType();
result := (anot = info) or anot.inheritsFrom(info);
end;
function ClassTypeInformation.isInstance(ref: ISimple): boolean;
var
obj: TObject;
info: TClass;
anot: TClass;
begin
if (ref = nil) or (ref.queryInterface(IObjectInstance, obj) <> system.S_OK) then begin
result := false;
exit;
end;
info := fldType;
anot := obj.classType();
result := (anot = info) or anot.inheritsFrom(info);
end;
function ClassTypeInformation.isInstance(ref: IUnknown): boolean;
var
obj: TObject;
info: TClass;
anot: TClass;
begin
if (ref = nil) or (ref.queryInterface(IObjectInstance, obj) <> system.S_OK) then begin
result := false;
exit;
end;
info := fldType;
anot := obj.classType();
result := (anot = info) or anot.inheritsFrom(info);
end;
function ClassTypeInformation.isAssignableFrom(cls: &Class): boolean;
var
obj: TObject;
info: TClass;
anot: TClass;
begin
if (cls = nil) or (cls.queryInterface(IObjectInstance, obj) <> system.S_OK) or not(obj is ClassTypeInformation) then begin
result := false;
exit;
end;
info := fldType;
anot := ClassTypeInformation(obj).fldType;
result := (anot = info) or anot.inheritsFrom(info);
end;
function ClassTypeInformation.getTypeKind(): int;
begin
result := Lang.TYPE_CLASS;
end;
function ClassTypeInformation.getOriginalUnit(): AnsiString;
begin
result := AnsiString(fldData^.unitName).toLowerCase();
end;
function ClassTypeInformation.getProperties(): Property_Array1d;
var
idx: int;
len: int;
pinfo: PPropInfo;
tinfo: PTypeInfo;
tdata: PTypeData;
begin
tinfo := PTypeInfo(fldType.classInfo());
if tinfo = nil then begin
result := nil;
exit;
end;
tdata := getTypeData(tinfo);
pinfo := PPropInfo(Pointer(@(tdata^.unitName[1])) + int(tdata^.unitName[0]));
len := system.PUInt16(pinfo)^;
pinfo := Pointer(pinfo) + 2;
result := Property_Array1d(&Array.newIUnknown1d(len));
for idx := 0 to len - 1 do begin
result[idx] := propInfoToProperty(pinfo);
pinfo := PPropInfo(Pointer(@(pinfo^.name[1])) + int(pinfo^.name[0]));
end;
end;
function ClassTypeInformation.getInterfaces(): Class_Array1d;
var
idx: int;
len: int;
guid: system.TGuid;
pgid: system.PGuid;
psid: PShortString;
table: PInterfaceTable;
begin
table := fldType.getInterfaceTable();
if table = nil then begin
result := nil;
exit;
end;
with table^ do begin
len := int(entryCount);
result := Class_Array1d(&Array.newIUnknown1d(len));
for idx := len - 1 downto 0 do begin
with entries[idx] do begin
pgid := iid;
psid := iidstr;
end;
if pgid <> nil then begin
result[idx] := Lang.classFor(pgid^);
continue;
end;
if (psid <> nil) and guidTryParse(psid^, guid) then begin
result[idx] := Lang.classFor(guid);
continue;
end;
result[idx] := InterfaceTypeInformation.create(PTypeInfo(typeInfo(IUnknown)));
end;
end;
end;
function ClassTypeInformation.getProperty(const name: AnsiString): &Property;
begin
result := propInfoToProperty(fldType.getPropertyInfo(name));
end;
function ClassTypeInformation.getSuperclass(): &Class;
var
super: TClass;
begin
super := fldType.classParent();
if super = nil then begin
result := nil;
exit;
end;
result := ClassTypeInformation.create(super);
end;
function ClassTypeInformation.createInstance(): DynamicObject;
type
DynamicClass = class of DynamicObject;
var
info: TClass;
begin
info := fldType;
if (info <> DynamicObject) and not info.inheritsFrom(DynamicObject) then begin
raise InstantiationException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'instantiation.object'), [
CoAnsiString.create(getCanonicalName())
]));
end;
result := DynamicClass(info).create();
end;
{%endregion}
{%region ClassRefTypeInformation}
constructor ClassRefTypeInformation.create(info: PTypeInfo);
begin
inherited create(info);
fldType := getTypeData(fldData^.instanceTypeRef^)^.classType;
end;
function ClassRefTypeInformation.toString(): AnsiString;
var
info: TClass;
begin
info := fldType;
result := AnsiString('class of ') + info.unitName().toLowerCase() + '.' + info.className();
end;
function ClassRefTypeInformation.isAssignableFrom(cls: &Class): boolean;
var
obj: TObject;
info: TClass;
anot: TClass;
begin
if (cls = nil) or (cls.queryInterface(IObjectInstance, obj) <> system.S_OK) or not(obj is ClassRefTypeInformation) then begin
result := false;
exit;
end;
info := fldType;
anot := ClassRefTypeInformation(obj).fldType;
result := (anot = info) or anot.inheritsFrom(info);
end;
function ClassRefTypeInformation.getTypeKind(): int;
begin
result := Lang.TYPE_CLASSREF;
end;
function ClassRefTypeInformation.getReference(): &Class;
begin
result := Lang.classFor(fldType);
end;
{%endregion}
{%region InterfaceTypeInformation}
function InterfaceTypeInformation.toString(): AnsiString;
begin
result := AnsiString('interface ') + AnsiString(fldData^.intfUnit).toLowerCase() + '.' + fldInfo^.name;
end;
function InterfaceTypeInformation.isInstance(ref: TObject): boolean;
begin
result := (ref <> nil) and (ref.getInterfaceEntry(fldData^.guid) <> nil);
end;
function InterfaceTypeInformation.isInstance(ref: ISimple): boolean;
var
obj: TObject;
begin
if ref = nil then begin
result := false;
exit;
end;
if fldInfo^.kind = tkInterface then begin
result := (ref.queryInterface(IObjectInstance, obj) = system.S_OK) and (obj.getInterfaceEntry(fldData^.guid) <> nil);
exit;
end;
result := ref.queryInterface(fldData^.guid, obj) = system.S_OK;
end;
function InterfaceTypeInformation.isInstance(ref: IUnknown): boolean;
var
intfRC: IUnknown;
intfRaw: ISimple;
begin
if ref = nil then begin
result := false;
exit;
end;
if fldInfo^.kind = tkInterface then begin
result := ref.queryInterface(fldData^.guid, intfRC) = system.S_OK;
exit;
end;
result := ref.queryInterface(fldData^.guid, intfRaw) = system.S_OK;
end;
function InterfaceTypeInformation.isAssignableFrom(cls: &Class): boolean;
var
obj: TObject;
info: PTypeInfo;
anot: PTypeInfo;
iptr: PPTypeInfo;
begin
if (cls = nil) or (cls.queryInterface(IObjectInstance, obj) <> system.S_OK) or not(obj is InterfaceTypeInformation) then begin
result := false;
exit;
end;
info := fldInfo;
anot := InterfaceTypeInformation(obj).fldInfo;
repeat
if info = anot then begin
result := true;
exit;
end;
iptr := getTypeData(anot)^.intfParentRef;
if iptr = nil then break;
anot := iptr^;
until false;
result := false;
end;
function InterfaceTypeInformation.getOriginalUnit(): AnsiString;
begin
result := AnsiString(fldData^.intfUnit).toLowerCase();
end;
function InterfaceTypeInformation.getInterfaces(): Class_Array1d;
var
iptr: PPTypeInfo;
begin
iptr := fldData^.intfParentRef;
if iptr = nil then begin
result := nil;
exit;
end;
result := [ InterfaceTypeInformation.create(iptr^) as &Class ];
end;
{%endregion}
{%region DynamicArrayTypeInformation}
constructor DynamicArrayTypeInformation.create(info: PTypeInfo);
var
component: PPTypeInfo;
begin
inherited create(info);
component := fldData^.elTypeRef;
if component = nil then component := fldData^.elType2Ref;
fldComponent := component^;
end;
function DynamicArrayTypeInformation.toString(): AnsiString;
begin
result := AnsiString('array ') + Lang.classFor(fldComponent).getCanonicalName() + '[]';
end;
function DynamicArrayTypeInformation.isAssignableFrom(cls: &Class): boolean;
var
obj: TObject;
info: PTypeInfo;
anot: PTypeInfo;
begin
if (cls = nil) or (cls.queryInterface(IObjectInstance, obj) <> system.S_OK) or not(obj is DynamicArrayTypeInformation) then begin
result := false;
exit;
end;
info := fldComponent;
anot := DynamicArrayTypeInformation(obj).fldComponent;
result := (info = anot) or Lang.classFor(info).isAssignableFrom(Lang.classFor(anot));
end;
function DynamicArrayTypeInformation.getTypeKind(): int;
begin
result := Lang.TYPE_ARRAY_DYNAMIC;
end;
function DynamicArrayTypeInformation.getUnitName(): AnsiString;
begin
result := Lang.classFor(fldComponent).getUnitName();
end;
function DynamicArrayTypeInformation.getSimpleName(): AnsiString;
begin
result := Lang.classFor(fldComponent).getSimpleName() + '[]';
end;
function DynamicArrayTypeInformation.getOriginalUnit(): AnsiString;
begin
result := AnsiString(fldData^.dynUnitName).toLowerCase();
end;
function DynamicArrayTypeInformation.getComponentType(): &Class;
begin
result := Lang.classFor(fldComponent);
end;
{%endregion}
{%region FunctionTypeInformation}
function FunctionTypeInformation.isAssignableFrom(cls: &Class): boolean;
type
PProcedureSignature = ^TProcedureSignature;
var
idx: int;
len: int;
obj: TObject;
info: PProcedureSignature;
anot: PProcedureSignature;
iarg: PProcedureParam;
aarg: PProcedureParam;
begin
if (cls = nil) or (cls.queryInterface(IObjectInstance, obj) <> system.S_OK) or not(obj is FunctionTypeInformation) then begin
result := false;
exit;
end;
info := @(fldData^.procSig);
anot := @(FunctionTypeInformation(obj).fldData^.procSig);
if info <> anot then begin
len := info^.paramCount;
if (info^.cc <> anot^.cc) or (len <> anot^.paramCount) or (info^.resultType <> anot^.resultType) then begin
result := false;
exit;
end;
for idx := 0 to len - 1 do begin
iarg := info^.getParam(idx);
aarg := anot^.getParam(idx);
if ((byte((@(iarg^.paramFlags))^) and $7f) <> (byte((@(aarg^.paramFlags))^) and $7f)) or (iarg^.paramType <> aarg^.paramType) then begin
result := false;
exit;
end;
end;
end;
result := true;
end;
function FunctionTypeInformation.getTypeKind(): int;
begin
result := Lang.TYPE_FUNCTION;
end;
{%endregion}
{%region StructuredTypeInformation}
function StructuredTypeInformation.isPointer(): boolean;
begin
result := false;
end;
function StructuredTypeInformation.isPrimitive(): boolean;
begin
result := false;
end;
{%endregion}
{%region PropertyInformation}
constructor PropertyInformation.create(readable, writeable, storeable: boolean; &type: &Class; const name: AnsiString);
var
flags: int;
begin
inherited create();
flags := 0;
if readable then flags := flags or 1;
if writeable then flags := flags or 2;
if storeable then flags := flags or 4;
fldFlags := flags;
fldName := name;
fldType := &type;
end;
function PropertyInformation.isReadable(): boolean;
begin
result := (fldFlags and 1) <> 0;
end;
function PropertyInformation.isWriteable(): boolean;
begin
result := (fldFlags and 2) <> 0;
end;
function PropertyInformation.isStoreable(): boolean;
begin
result := (fldFlags and 4) <> 0;
end;
function PropertyInformation.getName(): AnsiString;
begin
result := fldName;
end;
function PropertyInformation.getType(): &Class;
begin
result := fldType;
end;
{%endregion}
{%region ThreadCollection}
constructor ThreadCollection.create(const threads: Thread_Array1d);
begin
inherited create();
fldThreads := threads;
end;
destructor ThreadCollection.destroy;
var
index: int;
threadsData: Thread_Array1d;
threadRef: Thread;
begin
threadsData := fldThreads;
for index := system.length(threadsData) - 1 downto 0 do begin
threadRef := threadsData[index];
if threadRef.isAlive() then begin
threadDecrementEnum(threadRef);
continue;
end;
threadRemove(threadRef, true);
end;
threadClean();
inherited destroy;
end;
procedure ThreadCollection.copyInto(const dstArray; dstOffset: int);
var
threadsData: Thread_Array1d;
begin
threadsData := fldThreads;
&Array.copyObjects(threadsData, 0, dstArray, dstOffset, system.length(threadsData));
end;
function ThreadCollection.getLength(): int;
begin
result := system.length(fldThreads);
end;
function ThreadCollection.componentAt(index: int): Thread;
var
threadsData: Thread_Array1d;
begin
threadsData := fldThreads;
if (index < 0) or (index >= system.length(threadsData)) then begin
raise ArrayIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.array-index'));
end;
result := threadsData[index];
end;
function ThreadCollection.toArray(): Thread_Array1d;
var
length: int;
threadsData: Thread_Array1d;
threadsCopy: Thread_Array1d;
begin
threadsData := fldThreads;
length := system.length(threadsData);
threadsCopy := Thread_Array1d(&Array.newTObject1d(length));
&Array.copyObjects(threadsData, 0, threadsCopy, 0, length);
result := threadsCopy;
end;
{%endregion}
{%region InterfaceEntry}
constructor InterfaceEntry.create(const guid: system.TGuid; info: PTypeInfo; next: InterfaceEntry);
begin
inherited create();
self.guid := guid;
self.info := info;
self.next := next;
end;
{%endregion}
{%region ThreadEntry}
constructor ThreadEntry.create(const threadId1, threadId2: long; threadRef: Thread; next: ThreadEntry);
begin
inherited create();
self.threadId1 := threadId1;
self.threadId2 := threadId2;
self.event := eventCreate(false, false, 'Event.' + CoLong.toHexString(threadId1) + '.' + CoInt.toHexString(interlockedIncrementInt(@threadCounter)));
self.next := next;
self.threadRef := threadRef;
self.threadOld := nil;
end;
destructor ThreadEntry.destroy;
begin
eventDestroy(event);
threadOld.freeIfNecessary();
threadRef.freeIfNecessary();
inherited destroy;
end;
{%endregion}
{%region} initialization
exceptionInitialize();
default8087CW := $037f;
defaultMXCSR := $1f80;
with fpusseDefaultContext do begin
fcw := $037f;
mxcsr := $1f80;
end;
{$IFNDEF LIBRARY}
fxcontextLoadFrom(@fpusseDefaultContext);
{$ENDIF}
primitives := [
nil,
PrimitiveTypeInformation.create(typeInfo(int), Lang.TYPE_INT, 'int') as &Class,
PrimitiveTypeInformation.create(typeInfo(char), Lang.TYPE_CHAR, 'char') as &Class,
nil,
PrimitiveTypeInformation.create(typeInfo(float), Lang.TYPE_FLOAT, 'float') as &Class,
nil,
nil,
PrimitiveTypeInformation.create(typeInfo(ShortString), Lang.TYPE_SHORTSTRING, 'ShortString') as &Class,
nil,
PrimitiveTypeInformation.create(typeInfo(AnsiString), Lang.TYPE_ANSISTRING, 'AnsiString') as &Class,
PrimitiveTypeInformation.create(typeInfo(WideString), Lang.TYPE_WIDESTRING, 'WideString') as &Class,
nil,
nil,
nil,
nil,
nil,
nil,
PrimitiveTypeInformation.create(typeInfo(uchar), Lang.TYPE_UCHAR, 'uchar') as &Class,
PrimitiveTypeInformation.create(typeInfo(boolean), Lang.TYPE_BOOLEAN, 'boolean') as &Class,
PrimitiveTypeInformation.create(typeInfo(long), Lang.TYPE_LONG, 'long') as &Class,
PrimitiveTypeInformation.create(typeInfo(system.UInt64), Lang.TYPE_ULONG, 'ulong') as &Class,
nil,
nil,
nil,
PrimitiveTypeInformation.create(typeInfo(UnicodeString), Lang.TYPE_UNICODESTRING, 'UnicodeString') as &Class,
nil,
nil,
nil,
nil,
PrimitiveTypeInformation.create(typeInfo(Pointer), Lang.TYPE_POINTER, 'Pointer') as &Class,
PrimitiveTypeInformation.create(typeInfo(byte), Lang.TYPE_BYTE, 'byte') as &Class,
PrimitiveTypeInformation.create(typeInfo(system.UInt8), Lang.TYPE_UBYTE, 'ubyte') as &Class,
PrimitiveTypeInformation.create(typeInfo(short), Lang.TYPE_SHORT, 'short') as &Class,
PrimitiveTypeInformation.create(typeInfo(system.UInt16), Lang.TYPE_USHORT, 'ushort') as &Class,
nil,
PrimitiveTypeInformation.create(typeInfo(system.UInt32), Lang.TYPE_UINT, 'uint') as &Class,
nil,
nil,
nil,
PrimitiveTypeInformation.create(typeInfo(double), Lang.TYPE_DOUBLE, 'double') as &Class,
PrimitiveTypeInformation.create(typeInfo(real), Lang.TYPE_REAL, 'real') as &Class,
PrimitiveTypeInformation.create(typeInfo(system.Comp), Lang.TYPE_COMP, 'comp') as &Class,
PrimitiveTypeInformation.create(typeInfo(system.Currency), Lang.TYPE_CURRENCY, 'currency') as &Class
];
representReal := RealRepresenter.create(RealRepresenter.REAL_SIGNIFICAND_DIGITS, RealRepresenter.REAL_ORDER_DIGITS);
representFloat := RealRepresenter.create(RealRepresenter.FLOAT_SIGNIFICAND_DIGITS, RealRepresenter.FLOAT_ORDER_DIGITS);
representDouble := RealRepresenter.create(RealRepresenter.DOUBLE_SIGNIFICAND_DIGITS, RealRepresenter.DOUBLE_ORDER_DIGITS);
interfaceInitialize();
threadInitialize();
{$IFNDEF LIBRARY}
threadAdd(Thread.create(threadGetCurrentId(), {$IFDEF WINDOWS}-2{$ELSE}threadGetCurrentId2(){$ENDIF}, false));
{$ENDIF}
resourcestringOverrides := AResource.readResourceAsAnsiString('resourcestring').split();
if system.length(resourcestringOverrides) > 0 then try
objpas.setResourceStrings(TResourceIterator(@resourcestringOverride), nil);
finally
resourcestringOverrides := nil;
end;
Lang.registerInterfaces([
typeInfo(IUnknown),
typeInfo(IDispatch),
typeInfo(IInvokable),
typeInfo(ISimple),
typeInfo(RawInterface),
typeInfo(RefCountInterface),
typeInfo(&Property),
typeInfo(&Class),
typeInfo(Runnable),
typeInfo(Value),
typeInfo(Serializable)
]);
{%endregion}
{%region} finalization
threadFinalize();
interfaceFinalize();
representDouble.free();
representFloat.free();
representReal.free();
primitives := nil;
exceptionFinalize();
{%endregion}
end.