Unit CastleUtils

Description

Various basic utilities.

  • Lists, using generics derived from standard Generics.Collections. Lists of primitives, like TIntegerList and TFloatList, and a helpful class to define a list of structures TStructList.

  • Basic operations on numbers (compare, randomize).

  • Some OS-dependent things.

  • Some compatibility things, to plug the differences between various versions of FPC and Delphi.

  • Filenames operations. They do not touch actual files (operations on files are in CastleFilesUtils.)

This unit is a bag for simple and useful things. Let's not overload this unit with too many trivial utilities. When adding new utilities, first consider more specific units, like CastleFilesUtils, CastleStringUtils and CastleClassUtils. This unit does not depend on the standard Classes unit (use CastleClassUtils for utilities on top of Classes).

Initialization of this unit does some generally-useful things:

  • Sets DecimalSeparator to '.' (dot).

    Bacause Delphi and FPC define DecimalSeparator based on local settings (e.g. user's country). This makes standard functions like StrToFloat and FloatToStr less useful for various parsing and printing done by Castle Game Engine, where we often must read and write the "dot". E.g. FloatToStr(0.9) may output '0,9' (with a comma) in a some countries. Writing it to a file would be usually a mistake – as the file may be transferred to another user with a different locale, where StrToFloat could not deal with a comma being used for the separator.

    Initial (localized) value of DecimalSeparator is saved in LocaleDecimalSeparator variable.

    Do not depend on this feature. Maybe we had good reasons to do this, but in the long run it may be unexpected to new developers that the engine overrides a global DecimalSeparator. We will remove this feature in the future.

    Use FormatDot to reliably output floating point values with "dot" as a decimal separator. Similarly, use TryStrToFloatDot to read string with dot to a float.

  • Makes AnsiString (which is usually just called "string") have UTF-8 encoding.

    This is consistent with Lazarus, that already does the same: http://wiki.lazarus.freepascal.org/Unicode_Support_in_Lazarus . This way you can just use "string" (not UTF8String or UnicodeString) throughout your code, and everything will just work.

    This way your applications will behave the same, whether they use LCL (which happens if you use TCastleControl on Lazarus form) or not (which happens if you use TCastleWindow).

    This is also consistent with what our TCastleFont expects (it's rendering assumes UTF-8 encoding of strings) and what some of our XML manipulation routines expect.

Uses

  • BaseUnix
  • Unix
  • Dl
  • Variants
  • SysUtils
  • Math
  • Generics.Collections

Overview

Classes, Interfaces, Objects and Records

Name Description
Class EInternalError Internal error (bug) in the program.
Class ECheckFailed  
Class TNoParameterlessContructor Descend from this to hide a parameterless constructor.
Class TStructList List of structures.
Class EListsDifferentCount  
Class TWordList  
Class TLongWordList  
Class TFloatList  
Class TSingleList  
Class TDoubleList  
Class TCardinalList  
Class TBooleanList  
Class TLongIntList  
Class TIntegerList  
Class EShortErrorMessage Descend from this to mark exceptions that should be shown in more concise way by ExceptMessage function.
Class TCodeBreaker Special class to raise an exception that is always catched.
Class EVectorInvalidOp  
Class ETransformedResultInvalid  

Functions and Procedures

procedure Sort(Arr: pointer; ArrRecordSize: Cardinal; IsSmallerFunc: TIsSmallerFunc; IsSmallerFuncData: Pointer; FirstIndex, LastIndex: integer; CountToUseSimpleSort: Integer = DefaultCountToUseSimpleSort); overload; deprecated 'use Generics.Collections lists and their Sort method';
procedure Sort(Arr: pointer; ArrRecordSize: Cardinal; ArrStride: integer; IsSmallerFunc: TIsSmallerFunc; IsSmallerFuncData: Pointer; FirstIndex, LastIndex: integer; CountToUseSimpleSort: Integer = DefaultCountToUseSimpleSort); overload; deprecated 'use Generics.Collections lists and their Sort method';
procedure SortByObject(Arr: pointer; ArrRecordSize: Cardinal; IsSmallerFunc: TIsSmallerFuncByObject; FirstIndex, LastIndex: integer; CountToUseSimpleSort: Integer = DefaultCountToUseSimpleSort); overload; deprecated 'use Generics.Collections lists and their Sort method';
procedure SortByObject(Arr: pointer; ArrRecordSize: Cardinal; ArrStride: integer; IsSmallerFunc: TIsSmallerFuncByObject; FirstIndex, LastIndex: integer; CountToUseSimpleSort: Integer = DefaultCountToUseSimpleSort); overload; deprecated 'use Generics.Collections lists and their Sort method';
procedure Check(TrueValue: boolean; const ErrMessage: string = 'Check failed');
function ArrayPosStr(const A: string; const Arr: array of string): Integer; overload;
function ArrayPosText(const A: string; const Arr: array of string; IgnoreCase: boolean = true): Integer; overload;
function Iff(boolval: boolean; trueval, falseval: string) : string; overload;
function Iff(boolval: boolean; trueval, falseval: Integer) : Integer; overload;
function Iff(boolval: boolean; trueval, falseval: Float) : Float; overload;
function Iff(boolval: boolean; trueval, falseval: Cardinal): Cardinal; overload;
function Iff(boolval: boolean; trueval, falseval: char) : char; overload;
function SFPCVersion: string;
function SCompilerDescription: string;
function SCastleEngineProgramHelpSuffix(const DisplayApplicationName: string; const Version: string; WrapLines: boolean): string;
procedure OSCheck(TrueValue: boolean); overload;
procedure OSCheck(TrueValue: boolean; const Place: string); overload;
function FormatDot(const Fmt: String; const Args: array of const): String;
function TryStrToFloatDot(const S: String; out Value: Single): Boolean; overload;
function TryStrToFloatDot(const S: String; out Value: Double): Boolean; overload;
function StrToFloatDot(const S: String): Extended;
function StrToFloatDefDot(Const S: String; const Default: Extended): Extended;
function ExceptMessage(const E: TObject): string;
procedure ProgramBreak; deprecated 'Use Halt';
function CastleReadLink(const FileName: string): string;
procedure SwapValues(var a, b: Byte ); overload; inline;
procedure SwapValues(var a, b: Int64 ); overload; inline;
procedure SwapValues(var a, b: QWord ); overload; inline;
procedure SwapValues(var a, b: Integer ); overload; inline;
procedure SwapValues(var a, b: Cardinal); overload; inline;
procedure SwapValues(var a, b: Single ); overload; inline;
procedure SwapValues(var a, b: Double ); overload; inline;
procedure SwapValues(var a, b: char ); overload; inline;
procedure SwapValues(var a, b: Pointer ); overload; inline;
procedure OrderUp(var Smaller, Larger: Int64 ); overload; inline;
procedure OrderUp(var Smaller, Larger: Integer ); overload; inline;
procedure OrderUp(var Smaller, Larger: Cardinal); overload; inline;
procedure OrderUp(var Smaller, Larger: Single ); overload; inline;
procedure OrderUp(var Smaller, Larger: Double ); overload; inline;
procedure OrderUp(x, y: Integer; var Smaller, Larger: Integer ); overload; inline;
procedure OrderUp(x, y: Cardinal; var Smaller, Larger: Cardinal); overload; inline;
procedure OrderUp(x, y: Single; var Smaller, Larger: Single ); overload; inline;
procedure OrderUp(x, y: Double; var Smaller, Larger: Double ); overload; inline;
procedure MinVar(var a: Word ; const b: Word ); overload; inline;
procedure MinVar(var a: Int64 ; const b: Int64 ); overload; inline;
procedure MinVar(var a: Integer ; const b: Integer ); overload; inline;
procedure MinVar(var a: Cardinal; const b: Cardinal); overload; inline;
procedure MinVar(var a: Single ; const b: Single ); overload; inline;
procedure MinVar(var a: Double ; const b: Double ); overload; inline;
procedure MaxVar(var a: Word ; const b: Word ); overload; inline;
procedure MaxVar(var a: Int64 ; const b: Int64 ); overload; inline;
procedure MaxVar(var a: Integer ; const b: Integer ); overload; inline;
procedure MaxVar(var a: Cardinal; const b: Cardinal); overload; inline;
procedure MaxVar(var a: Single ; const b: Single ); overload; inline;
procedure MaxVar(var a: Double ; const b: Double ); overload; inline;
function IndexMax(const a0, a1, a2: Double): Integer; overload; inline;
function IndexMin(const a0, a1, a2: Double): Integer; overload; inline;
function Between(const a, vBegin, vEnd: Int64 ): boolean; overload; inline;
function Between(const a, vBegin, vEnd: Integer ): boolean; overload; inline;
function Between(const a, vBegin, vEnd: cardinal): boolean; overload; inline;
function Between(const a, vBegin, vEnd: Float ): boolean; overload; inline;
function Between(const a, vBegin, vEnd: Char ): boolean; overload; inline;
function RoundClamp255(const A: Single): Byte; inline;
function Clamped(const a, vBegin, vEnd: Int64 ): Int64 ; overload; inline;
function Clamped(const a, vBegin, vEnd: QWord ): QWord ; overload; inline;
function Clamped(const a, vBegin, vEnd: Integer ): Integer ; overload; inline;
function Clamped(const a, vBegin, vEnd: cardinal): cardinal; overload; inline;
function Clamped(const a, vBegin, vEnd: Single ): Single ; overload; inline;
function Clamped(const a, vBegin, vEnd: Double ): Double ; overload; inline;
procedure ClampVar(var a: Int64 ; const vBegin, vEnd: Int64 ); overload; inline;
procedure ClampVar(var a: QWord ; const vBegin, vEnd: QWord ); overload; inline;
procedure ClampVar(var a: Integer ; const vBegin, vEnd: Integer ); overload; inline;
procedure ClampVar(var a: cardinal; const vBegin, vEnd: cardinal); overload; inline;
procedure ClampVar(var a: Single ; const vBegin, vEnd: Single ); overload; inline;
procedure ClampVar(var a: Double ; const vBegin, vEnd: Double ); overload; inline;
procedure Clamp(var a: Int64 ; const vBegin, vEnd: Int64 ); overload; inline; deprecated 'Use ClampVar';
procedure Clamp(var a: Integer ; const vBegin, vEnd: Integer ); overload; inline; deprecated 'Use ClampVar';
procedure Clamp(var a: cardinal; const vBegin, vEnd: cardinal); overload; inline; deprecated 'Use ClampVar';
procedure Clamp(var a: Single ; const vBegin, vEnd: Single ); overload; inline; deprecated 'Use ClampVar';
procedure Clamp(var a: Double ; const vBegin, vEnd: Double ); overload; inline; deprecated 'Use ClampVar';
procedure RestOf3dCoords(coord: Integer; out first, second: Integer);
function ChangeIntCycle(value, change, maxValue: Integer): Integer;
function Lerp(const a: Single; const l, h: Integer): Single; overload; inline;
function Lerp(const a: Single; const l, h: Cardinal): Single; overload; inline;
function Lerp(const a, l, h: Single): Single; overload; inline;
function Lerp(const a: Double; const l, h: Integer): Double; overload; inline;
function Lerp(const a: Double; const l, h: Cardinal): Double; overload; inline;
function Lerp(const a, l, h: Double): Double; overload; inline;
function RoundUpToMultiply(value, multiplicator: Integer): Integer;
function BiggestPowerOf2(Value: Cardinal): Cardinal;
function Biggest2Exponent(Value: Cardinal): Integer;
function Smallest2Exponent(Value: Cardinal): Integer;
function Smallest2Power(Value: Cardinal): Cardinal;
function IsPowerOf2(Value: Cardinal): boolean;
function DivRoundUp(const Value, Divider: Cardinal): Cardinal; overload;
function DivRoundUp(const Value, Divider: Integer): Integer; overload;
function MapRange(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: Integer): Float; overload;
function MapRange(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: Int64 ): Float; overload;
function MapRange(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: QWord ): Float; overload;
function MapRange(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: Float ): Float; overload;
function MapRangeClamped(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: Integer): Float; overload;
function MapRangeClamped(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: Int64 ): Float; overload;
function MapRangeClamped(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: QWord ): Float; overload;
function MapRangeClamped(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: Float ): Float; overload;
function RandomFloatRange(const RangeBegin, RangeEnd: Single): Single; overload;
function RandomFloatRange(const RangeBegin, RangeEnd: Float): Float; overload;
function RandomIntRange(const RangeBegin, RangeEnd: Integer): Integer; overload;
function RandomIntRange(const RangeBegin, RangeEnd: Int64): Int64; overload;
function RandomIntRangeInclusive(const RangeBegin, RangeEnd: Integer): Integer; overload;
function RandomIntRangeInclusive(const RangeBegin, RangeEnd: Int64): Int64; overload;
function RandomBoolean: boolean;
function RandomPlusMinus: Integer;
function AngleRadPointToPoint(x1, y1, x2, y2: Single): Single;
function NatNatPower(Base, Exponent: Cardinal): Cardinal;
function ArcCot(x: Float): Float;
function SmallFactorial(n: Integer): Int64;
procedure CastleDivMod(Dividend: Integer; Divisor: Word; out Result, Remainder: SmallInt);
procedure DivUnsignedMod(Dividend: Integer; Divisor: Word; out Result: Smallint; out Remainder: Word);
function CeilDiv(const A, B: Cardinal): Cardinal; overload;
function CeilDiv(const A, B: Int64): Int64; overload;
procedure FloatDivMod(const A, B: Double; out DivResult: Int64; out Remainder: Double);
function FloatModulo(const A, B: Double): Double;
procedure MinMax(const x0, x1, x2: Double; out min, max: Double); overload;
procedure MinMax(const x0, x1, x2: Single; out min, max: Single); overload;
function CastleCoTan(const Value: Float): Float;
function IntSqrt(const Value: Cardinal): Cardinal;
function SmoothStep(const Edge0, Edge1, X: Single): Single;
function Swap32(Value: LongWord): LongWord;
function Swap64(Value: QWord): QWord;
function SwapEndian(const Value: Single): Single; overload;
function SwapEndian(const Value: Double): Double; overload;
function NtoLE(const Value: Single): Single; overload;
function NtoLE(const Value: Double): Double; overload;
function NtoBE(const Value: Single): Single; overload;
function NtoBE(const Value: Double): Double; overload;
function LEtoN(const Value: Single): Single; overload;
function LEtoN(const Value: Double): Double; overload;
function BEtoN(const Value: Single): Single; overload;
function BEtoN(const Value: Double): Double; overload;
function DeleteFileExt(const FileName: string): string;
function ExtractFileDoubleExt(const FileName: string): string;
function ExtractOnlyFilename(const FileName: string): string; deprecated;
function ChangeFilePath(const FileName, NewPath: string): string; deprecated;
function InclPathDelim(const s: string): string;
function ExclPathDelim(const s: string): string;
function IsPathAbsolute(const Path: string): boolean;
function IsPathAbsoluteOnDrive(const Path: string): boolean;
function SpecialDirName(const DirectoryName: string): boolean;
function AppendToFilename(const FileName, Suffix: string): string;
function PointerAdd(p: pointer; add: integer): pointer;
function GetClearMem(Size: integer; ClearValue: byte = 0): pointer; overload;
procedure FreeMemNiling(var p: pointer);
function CheckIsMemCharFilled(const Data; Size: Integer; AChar: Char): Integer;
function IsMemCharFilled(const Data; Size: Integer; AChar: Char): boolean;
function IsMemWordFilled(const Data; Size: Integer; Value: Word): boolean;
function IsMemDWordFilled(const Data; Size: Integer; Value: DWord): boolean;
function OffsetUInt(var A, B): PtrUInt;
function Offset(var A, B): Pointer;
function CompareMethods(const AMethod1, AMethod2: TMethod): boolean; deprecated 'use SameMethods';
function SameMethods(const AMethod1, AMethod2: TMethod): boolean;
procedure ErrorWrite(const s: string); overload;
procedure WarningWrite(const s: string); overload;
procedure InfoWrite(const s: string); overload;
procedure ErrorWrite(const s: string; const args: array of const); overload;
procedure WarningWrite(const s: string; const args: array of const); overload;
procedure InfoWrite(const s: string; const args: array of const); overload;
procedure InfoWriteParts(const TitleFormat: string; const Messages: array of string); deprecated;

Types

Float = Math.Float ;
PFloat = Math.PFloat ;
PCardinal = ˆCardinal;
PLongWord = ˆLongWord;
PShortint = ˆShortint;
PBoolean = ˆBoolean;
PByteArray = ˆTByteArray;
TByteArray = array[0..MaxInt div SizeOf(Byte)-1] of Byte;
PString = ˆAnsiString;
PtrObject = ˆTObject;
TIsSmallerFunc = function (const A, B, Data: Pointer): boolean;
TIsSmallerFuncByObject = function (const A, B: Pointer): boolean of object;
TSingleArray = packed array [0..MaxInt div SizeOf(Single) - 1] of Single;
PSingleArray = ˆTSingleArray;
TLongIntArray = packed array [0..MaxInt div SizeOf(LongInt) - 1] of LongInt;
PLongIntArray = ˆTLongIntArray;
EWithHiddenClassName = EShortErrorMessage deprecated 'use EShortErrorMessage';

Constants

DefaultCountToUseSimpleSort = 10;
NL = LineEnding;
CastleEngineVersion = '6.5 (unstable)' ;
enatural = 2.71828182845905;
sqrt2 = 1.4142135623730950488016887242097;
Sqrt3 = 1.7320508075688773;
HalfPi = 1.57079632679489661923;
RootDir = '/' ;
ExeExtension = '' ;

Variables

CastleDesignMode: Boolean;
LocaleDecimalSeparator: char;

Description

Functions and Procedures

procedure Sort(Arr: pointer; ArrRecordSize: Cardinal; IsSmallerFunc: TIsSmallerFunc; IsSmallerFuncData: Pointer; FirstIndex, LastIndex: integer; CountToUseSimpleSort: Integer = DefaultCountToUseSimpleSort); overload; deprecated 'use Generics.Collections lists and their Sort method';

Warning: this symbol is deprecated: use Generics.Collections lists and their Sort method

Sort given table of items.

Sorts items ascending, that is Arr[FirstIndex] <= ... <= Arr[LastIndex].

Parameters
Arr
Pointer to items array in memory.
ArrRecordSize
Size (in bytes) of every item. This is the size of item that will be moved around in the memory.
IsSmallerFunc
Comparison function, should return is "A < B" true.

I'm assuming here that IsSmallerFunc works like mathematical "<": it's not reflexive (IsSmallerFunc(A, A) = False), for A <> B exactly one of IsSmallerFunc(A, B) or IsSmallerFunc(B, A) is true, and it's transitive.

Note that IsSmallerFunc gets only the pointers to the items. These may be pointers to the Arr, or a pointer to internal temporary copy of some array item. So IsSmallerFunc cannot modify the item underneath (it would not work for internal copy, and also would create problems with types that need initialization/finalization since our internal copy is done using low-level memory copying.)

FirstIndex
FirstIndex and LastIndex allow you to sort only given part of the array. We don't touch items outside of this range. Note that you could achieve the effect of FirstIndex > 0 also by increasing the Arr pointer, but FirstIndex is usually more comfortable.

If FirstIndex > LastIndex, we do nothing.

ArrStride
Distance (in bytes) between array items in memory. If you don't provide it, we'll assume ArrRecordSize. ArrStride is useful if your array is interleaved with another array, and you want to keep the other data untouched by sorting.

ArrStride must be > 0, actually it must be > ArrRecordSize for sensible behavior. (Unless ArrRecordSize is 0, then ArrStride may be 0 too.).

procedure Sort(Arr: pointer; ArrRecordSize: Cardinal; ArrStride: integer; IsSmallerFunc: TIsSmallerFunc; IsSmallerFuncData: Pointer; FirstIndex, LastIndex: integer; CountToUseSimpleSort: Integer = DefaultCountToUseSimpleSort); overload; deprecated 'use Generics.Collections lists and their Sort method';

Warning: this symbol is deprecated: use Generics.Collections lists and their Sort method

 
procedure SortByObject(Arr: pointer; ArrRecordSize: Cardinal; IsSmallerFunc: TIsSmallerFuncByObject; FirstIndex, LastIndex: integer; CountToUseSimpleSort: Integer = DefaultCountToUseSimpleSort); overload; deprecated 'use Generics.Collections lists and their Sort method';

Warning: this symbol is deprecated: use Generics.Collections lists and their Sort method

 
procedure SortByObject(Arr: pointer; ArrRecordSize: Cardinal; ArrStride: integer; IsSmallerFunc: TIsSmallerFuncByObject; FirstIndex, LastIndex: integer; CountToUseSimpleSort: Integer = DefaultCountToUseSimpleSort); overload; deprecated 'use Generics.Collections lists and their Sort method';

Warning: this symbol is deprecated: use Generics.Collections lists and their Sort method

 
procedure Check(TrueValue: boolean; const ErrMessage: string = 'Check failed');

Check condition.

Exceptions raised
ECheckFailed
Raised with ErrMessage if condition TrueValue if false.
function ArrayPosStr(const A: string; const Arr: array of string): Integer; overload;

Search the array for a given value. Returns index (zero-based) or -1 if not found.

Useful for writing case as:

case ArrayPosStr(variable, [val1, val2]) of
  0 : Something1;
  1 : Something2;
  else SomethingElse;
end;

function ArrayPosText(const A: string; const Arr: array of string; IgnoreCase: boolean = true): Integer; overload;
 
function Iff(boolval: boolean; trueval, falseval: string) : string; overload;
 
function Iff(boolval: boolean; trueval, falseval: Integer) : Integer; overload;
 
function Iff(boolval: boolean; trueval, falseval: Float) : Float; overload;
 
function Iff(boolval: boolean; trueval, falseval: Cardinal): Cardinal; overload;
 
function Iff(boolval: boolean; trueval, falseval: char) : char; overload;
 
function SFPCVersion: string;

FPC version. In the form 'version.release.patch'.

This is actually a constant (for every run of a program it has always the same value) but I can't declare it as a Pascal constant because it must use "Format" function that is not allowed in constant expressions.

function SCompilerDescription: string;

Short name and version of Pascal compiler used to compile this unit. It is a constant, actually, but I cannot declare it as a constant because it must call SFPCVersion that is not declared as a constant.

function SCastleEngineProgramHelpSuffix(const DisplayApplicationName: string; const Version: string; WrapLines: boolean): string;

Print some common info for programs released on [https://castle-engine.io/]. This is useful only for programs released on this WWW page by Michalis. Resulting string is multiline.

Parameters
DisplayApplicationName
Short application name. Usually you should take it from ApplicationName.
Version
Version to display. Usually you should take it from ApplicationProperties.Version.
WrapLines
If true then resulting string will not have lines longer than 80 characters. Suitable for printing program help message on stdout, e.g. in response to --help option.
procedure OSCheck(TrueValue: boolean); overload;

If not TrueValue then RaiseLastOSError.

procedure OSCheck(TrueValue: boolean; const Place: string); overload;
 
function FormatDot(const Fmt: String; const Args: array of const): String;

Like standard Format, but always uses dot (.) as a decimal separator for the floating point numbers, regardless of the user's locale settings.

function TryStrToFloatDot(const S: String; out Value: Single): Boolean; overload;

Like standard TryStrToFloat, but always uses dot (.) as a decimal separator for the floating point numbers, regardless of the user's locale settings.

function TryStrToFloatDot(const S: String; out Value: Double): Boolean; overload;
 
function StrToFloatDot(const S: String): Extended;

Like standard StrToFloat, but always uses dot (.) as a decimal separator for the floating point numbers, regardless of the user's locale settings.

function StrToFloatDefDot(Const S: String; const Default: Extended): Extended;

Like standard StrToFloatDef, but always uses dot (.) as a decimal separator for the floating point numbers, regardless of the user's locale settings.

function ExceptMessage(const E: TObject): string;

Nice exception description. Contains the ClassName (unless it descends from EShortErrorMessage), and the exception Message (if it descends from Exception).

procedure ProgramBreak; deprecated 'Use Halt';

Warning: this symbol is deprecated: Use Halt

 
function CastleReadLink(const FileName: string): string;

Return the symlink target path. Like Libc.ReadLink or FpReadLink, but more comfortable, it returns a normal Pascal string.

Exceptions raised
EOSError
In case of any failure (non-existing FileName etc.)
procedure SwapValues(var a, b: Byte ); overload; inline;

Swap variables values.

procedure SwapValues(var a, b: Int64 ); overload; inline;
 
procedure SwapValues(var a, b: QWord ); overload; inline;
 
procedure SwapValues(var a, b: Integer ); overload; inline;
 
procedure SwapValues(var a, b: Cardinal); overload; inline;
 
procedure SwapValues(var a, b: Single ); overload; inline;
 
procedure SwapValues(var a, b: Double ); overload; inline;
 
procedure SwapValues(var a, b: char ); overload; inline;
 
procedure SwapValues(var a, b: Pointer ); overload; inline;
 
procedure OrderUp(var Smaller, Larger: Int64 ); overload; inline;

Make sure the Smaller value is <= than the Larger value, by eventually swapping them.

procedure OrderUp(var Smaller, Larger: Integer ); overload; inline;
 
procedure OrderUp(var Smaller, Larger: Cardinal); overload; inline;
 
procedure OrderUp(var Smaller, Larger: Single ); overload; inline;
 
procedure OrderUp(var Smaller, Larger: Double ); overload; inline;
 
procedure OrderUp(x, y: Integer; var Smaller, Larger: Integer ); overload; inline;

Assign the smaller value from X, Y to Smaller variable, the other one to Larger variable.

procedure OrderUp(x, y: Cardinal; var Smaller, Larger: Cardinal); overload; inline;
 
procedure OrderUp(x, y: Single; var Smaller, Larger: Single ); overload; inline;
 
procedure OrderUp(x, y: Double; var Smaller, Larger: Double ); overload; inline;
 
procedure MinVar(var a: Word ; const b: Word ); overload; inline;

Update value of A to be a minimum of A, B. Works like A := Min(A, B), but is marginally faster, since you don't have to do anything when A is already smaller.

procedure MinVar(var a: Int64 ; const b: Int64 ); overload; inline;

procedure MinVar(var a: LongWord; const b: LongWord); overload; {$ifdef SUPPORTS_INLINE} inline; {$endif} // same as Cardinal

procedure MinVar(var a: Integer ; const b: Integer ); overload; inline;
 
procedure MinVar(var a: Cardinal; const b: Cardinal); overload; inline;
 
procedure MinVar(var a: Single ; const b: Single ); overload; inline;
 
procedure MinVar(var a: Double ; const b: Double ); overload; inline;
 
procedure MaxVar(var a: Word ; const b: Word ); overload; inline;

Update value of A to be a maximum of A, B. Works like A := Max(A, B), but is marginally faster, since you don't have to do anything when A is already larger.

procedure MaxVar(var a: Int64 ; const b: Int64 ); overload; inline;

procedure MaxVar(var a: LongWord; const b: LongWord); overload; {$ifdef SUPPORTS_INLINE} inline; {$endif} // same as Cardinal

procedure MaxVar(var a: Integer ; const b: Integer ); overload; inline;
 
procedure MaxVar(var a: Cardinal; const b: Cardinal); overload; inline;
 
procedure MaxVar(var a: Single ; const b: Single ); overload; inline;
 
procedure MaxVar(var a: Double ; const b: Double ); overload; inline;
 
function IndexMax(const a0, a1, a2: Double): Integer; overload; inline;

Index (0, 1 or 2) of maximum / minimum of 3 numbers.

function IndexMin(const a0, a1, a2: Double): Integer; overload; inline;
 
function Between(const a, vBegin, vEnd: Int64 ): boolean; overload; inline;
 
function Between(const a, vBegin, vEnd: Integer ): boolean; overload; inline;
 
function Between(const a, vBegin, vEnd: cardinal): boolean; overload; inline;
 
function Between(const a, vBegin, vEnd: Float ): boolean; overload; inline;
 
function Between(const a, vBegin, vEnd: Char ): boolean; overload; inline;
 
function RoundClamp255(const A: Single): Byte; inline;
 
function Clamped(const a, vBegin, vEnd: Int64 ): Int64 ; overload; inline;
 
function Clamped(const a, vBegin, vEnd: QWord ): QWord ; overload; inline;
 
function Clamped(const a, vBegin, vEnd: Integer ): Integer ; overload; inline;
 
function Clamped(const a, vBegin, vEnd: cardinal): cardinal; overload; inline;
 
function Clamped(const a, vBegin, vEnd: Single ): Single ; overload; inline;
 
function Clamped(const a, vBegin, vEnd: Double ): Double ; overload; inline;
 
procedure ClampVar(var a: Int64 ; const vBegin, vEnd: Int64 ); overload; inline;
 
procedure ClampVar(var a: QWord ; const vBegin, vEnd: QWord ); overload; inline;
 
procedure ClampVar(var a: Integer ; const vBegin, vEnd: Integer ); overload; inline;
 
procedure ClampVar(var a: cardinal; const vBegin, vEnd: cardinal); overload; inline;
 
procedure ClampVar(var a: Single ; const vBegin, vEnd: Single ); overload; inline;
 
procedure ClampVar(var a: Double ; const vBegin, vEnd: Double ); overload; inline;
 
procedure Clamp(var a: Int64 ; const vBegin, vEnd: Int64 ); overload; inline; deprecated 'Use ClampVar';

Warning: this symbol is deprecated: Use ClampVar

 
procedure Clamp(var a: Integer ; const vBegin, vEnd: Integer ); overload; inline; deprecated 'Use ClampVar';

Warning: this symbol is deprecated: Use ClampVar

 
procedure Clamp(var a: cardinal; const vBegin, vEnd: cardinal); overload; inline; deprecated 'Use ClampVar';

Warning: this symbol is deprecated: Use ClampVar

 
procedure Clamp(var a: Single ; const vBegin, vEnd: Single ); overload; inline; deprecated 'Use ClampVar';

Warning: this symbol is deprecated: Use ClampVar

 
procedure Clamp(var a: Double ; const vBegin, vEnd: Double ); overload; inline; deprecated 'Use ClampVar';

Warning: this symbol is deprecated: Use ClampVar

 
procedure RestOf3dCoords(coord: Integer; out first, second: Integer);

3D coordinates (0, 1 or 2) except the given coordinate. If Coord = 0, then it sets First = 1 and Second = 2. And so on — for each Coord value, we set First and Second to the remaining indexes.

function ChangeIntCycle(value, change, maxValue: Integer): Integer;

Increase Value by Change, nicely wrapping in [0..MaxValue], accepting also negative Change. The final value is always in the [0..MaxValue] range, even when initial Value was outside.

function Lerp(const a: Single; const l, h: Integer): Single; overload; inline;

Linear interpolation between two values. Returns (1-A)*L + A*H.

function Lerp(const a: Single; const l, h: Cardinal): Single; overload; inline;
 
function Lerp(const a, l, h: Single): Single; overload; inline;
 
function Lerp(const a: Double; const l, h: Integer): Double; overload; inline;
 
function Lerp(const a: Double; const l, h: Cardinal): Double; overload; inline;
 
function Lerp(const a, l, h: Double): Double; overload; inline;
 
function RoundUpToMultiply(value, multiplicator: Integer): Integer;

Smallest multiple of Multiplicator that is still >= Value.

function BiggestPowerOf2(Value: Cardinal): Cardinal;

Largest power of 2 still <= Value. When Value = 0 returns 0.

function Biggest2Exponent(Value: Cardinal): Integer;

Exponent of the largest power of 2 that it's still <= Value. Like BiggestPowerOf2, except that this returns which power of 2 it is, while BiggestPowerOf2 just returns exactly this power. Biggest2Exponent(0) = -1.

function Smallest2Exponent(Value: Cardinal): Integer;

Smallest exponent such that 2ˆthis exponent is >= Value. Smallest2Exponent(0) = -1 (this is different situation than Smallest2Exponent(1), when we return 0.

function Smallest2Power(Value: Cardinal): Cardinal;

Smallest power of 2 that is >= Value. Like Smallest2Exponent, except here we return 2ˆSmallest2Exponent(Value). Returns 0 when Value = 0.

function IsPowerOf2(Value: Cardinal): boolean;

Check is Value an exact power of 2.

function DivRoundUp(const Value, Divider: Cardinal): Cardinal; overload;
 
function DivRoundUp(const Value, Divider: Integer): Integer; overload;
 
function MapRange(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: Integer): Float; overload;

Linearly map value from a one range to another.

Consider how SourceVal is placed in the [SourceBegin .. SourceEnd] (it may be outside of this range, it all still works OK). It has some distance to range start (SourceBegin), and some distance to range end (SourceEnd).

We want to find another number, that is identically placed in another range [DestBegin .. DestEnd].

  1. Such that Distance(SourceVal, SourceBegin) / Distance(SourceVal, SourceEnd) = Distance(Result, DestBegin) / Distance(Result, DestEnd).

  2. And such that it's on the same side of the range. So if SourceVal is beyond SourceEnd (that is, SourceBegin < SourceEnd < SourceVal or SourceBegin > SourceEnd > SourceVal) then the result must be similarly beyond DestEnd.

    As you can see, this works regardless if one, or both, of the ranges increase (range end is larger than range begin).

MapRangeClamped additionally at the end clamps the result to be within [DestBegin, DestEnd] range (or [DestEnd, DestBegin] range, in case DestEnd < DestBegin).

function MapRange(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: Int64 ): Float; overload;
 
function MapRange(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: QWord ): Float; overload;
 
function MapRange(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: Float ): Float; overload;
 
function MapRangeClamped(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: Integer): Float; overload;
 
function MapRangeClamped(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: Int64 ): Float; overload;
 
function MapRangeClamped(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: QWord ): Float; overload;
 
function MapRangeClamped(const SourceVal, SourceBegin, SourceEnd, DestBegin, DestEnd: Float ): Float; overload;
 
function RandomFloatRange(const RangeBegin, RangeEnd: Single): Single; overload;

Random Float value in the given range, result is between RangeBegin and RangeEnd. Always pass arguments such that RangeBegin < RangeEnd.

function RandomFloatRange(const RangeBegin, RangeEnd: Float): Float; overload;
 
function RandomIntRange(const RangeBegin, RangeEnd: Integer): Integer; overload;

Random integer value in the given range, result is always >= RangeBegin and < RangeEnd. So result is never equal to RangeEnd, this is often convenient, and makes RandomIntRange(0, N) consistent with Random(N). Always pass arguments such that RangeBegin < RangeEnd.

function RandomIntRange(const RangeBegin, RangeEnd: Int64): Int64; overload;
 
function RandomIntRangeInclusive(const RangeBegin, RangeEnd: Integer): Integer; overload;

Random int value in the given range, result is always >= RangeBegin and <= RangeEnd. Always pass arguments such that RangeBegin <= RangeEnd.

function RandomIntRangeInclusive(const RangeBegin, RangeEnd: Int64): Int64; overload;
 
function RandomBoolean: boolean;
 
function RandomPlusMinus: Integer;

Random -1 or +1.

function AngleRadPointToPoint(x1, y1, x2, y2: Single): Single;

Angle between a 2D line segments and OX axis. Angle 0 means that Y1 = Y2 and X2 > X1, then the angle increases as you rotate CCW. In radians.

function NatNatPower(Base, Exponent: Cardinal): Cardinal;

Calculate power Base to Exponent, knowing both arguments (and so, also the result) are >= 0.

function ArcCot(x: Float): Float;
 
function SmallFactorial(n: Integer): Int64;

Trivial factorial with Int64 result. Beware, the results very quickly stop to fit inside Int64 range.

procedure CastleDivMod(Dividend: Integer; Divisor: Word; out Result, Remainder: SmallInt);

Better DivMod version, in case Dividend may be < 0.

This fixes lack of DivMod with negative Remainder (for FPC at least older than 2.2.4, see fpc-devel thread "Math.DivMod results should be signed" on 2006-03-21, http://www.mail-archive.com/[email protected]/msg04565.html).

And workarounds faulty DivMod behavior with FPC 2.4.0, see http://bugs.freepascal.org/view.php?id=15453

procedure DivUnsignedMod(Dividend: Integer; Divisor: Word; out Result: Smallint; out Remainder: Word);

Like DivMod (return result of Integer division and a remainder), but always return Remainder >= 0.

This is useful in case when Dividend < 0. Standard DivMod (and Pascal div and mod operators) return then Result rounded toward zero, and Remainder may be < 0. This procedure will return Result rounded toward negative infinity, and Remainder will always be >= 0.

function CeilDiv(const A, B: Cardinal): Cardinal; overload;

Returns Ceil(A / B), but calculated faster and more precisely (without floating-point help).

function CeilDiv(const A, B: Int64): Int64; overload;
 
procedure FloatDivMod(const A, B: Double; out DivResult: Int64; out Remainder: Double);

Calculate Integer division and modulo on two Float arguments. Requires that A >= 0 and B > 0, and the Result is always >= 0.

Tries to secure against floating point imprecision. It's always guaranteed that Remainder >= 0 and <= B (and usually should be < B, but this cannot be guaranteed).

function FloatModulo(const A, B: Double): Double;

Calculate Float modulo of division on two Float arguments. Works for any A (lesser than zero too). Assumes that B > 0.

Tries to secure against floating point imprecision. It's always guaranteed that Remainder >= 0 and <= B (and usually should be < B, but this cannot be guaranteed).

procedure MinMax(const x0, x1, x2: Double; out min, max: Double); overload;
 
procedure MinMax(const x0, x1, x2: Single; out min, max: Single); overload;
 
function CastleCoTan(const Value: Float): Float;

Our version of CoTan, to workaround http://www.freepascal.org/mantis/view.php?id=9944.

function IntSqrt(const Value: Cardinal): Cardinal;

Floor from Sqrt(Value).

function SmoothStep(const Edge0, Edge1, X: Single): Single;

Hermite interpolation between two values. For X changing from Edge0 to Edge1, the resulting value changes from 0 to 1, smoothly (not with a linear speed). This is useful to make nicer transition from one value to another, it often looks better than using directly Lerp or MapRange.

Just like GLSL smoothstep: http://www.khronos.org/opengles/sdk/docs/manglsl/xhtml/smoothstep.xml

function Swap32(Value: LongWord): LongWord;

Utility functions to control the endianess of Single and Double values; no support for Extended though as such values have yet to be encountered when read from a file

function Swap64(Value: QWord): QWord;
 
function SwapEndian(const Value: Single): Single; overload;
 
function SwapEndian(const Value: Double): Double; overload;
 
function NtoLE(const Value: Single): Single; overload;
 
function NtoLE(const Value: Double): Double; overload;
 
function NtoBE(const Value: Single): Single; overload;
 
function NtoBE(const Value: Double): Double; overload;
 
function LEtoN(const Value: Single): Single; overload;
 
function LEtoN(const Value: Double): Double; overload;
 
function BEtoN(const Value: Single): Single; overload;
 
function BEtoN(const Value: Double): Double; overload;
 
function DeleteFileExt(const FileName: string): string;

Remove from the FileName the last extension (including the dot). Note that if the FileName had a couple of extensions (e.g. blah.x3d.gz) this will remove only the last one. Will remove nothing if filename has no extension.

It is not adviced to use this function, better to operate on URLs and MIME types instead of filenames and extensions, see CastleURIUtils.

function ExtractFileDoubleExt(const FileName: string): string;

Extracts two last extensions from the filename, if it has two extensions. If the filename has only one extension, returns that one extension, if the filename has no extension — returns empty string, similar to ExtractFileExt.

This is useful to detect file types from filenames like model.x3d.gz, where ExtractFileExt returns only .gz. This function will return .x3d.gz.

It is not adviced to use this function, better to operate on URLs and MIME types instead of filenames and extensions, see CastleURIUtils.

function ExtractOnlyFilename(const FileName: string): string; deprecated;

Warning: this symbol is deprecated.

Extracts from FileName the name of file, without directory, without last extension and without any Windows drive letter.

Deprecated, since we use URLs everywhere and also because this has very low usage. Use DeleteURIExt(ExtractURIName(URL)) if you really need to.

function ChangeFilePath(const FileName, NewPath: string): string; deprecated;

Warning: this symbol is deprecated.

Returns FileName with directory (path) part replaced with given NewPath. NewPath must contain trailing PathDelim.

Deprecated, since we use URLs everywhere and also because this has very low usage.

function InclPathDelim(const s: string): string;

Include / exclude the last path delimiter, if necessary. They are just comfortable shorter names for IncludeTrailingPathDelimiter and ExcludeTrailingPathDelimiter.

function ExclPathDelim(const s: string): string;
 
function IsPathAbsolute(const Path: string): boolean;

Check is the given Path absolute.

Path may point to directory or normal file, it doesn't matter. Also it doesn't matter whether Path ends with PathDelim or not.

Note for Windows: while it's obvious that 'c:\autoexec.bat' is an absolute path, and 'autoexec.bat' is not, there's a question whether path like '\autoexec.bat' is absolute? It doesn't specify drive letter, but it does specify full directory hierarchy on some drive. This function treats this as not absolute, on the reasoning that "not all information is contained in Path".

See also
IsPathAbsoluteOnDrive
Just like IsPathAbsolute, but on Windows accepts also paths that specify full directory tree without drive letter.
function IsPathAbsoluteOnDrive(const Path: string): boolean;

Just like IsPathAbsolute, but on Windows accepts also paths that specify full directory tree without drive letter.

See also
IsPathAbsolute
Check is the given Path absolute.
function SpecialDirName(const DirectoryName: string): boolean;

Checks is the directory name special, like "." or "..".

The precise definition of "special" is that you cannot ever create or even have any filenames / directories named like this.

function AppendToFilename(const FileName, Suffix: string): string;

Add Suffix to the filename, right before extension. Returns DeleteFileExt(FileName) + Suffix + ExtractFileExt(FileName).

function PointerAdd(p: pointer; add: integer): pointer;

Pointer arithmetic. Will wrap over if you add too much. Add may be negative. This is just a shortcut for PtrInt(Result) := PtrInt(P)+Add, without any range / overflow checks.

function GetClearMem(Size: integer; ClearValue: byte = 0): pointer; overload;
 
procedure FreeMemNiling(var p: pointer);

Safer version of FreeMem, checks is parameter Nil, and sets it to Nil afterwards.

function CheckIsMemCharFilled(const Data; Size: Integer; AChar: Char): Integer;

Check is memory filled with the given character. Returns -1 is True, or the number (between 0 .. Size - 1) or the first character different than AChar.

function IsMemCharFilled(const Data; Size: Integer; AChar: Char): boolean;

Check is memory filled with the given character. Returns simple boolean, use CheckIsMemCharFilled to get more informative result.

function IsMemWordFilled(const Data; Size: Integer; Value: Word): boolean;

Check is memory filled with the Word (2 byte sequence). Size if the number of words (not bytes), this is consequent with Size parameter from FillWord from FPC's RTL.

function IsMemDWordFilled(const Data; Size: Integer; Value: DWord): boolean;

Check is memory filled with the DWord (4 byte sequence). Size if the number of dwords (not bytes), this is consequent with Size parameter from FillDWord from FPC's RTL.

function OffsetUInt(var A, B): PtrUInt;

Calculate shift between A and B addresses (in bytes). Useful to pass as offsets to methods like TGLSLAttribute.EnableArray that wrap OpenGL vertex-array API. This is simply Result := A - B, except we do some typecasting.

function Offset(var A, B): Pointer;
 
function CompareMethods(const AMethod1, AMethod2: TMethod): boolean; deprecated 'use SameMethods';

Warning: this symbol is deprecated: use SameMethods

Compare two methods.

function SameMethods(const AMethod1, AMethod2: TMethod): boolean;
 
procedure ErrorWrite(const s: string); overload;

Write using a dialog box or console.

If we are a Windows GUI program (not IsConsole) then we use native Windows dialog boxes. Otherwise (a console is available, which is always true on non-Windows) we output the message using simple Writeln (to standard output for InfoWrite, or ErrOutput for ErrorWrite and WarningWrite).

procedure WarningWrite(const s: string); overload;
 
procedure InfoWrite(const s: string); overload;
 
procedure ErrorWrite(const s: string; const args: array of const); overload;
 
procedure WarningWrite(const s: string; const args: array of const); overload;
 
procedure InfoWrite(const s: string; const args: array of const); overload;
 
procedure InfoWriteParts(const TitleFormat: string; const Messages: array of string); deprecated;

Warning: this symbol is deprecated.

Output messages, using console or dialog box.

If we're not on Windows or IsConsole, then we simply output Messages using Writeln.

If we're on Windows and not IsConsole, then every Messages is displayed in a separate dialog box. Dialog box uses our InfoBox routine, with Messages[I] being message content and title being Format(TitleFormat, [I + 1, Messages.Count]).

This is good for outputting a lot of information.

Deprecated. This just looks ugly in GUI version. It's better to present long information using only a console (just use Writeln), or only a full-featured GUI (like Lazarus LCL or our CastleUIControls).

Types

Float = Math.Float ;

Floating-point type with best precision.

PFloat = Math.PFloat ;
 
PCardinal = ˆCardinal;
 
PLongWord = ˆLongWord;
 
PShortint = ˆShortint;
 
PBoolean = ˆBoolean;

Pointer to a boolean. Defined as ˆByte in some Delphi Windows unit, for FPC 1.0.x PBoolean is not available at all.

PByteArray = ˆTByteArray;

Infinite array of bytes.

TByteArray = array[0..MaxInt div SizeOf(Byte)-1] of Byte;
 
PString = ˆAnsiString;
 
PtrObject = ˆTObject;

Pointer to TObject. Don't call this PObject or PTObject to avoid possible name clashes with other units (pointers are often used in situations that prevent good type-checking, so better to avoid name clashes to avoid some nasty errors).

TIsSmallerFunc = function (const A, B, Data: Pointer): boolean;
 
TIsSmallerFuncByObject = function (const A, B: Pointer): boolean of object;
 
TSingleArray = packed array [0..MaxInt div SizeOf(Single) - 1] of Single;
 
PSingleArray = ˆTSingleArray;
 
TLongIntArray = packed array [0..MaxInt div SizeOf(LongInt) - 1] of LongInt;
 
PLongIntArray = ˆTLongIntArray;
 
EWithHiddenClassName = EShortErrorMessage deprecated 'use EShortErrorMessage';

Warning: this symbol is deprecated: use EShortErrorMessage

 

Constants

DefaultCountToUseSimpleSort = 10;

When should the complicated sorting algorithm fallback to a simpler one. If number of items is <= CountToUseSimpleSort, then Sort will fallback to SimpleSort (= sort by choosing for now) instead of recursive QuickSort. Set CountToUseSimpleSort = 0 to make it never fall back to SimpleSort.

By default this is DefaultCountToUseSimpleSort.

NL = LineEnding;

New line sequence, suitable for current OS. Short name for LineEnding.

CastleEngineVersion = '6.5 (unstable)' ;

Castle Game Engine version.

enatural = 2.71828182845905;
 
sqrt2 = 1.4142135623730950488016887242097;
 
Sqrt3 = 1.7320508075688773;
 
HalfPi = 1.57079632679489661923;

Half of Pi. Taken from FPC sources, file rtl/inc/genmath.inc

RootDir = '/' ;

Root dir name. Empty if not applicable to this OS.

ExeExtension = '' ;
 

Variables

CastleDesignMode: Boolean;

Are we inside Castle Game Engine designer mode.

LocaleDecimalSeparator: char;
 

Generated by PasDoc 0.15.0.