Browse Source

* simplified uutlEvents

* fixed leaks in uutlGenerics and uutlObservable
* implemented TryGet methods fpr TutlMcfSection
* implemented TryGet methods fpr TutlXmlHelper
master
bergmann 7 years ago
parent
commit
85c54184d1
7 changed files with 460 additions and 259 deletions
  1. +27
    -49
      uutlEvent.pas
  2. +73
    -51
      uutlEventManager.pas
  3. +1
    -1
      uutlGenerics.pas
  4. +98
    -48
      uutlMCF.pas
  5. +74
    -25
      uutlObservable.pas
  6. +12
    -0
      uutlSyncObjs.pas
  7. +175
    -85
      uutlXmlHelper.pas

+ 27
- 49
uutlEvent.pas View File

@@ -22,7 +22,10 @@ type

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TutlEventHandler = procedure (constref aSender: TObject; constref aEventArgs: IutlEventArgs) of object;
TutlEventArgs = class(TInterfacedObject, IutlEventArgs);
TutlEventArgs = class(TutlInterfacedObject, IutlEventArgs)
public
constructor Create;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
IutlObservable = interface(IUnknown)
@@ -93,7 +96,7 @@ type

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TutlEventListenerAsync = class(
TutlInterfaceNoRefCount
TInterfacedObject
, IutlEventListener)

private type
@@ -104,10 +107,9 @@ type
end;

private
fEventLock: TCriticalSection;
fListenerLock: TCriticalSection;
fEvents: TEventList;
fListener: TutlEventListenerSet;
fEventLock: TCriticalSection;
fEvents: TEventList;
fListener: IutlEventListener;

function PopEventPair(out aPair: TEventPair): Boolean;

@@ -115,17 +117,23 @@ type
procedure DispatchEvent(constref aSender: TObject; constref aEventArgs: IutlEventArgs);

public
function RegisterListener (const aListener: IutlEventListener): Boolean;
function UnregisterListener(const aListener: IutlEventListener): Boolean;

procedure DispatchEvents;

constructor Create;
constructor Create(const aListener: IutlEventListener);
destructor Destroy; override;
end;

implementation

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlEventArgs/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlEventArgs.Create;
begin
inherited Create;
AutoFree := true;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlEventList/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -272,67 +280,37 @@ begin
end;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlEventListenerAsync.RegisterListener(const aListener: IutlEventListener): Boolean;
begin
fListenerLock.Enter;
try
result := fListener.Add(aListener);
finally
fListenerLock.Leave;
end;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlEventListenerAsync.UnregisterListener(const aListener: IutlEventListener): Boolean;
begin
fListenerLock.Enter;
try
result := fListener.Remove(aListener);
finally
fListenerLock.Leave;
end;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlEventListenerAsync.DispatchEvents;
var
p: TEventPair;
begin
while PopEventPair(p) do begin
fListenerLock.Enter;
try
fListener.DispatchEvent(p.first, p.second);
finally
fListenerLock.Leave;
end;
end;
while PopEventPair(p) do
fListener.DispatchEvent(p.first, p.second);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlEventListenerAsync.Create;
constructor TutlEventListenerAsync.Create(const aListener: IutlEventListener);
begin
if not Assigned(aListener) then
raise EArgumentNilException.Create('aListener');
inherited Create;
fEventLock := TCriticalSection.Create;
fListenerLock := TCriticalSection.Create;
fEvents := TEventList.Create(true);
fListener := TutlEventListenerSet.Create;
fEventLock := TCriticalSection.Create;
fEvents := TEventList.Create(true);
fListener := aListener;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TutlEventListenerAsync.Destroy;
begin
fEventLock.Enter;
fListenerLock.Enter;
try
FreeAndNil(fEvents);
FreeAndNil(fListener);
fListener := nil;
finally
fListenerLock.Leave;
fEventLock.Leave;
end;
FreeAndNil(fEventLock);
FreeAndNil(fListenerLock);
inherited Destroy;
end;



+ 73
- 51
uutlEventManager.pas View File

@@ -14,8 +14,8 @@ uses

type
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TutlEventType = byte;
TutlEventTypes = set of TutlEventType;
TutlEventType = byte;
TutlEventTypes = set of TutlEventType;
TutlMouseButtons = set of TMouseButton;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -48,7 +48,7 @@ type
property ScreenPos: TPoint read fScreenPos;

constructor Create(
const aSender: TControl;
const aControl: TControl;
const aEventType: TutlEventType;
const aButtons: TutlMouseButtons;
const aClientPos: TPoint);
@@ -67,7 +67,7 @@ type
property ScreenPos: TPoint read fScreenPos;

constructor Create(
const aSender: TControl;
const aControl: TControl;
const aWheelDelta: Integer;
const aClientPos: TPoint);
end;
@@ -83,7 +83,7 @@ type
property KeyCode: Word read fKeyCode;

constructor Create(
const aSender: TControl;
const aControl: TControl;
const aEventType: TutlEventType;
const aCharCode: WideChar;
const aKeyCode: Word);
@@ -102,7 +102,7 @@ type
property ClientHeight: Cardinal read fClientHeight;

constructor Create(
const aSender: TControl;
const aControl: TControl;
const aEventType: TutlEventType;
const aScreenRect: TRect;
const aClientWidth: Cardinal;
@@ -152,6 +152,17 @@ type
EVENT_WINDOW_DEACTIVATE
];

public type
TutlEventType = uutlEventManager.TutlEventType;
TutlEventTypes = uutlEventManager.TutlEventTypes;
TutlMouseButtons = uutlEventManager.TutlMouseButtons;

TutlWinControlEventArgs = uutlEventManager.TutlWinControlEventArgs;
TutlMouseEventArgs = uutlEventManager.TutlMouseEventArgs;
TutlMouseWheelEventArgs = uutlEventManager.TutlMouseWheelEventArgs;
TutlKeyEventArgs = uutlEventManager.TutlKeyEventArgs;
TutlWindowEventArgs = uutlEventManager.TutlWindowEventArgs;

private type
TKeyboardState = record
Modifiers: TShiftState;
@@ -170,6 +181,7 @@ type
ClientWidth: Integer;
ClientHeight: Integer;
end;

private
fKeyboard: TKeyboardState;
fMouse: TMouseState;
@@ -195,23 +207,24 @@ type
procedure RecordEvent(constref aEventArgs: IutlEventArgs); virtual;

function CreateMouseEventArgs(
aSender: TObject;
aControl: TControl;
aType: TutlEventType;
aButtons: TutlMouseButtons;
aClientPos: TPoint): TutlMouseEventArgs; virtual;
aClientPos: TPoint): IutlEventArgs; virtual;

function CreateMouseWheelEventArgs(
aSender: TObject;
aControl: TControl;
aDelta: Integer;
aClientPos: TPoint): TutlMouseWheelEventArgs; virtual;
aClientPos: TPoint): IutlEventArgs; virtual;

function CreateKeyEventArgs(
aSender: TObject; aType: TutlEventType;
aKey: Word): TutlKeyEventArgs; virtual;
aControl: TControl;
aType: TutlEventType;
aKey: Word): IutlEventArgs; virtual;

function CreateWindowEventArgs(
aSender: TObject;
aType: TutlEventType): TutlWindowEventArgs; virtual;
aControl: TControl;
aType: TutlEventType): IutlEventArgs; virtual;

public
property Keyboard: TKeyboardState read fKeyboard;
@@ -262,12 +275,12 @@ end;
//TutlMouseEventArgs/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlMouseEventArgs.Create(
const aSender: TControl;
const aControl: TControl;
const aEventType: TutlEventType;
const aButtons: TutlMouseButtons;
const aClientPos: TPoint);
begin
inherited Create(aSender, aEventType);
inherited Create(aControl, aEventType);
fButtons := aButtons;
fClientPos := aClientPos;
fScreenPos := Control.ClientToScreen(fClientPos);
@@ -277,13 +290,13 @@ end;
//TutlMouseWheelEventArgs////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlMouseWheelEventArgs.Create(
const aSender: TControl;
const aControl: TControl;
const aWheelDelta: Integer;
const aClientPos: TPoint);
begin
if (aWheelDelta < 0)
then inherited Create(aSender, TutlWinControlEventManager.EVENT_MOUSE_WHEEL_DOWN)
else inherited Create(aSender, TutlWinControlEventManager.EVENT_MOUSE_WHEEL_UP);
then inherited Create(aControl, TutlWinControlEventManager.EVENT_MOUSE_WHEEL_DOWN)
else inherited Create(aControl, TutlWinControlEventManager.EVENT_MOUSE_WHEEL_UP);
fWheelDelta := aWheelDelta;
fClientPos := aClientPos;
fScreenPos := Control.ClientToScreen(fClientPos);
@@ -293,12 +306,12 @@ end;
//TutlKeyEventArgs///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlKeyEventArgs.Create(
const aSender: TControl;
const aControl: TControl;
const aEventType: TutlEventType;
const aCharCode: WideChar;
const aKeyCode: Word);
begin
inherited Create(aSender, aEventType);
inherited Create(aControl, aEventType);
fCharCode := aCharCode;
fKeyCode := aKeyCode;
end;
@@ -307,13 +320,13 @@ end;
//TutlWindowEventArgs////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlWindowEventArgs.Create(
const aSender: TControl;
const aControl: TControl;
const aEventType: TutlEventType;
const aScreenRect: TRect;
const aClientWidth: Cardinal;
const aClientHeight: Cardinal);
begin
inherited Create(aSender, aEventType);
inherited Create(aControl, aEventType);
fScreenRect := aScreenRect;
fClientWidth := aClientWidth;
fClientHeight := aClientHeight;
@@ -325,82 +338,81 @@ end;
procedure TutlWinControlEventManager.HandlerMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
DispatchEvent(self, CreateMouseEventArgs(Sender, EVENT_MOUSE_DOWN, [ Button ], Point(X, Y)));
DispatchEvent(self, CreateMouseEventArgs(Sender as TControl, EVENT_MOUSE_DOWN, [Button], Point(X, Y)));
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlWinControlEventManager.HandlerMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure TutlWinControlEventManager.HandlerMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
DispatchEvent(self, CreateMouseEventArgs(Sender, EVENT_MOUSE_UP, [Button], Point(X, Y)));
DispatchEvent(self, CreateMouseEventArgs(Sender as TControl, EVENT_MOUSE_UP, [Button], Point(X, Y)));
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlWinControlEventManager.HandlerMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
DispatchEvent(self, CreateMouseEventArgs(Sender, EVENT_MOUSE_MOVE, [], Point(X, Y)));
DispatchEvent(self, CreateMouseEventArgs(Sender as TControl, EVENT_MOUSE_MOVE, [], Point(X, Y)));
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlWinControlEventManager.HandlerMouseEnter(Sender: TObject);
begin
DispatchEvent(self, CreateMouseEventArgs(Sender, EVENT_MOUSE_ENTER, [], TControl(Sender).ScreenToClient(Controls.Mouse.CursorPos)));
DispatchEvent(self, CreateMouseEventArgs(Sender as TControl, EVENT_MOUSE_ENTER, [], TControl(Sender).ScreenToClient(Controls.Mouse.CursorPos)));
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlWinControlEventManager.HandlerMouseLeave(Sender: TObject);
begin
DispatchEvent(self, CreateMouseEventArgs(Sender, EVENT_MOUSE_LEAVE, [], TControl(Sender).ScreenToClient(Controls.Mouse.CursorPos)));
DispatchEvent(self, CreateMouseEventArgs(Sender as TControl, EVENT_MOUSE_LEAVE, [], TControl(Sender).ScreenToClient(Controls.Mouse.CursorPos)));
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlWinControlEventManager.HandlerClick(Sender: TObject);
begin
DispatchEvent(self, CreateMouseEventArgs(Sender, EVENT_MOUSE_CLICK, [], TControl(Sender).ScreenToClient(Controls.Mouse.CursorPos)));
DispatchEvent(self, CreateMouseEventArgs(Sender as TControl, EVENT_MOUSE_CLICK, [], TControl(Sender).ScreenToClient(Controls.Mouse.CursorPos)));
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlWinControlEventManager.HandlerDblClick(Sender: TObject);
begin
DispatchEvent(self, CreateMouseEventArgs(Sender, EVENT_MOUSE_DBL_CLICK, [], TControl(Sender).ScreenToClient(Controls.Mouse.CursorPos)));
DispatchEvent(self, CreateMouseEventArgs(Sender as TControl, EVENT_MOUSE_DBL_CLICK, [], TControl(Sender).ScreenToClient(Controls.Mouse.CursorPos)));
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlWinControlEventManager.HandlerMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
begin
DispatchEvent(self, CreateMouseWheelEventArgs(Sender, WheelDelta, MousePos));
DispatchEvent(self, CreateMouseWheelEventArgs(Sender as TControl, WheelDelta, MousePos));
Handled := false;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlWinControlEventManager.HandlerKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
DispatchEvent(self, CreateKeyEventArgs(Sender, EVENT_KEY_DOWN, Key));
DispatchEvent(self, CreateKeyEventArgs(Sender as TControl, EVENT_KEY_DOWN, Key));
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlWinControlEventManager.HandlerKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
DispatchEvent(self, CreateKeyEventArgs(Sender, EVENT_KEY_UP, Key));
DispatchEvent(self, CreateKeyEventArgs(Sender as TControl, EVENT_KEY_UP, Key));
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlWinControlEventManager.HandlerResize(Sender: TObject);
begin
DispatchEvent(self, CreateWindowEventArgs(Sender, EVENT_WINDOW_RESIZE));
DispatchEvent(self, CreateWindowEventArgs(Sender as TControl, EVENT_WINDOW_RESIZE));
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlWinControlEventManager.HandlerActivate(Sender: TObject);
begin
DispatchEvent(self, CreateWindowEventArgs(Sender, EVENT_WINDOW_ACTIVATE));
DispatchEvent(self, CreateWindowEventArgs(Sender as TControl, EVENT_WINDOW_ACTIVATE));
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlWinControlEventManager.HandlerDeactivate(Sender: TObject);
begin
DispatchEvent(self, CreateWindowEventArgs(Sender, EVENT_WINDOW_DEACTIVATE));
DispatchEvent(self, CreateWindowEventArgs(Sender as TControl, EVENT_WINDOW_DEACTIVATE));
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -480,53 +492,63 @@ begin
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlWinControlEventManager.CreateMouseEventArgs(aSender: TObject; aType: TutlEventType;
aButtons: TutlMouseButtons; aClientPos: TPoint): TutlMouseEventArgs;
function TutlWinControlEventManager.CreateMouseEventArgs(
aControl: TControl;
aType: TutlEventType;
aButtons: TutlMouseButtons;
aClientPos: TPoint): IutlEventArgs;
begin
result := TutlMouseEventArgs.Create(
(aSender as TControl),
aControl,
aType,
aButtons,
aClientPos);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlWinControlEventManager.CreateMouseWheelEventArgs(aSender: TObject; aDelta: Integer;
aClientPos: TPoint): TutlMouseWheelEventArgs;
function TutlWinControlEventManager.CreateMouseWheelEventArgs(
aControl: TControl;
aDelta: Integer;
aClientPos: TPoint): IutlEventArgs;
begin
result := TutlMouseWheelEventArgs.Create(
(aSender as TControl),
aControl,
aDelta,
aClientPos);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlWinControlEventManager.CreateKeyEventArgs(aSender: TObject; aType: TutlEventType; aKey: Word): TutlKeyEventArgs;
function TutlWinControlEventManager.CreateKeyEventArgs(
aControl: TControl;
aType: TutlEventType;
aKey: Word): IutlEventArgs;
begin
if (aType = EVENT_KEY_DOWN) and fKeyboard.KeyState[aKey and $FF] then
aType := EVENT_KEY_REPEAT;
result := TutlKeyEventArgs.Create(
(aSender as TControl),
aControl,
aType,
VKCodeToCharCode(aKey, fKeyboard.Modifiers),
aKey);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlWinControlEventManager.CreateWindowEventArgs(aSender: TObject; aType: TutlEventType): TutlWindowEventArgs;
function TutlWinControlEventManager.CreateWindowEventArgs(
aControl: TControl;
aType: TutlEventType): IutlEventArgs;
var
p0, p1: TPoint;
begin
with TControl(aSender) do begin
with aControl do begin
p0 := ClientToScreen(Point(0, 0));
p1 := ClientToScreen(Point(Width, Height));
end;
result := TutlWindowEventArgs.Create(
(aSender as TControl),
aControl,
aType,
Rect(p0.x, p0.y, p1.x, p1.y),
(aSender as TWinControl).ClientWidth,
(aSender as TWinControl).ClientHeight);
(aControl as TWinControl).ClientWidth,
(aControl as TWinControl).ClientHeight);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 1
- 1
uutlGenerics.pas View File

@@ -1492,6 +1492,7 @@ end;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TutlCustomMap.Destroy;
begin
Clear;
FreeAndNil(fKeyValuePairCollection);
FreeAndNil(fKeyCollection);
fHashSetRef := nil;
@@ -1510,7 +1511,6 @@ end;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TutlMap.Destroy;
begin
Clear;
inherited Destroy;
FreeAndNil(fHashSetImpl);
end;


+ 98
- 48
uutlMCF.pas View File

@@ -89,17 +89,27 @@ type
procedure DeleteSection(Name: string);

function ValueExists(Name: string): boolean;
function GetInt(Name: string; Default: Int64 = 0): Int64; overload;
function GetFloat(Name: string; Default: Double = 0): Double; overload;
function GetString(Name: string; Default: AnsiString = ''): AnsiString; overload;
function GetStringW(Name: string; Default: UnicodeString = ''): UnicodeString; overload;
function GetBool(Name: string; Default: Boolean = false): Boolean; overload;
procedure SetInt(Name: string; Value: Int64); overload;
procedure SetFloat(Name: string; Value: Double); overload;
procedure SetString(Name: string; Value: WideString); overload;
procedure SetString(Name: string; Value: AnsiString); overload;
procedure SetBool(Name: string; Value: Boolean); overload;
procedure UnsetValue(Name: string);

function GetValue (Name: String; Default: Variant): Variant;
function GetInt (Name: string; Default: Int64 = 0): Int64; overload;
function GetFloat (Name: string; Default: Double = 0): Double; overload;
function GetString (Name: string; Default: AnsiString = ''): AnsiString; overload;
function GetStringW (Name: string; Default: UnicodeString = ''): UnicodeString; overload;
function GetBool (Name: string; Default: Boolean = false): Boolean; overload;

function TryGetValue (aName: String; out aValue: Variant): Boolean;
function TryGetInt (aName: String; out aValue: Int64): Boolean;
function TryGetFloat (aName: String; out aValue: Double): Boolean;
function TryGetString (aName: String; out aValue: AnsiString): Boolean;
function TryGetStringW(aName: String; out aValue: UnicodeString): Boolean;
function TryGetBool (aName: String; out aValue: Boolean): Boolean;

procedure SetInt (Name: string; Value: Int64); overload;
procedure SetFloat (Name: string; Value: Double); overload;
procedure SetString (Name: string; Value: WideString); overload;
procedure SetString (Name: string; Value: AnsiString); overload;
procedure SetBool (Name: string; Value: Boolean); overload;
end;

{ TutlMCFFile }
@@ -426,55 +436,107 @@ begin
Result:= FValues.IndexOf(Name) >= 0;
end;

function TutlMCFSection.GetInt(Name: string; Default: Int64): Int64;
procedure TutlMCFSection.UnsetValue(Name: string);
var
i: integer;
begin
i:= FValues.IndexOf(Name);
if i < 0 then
Result:= Default
else
Result:= TutlMCFValue(FValues.Objects[i]).Value;
if i >= 0 then begin
FValues.Objects[i].Free;
FValues.Delete(i);
end;
end;

function TutlMCFSection.GetValue(Name: String; Default: Variant): Variant;
begin
if not TryGetValue(Name, result) then
result := Default;
end;

function TutlMCFSection.GetInt(Name: string; Default: Int64): Int64;
begin
if not TryGetInt(Name, result) then
result := Default;
end;

function TutlMCFSection.GetFloat(Name: string; Default: Double): Double;
var
i: integer;
begin
i:= FValues.IndexOf(Name);
if i < 0 then
Result:= Default
else
Result:= TutlMCFValue(FValues.Objects[i]).Value;
if not TryGetFloat(Name, result) then
result := Default;
end;

function TutlMCFSection.GetStringW(Name: string; Default: UnicodeString): UnicodeString;
var
i: integer;
begin
i:= FValues.IndexOf(Name);
if i < 0 then
Result:= Default
else
Result:= TutlMCFValue(FValues.Objects[i]).Value;
if not TryGetStringW(Name, result) then
result := Default;
end;

function TutlMCFSection.GetString(Name: string; Default: AnsiString): AnsiString;
begin
Result := AnsiString(GetStringW(Name, UnicodeString(Default)));
if not TryGetString(Name, result) then
result := Default;
end;

function TutlMCFSection.GetBool(Name: string; Default: Boolean): Boolean;
begin
if not TryGetBool(Name, result) then
result := Default;
end;

function TutlMCFSection.TryGetValue(aName: String; out aValue: Variant): Boolean;
var
i: integer;
i: Integer;
begin
i:= FValues.IndexOf(Name);
if i < 0 then
Result:= Default
else
Result:= TutlMCFValue(FValues.Objects[i]).Value;
i := FValues.IndexOf(aName);
result := (i >= 0);
if result then
aValue := TutlMcfValue(FValues.Objects[i]).Value;
end;

function TutlMCFSection.TryGetInt(aName: String; out aValue: Int64): Boolean;
var
v: Variant;
begin
result := TryGetValue(aName, v);
if result then
aValue := v;
end;

function TutlMCFSection.TryGetFloat(aName: String; out aValue: Double): Boolean;
var
v: Variant;
begin
result := TryGetValue(aName, v);
if result then
aValue := v;
end;

function TutlMCFSection.TryGetString(aName: String; out aValue: AnsiString): Boolean;
var
v: Variant;
begin
result := TryGetValue(aName, v);
if result then
aValue := v;
end;

function TutlMCFSection.TryGetStringW(aName: String; out aValue: UnicodeString): Boolean;
var
v: Variant;
begin
result := TryGetValue(aName, v);
if result then
aValue := v;
end;

function TutlMCFSection.TryGetBool(aName: String; out aValue: Boolean): Boolean;
var
v: Variant;
begin
result := TryGetValue(aName, v);
if result then
aValue := v;
end;

procedure TutlMCFSection.AddValueChecked(Name: String; Val: TObject);
var
@@ -540,18 +602,6 @@ begin
TutlMCFValue(FValues.Objects[i]).Value:= Value;
end;

procedure TutlMCFSection.UnsetValue(Name: string);
var
i: integer;
begin
i:= FValues.IndexOf(Name);
if i >= 0 then begin
FValues.Objects[i].Free;
FValues.Delete(i);
end;
end;


procedure TutlMCFSection.LoadData(Data: TStream; LineEnds: TutlMCFLineEndMarkerMode; Depth: Integer);
var
reader: TutlStreamReader;


+ 74
- 25
uutlObservable.pas View File

@@ -307,30 +307,46 @@ end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomList.DoAddItem(const aIndex: Integer; constref aItem: T);
var
e: IutlEventArgs;
begin
if Assigned(fEventListener) and not fEventListener.IsEmpty then
fEventListener.DispatchEvent(self, TItemEventArgs.Create(oetAdd, aIndex, aItem));
if Assigned(fEventListener) and not fEventListener.IsEmpty then begin
e := TItemEventArgs.Create(oetAdd, aIndex, aItem);
fEventListener.DispatchEvent(self, e);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomList.DoRemoveItem(const aIndex: Integer; constref aItem: T);
var
e: IutlEventArgs;
begin
if Assigned(fEventListener) and not fEventListener.IsEmpty then
fEventListener.DispatchEvent(self, TItemEventArgs.Create(oetRemove, aIndex, aItem));
if Assigned(fEventListener) and not fEventListener.IsEmpty then begin
e := TItemEventArgs.Create(oetRemove, aIndex, aItem);
fEventListener.DispatchEvent(self, e);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomList.DoChangeItem(const aIndex: Integer; constref aOldItem: T; constref aNewItem: T);
var
e: IutlEventArgs;
begin
if Assigned(fEventListener) and not fEventListener.IsEmpty then
fEventListener.DispatchEvent(self, TReplaceEventArgs.Create(oetReplace, aIndex, aOldItem, aNewItem));
if Assigned(fEventListener) and not fEventListener.IsEmpty then begin
e := TReplaceEventArgs.Create(oetReplace, aIndex, aOldItem, aNewItem);
fEventListener.DispatchEvent(self, e);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomList.DoClear;
var
e: IutlEventArgs;
begin
if Assigned(fEventListener) and not fEventListener.IsEmpty then
fEventListener.DispatchEvent(self, TutlObservableEventArgs.Create(oetClear));
if Assigned(fEventListener) and not fEventListener.IsEmpty then begin
e := TutlObservableEventArgs.Create(oetClear);
fEventListener.DispatchEvent(self, e);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -431,30 +447,46 @@ end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.DoAddItem(const aIndex: Integer; constref aItem: T);
var
e: IutlEventArgs;
begin
if Assigned(fEventListener) and not fEventListener.IsEmpty then
fEventListener.DispatchEvent(self, TItemEventArgs.Create(oetAdd, aIndex, aItem));
if Assigned(fEventListener) and not fEventListener.IsEmpty then begin
e := TItemEventArgs.Create(oetAdd, aIndex, aItem);
fEventListener.DispatchEvent(self, e);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.DoRemoveItem(const aIndex: Integer; constref aItem: T);
var
e: IutlEventArgs;
begin
if Assigned(fEventListener) and not fEventListener.IsEmpty then
fEventListener.DispatchEvent(self, TItemEventArgs.Create(oetRemove, aIndex, aItem));
if Assigned(fEventListener) and not fEventListener.IsEmpty then begin
e := TItemEventArgs.Create(oetRemove, aIndex, aItem);
fEventListener.DispatchEvent(self, e);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.DoChangeItem(const aIndex: Integer; constref aOldItem: T; constref aNewItem: T);
var
e: IutlEventArgs;
begin
if Assigned(fEventListener) and not fEventListener.IsEmpty then
fEventListener.DispatchEvent(self, TReplaceEventArgs.Create(oetReplace, aIndex, aOldItem, aNewItem));
if Assigned(fEventListener) and not fEventListener.IsEmpty then begin
e := TReplaceEventArgs.Create(oetReplace, aIndex, aOldItem, aNewItem);
fEventListener.DispatchEvent(self, e);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.DoClear;
var
e: IutlEventArgs;
begin
if Assigned(fEventListener) and not fEventListener.IsEmpty then
fEventListener.DispatchEvent(self, TutlObservableEventArgs.Create(oetClear));
if Assigned(fEventListener) and not fEventListener.IsEmpty then begin
e := TutlObservableEventArgs.Create(oetClear);
fEventListener.DispatchEvent(self, e);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -528,7 +560,8 @@ end;
procedure TutlObservableCustomMap.TObservableHashSet.Clear;
begin
fOwner.DoClear;
inherited Clear;
while (Count > 0) do
Delete(Count - 1);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -576,9 +609,13 @@ procedure TutlObservableCustomMap.DoAddItem(
const aIndex: Integer;
constref aKey: TKey;
constref aItem: TValue);
var
e: IutlEventArgs;
begin
if Assigned(fEventListener) and not fEventListener.IsEmpty then
fEventListener.DispatchEvent(self, TItemEventArgs.Create(oetAdd, aIndex, aKey, aItem));
if Assigned(fEventListener) and not fEventListener.IsEmpty then begin
e := TItemEventArgs.Create(oetAdd, aIndex, aKey, aItem);
fEventListener.DispatchEvent(self, e);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -586,9 +623,13 @@ procedure TutlObservableCustomMap.DoRemoveItem(
const aIndex: Integer;
constref aKey: TKey;
constref aItem: TValue);
var
e: IutlEventArgs;
begin
if Assigned(fEventListener) and not fEventListener.IsEmpty then
fEventListener.DispatchEvent(self, TItemEventArgs.Create(oetRemove, aIndex, aKey, aItem));
if Assigned(fEventListener) and not fEventListener.IsEmpty then begin
e := TItemEventArgs.Create(oetRemove, aIndex, aKey, aItem);
fEventListener.DispatchEvent(self, e);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -597,16 +638,24 @@ procedure TutlObservableCustomMap.DoChangeItem(
constref aKey: TKey;
constref aOldItem: TValue;
constref aNewItem: TValue);
var
e: IutlEventArgs;
begin
if Assigned(fEventListener) and not fEventListener.IsEmpty then
fEventListener.DispatchEvent(self, TReplaceEventArgs.Create(oetReplace, aIndex, aKey, aOldItem, aNewItem));
if Assigned(fEventListener) and not fEventListener.IsEmpty then begin
e := TReplaceEventArgs.Create(oetReplace, aIndex, aKey, aOldItem, aNewItem);
fEventListener.DispatchEvent(self, e);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomMap.DoClear;
var
e: IutlEventArgs;
begin
if Assigned(fEventListener) and not fEventListener.IsEmpty then
fEventListener.DispatchEvent(self, TutlObservableEventArgs.Create(oetClear));
if Assigned(fEventListener) and not fEventListener.IsEmpty then begin
e := TutlObservableEventArgs.Create(oetClear);
fEventListener.DispatchEvent(self, e);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 12
- 0
uutlSyncObjs.pas View File

@@ -112,15 +112,21 @@ type
TInterfacedObject,
specialize IutlLock<T>)

public type
ILock = specialize IutlLock<T>;

private
fLock: IutlLockable;
fObject: T;


public
function LockedObject: T; inline;

constructor Create(constref aLock: IutlLockable; constref aObject: T);
destructor Destroy; override;

class function CreateLock(constref aLock: IutlLockable; constref aObject: T): ILock;
end;

implementation
@@ -359,5 +365,11 @@ begin
inherited Destroy;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TutlLock.CreateLock(constref aLock: IutlLockable; constref aObject: T): ILock;
begin
result := TutlLock.Create(aLock, aObject);
end;

end.


+ 175
- 85
uutlXmlHelper.pas View File

@@ -75,6 +75,14 @@ type
function GetAttribFloat (const aName: DOMString; const aDefault: Double): Double;
function GetAttribBool (const aName: DOMString; const aDefault: Boolean): Boolean;

// get value of attribute
function TryGetAttribString (const aName: DOMString; out aValue: String): Boolean;
function TryGetAttribStringW (const aName: DOMString; out aValue: WideString): Boolean;
function TryGetAttribStringU (const aName: DOMString; out aValue: UnicodeString): Boolean;
function TryGetAttribInt (const aName: DOMString; out aValue: Int64): Boolean;
function TryGetAttribFloat (const aName: DOMString; out aValue: Double): Boolean;
function TryGetAttribBool (const aName: DOMString; out aValue: Boolean): Boolean;

// node operations
function Nodes (const aName: DOMString): IutlNodeEnumerator;
function PrependNode (const aName: DOMString): TDOMElement;
@@ -109,43 +117,51 @@ type
function GetElement: TDOMElement;

// set value of current node
procedure SetString (const aValue: String); overload;
procedure SetString (const aValue: WideString); overload;
procedure SetString (const aValue: UnicodeString); overload;
procedure SetInt (const aValue: Integer);
procedure SetFloat (const aValue: Double);
procedure SetBool (const aValue: Boolean);
procedure SetString (const aValue: String); overload;
procedure SetString (const aValue: WideString); overload;
procedure SetString (const aValue: UnicodeString); overload;
procedure SetInt (const aValue: Integer);
procedure SetFloat (const aValue: Double);
procedure SetBool (const aValue: Boolean);

// get value of current node
function GetString (const aDefault: String): String;
function GetStringW (const aDefault: WideString): WideString;
function GetStringU (const aDefault: UnicodeString): UnicodeString;
function GetInt (const aDefault: Int64): Int64;
function GetFloat (const aDefault: Double): Double;
function GetBool (const aDefault: Boolean): Boolean;
function GetString (const aDefault: String): String;
function GetStringW (const aDefault: WideString): WideString;
function GetStringU (const aDefault: UnicodeString): UnicodeString;
function GetInt (const aDefault: Int64): Int64;
function GetFloat (const aDefault: Double): Double;
function GetBool (const aDefault: Boolean): Boolean;

// set value of attribute
procedure SetAttribString (const aName: DOMString; const aValue: String); overload;
procedure SetAttribString (const aName: DOMString; const aValue: WideString); overload;
procedure SetAttribString (const aName: DOMString; const aValue: UnicodeString); overload;
procedure SetAttribInt (const aName: DOMString; const aValue: Integer);
procedure SetAttribFloat (const aName: DOMString; const aValue: Double);
procedure SetAttribBool (const aName: DOMString; const aValue: Boolean);
procedure SetAttribString (const aName: DOMString; const aValue: String); overload;
procedure SetAttribString (const aName: DOMString; const aValue: WideString); overload;
procedure SetAttribString (const aName: DOMString; const aValue: UnicodeString); overload;
procedure SetAttribInt (const aName: DOMString; const aValue: Integer);
procedure SetAttribFloat (const aName: DOMString; const aValue: Double);
procedure SetAttribBool (const aName: DOMString; const aValue: Boolean);

// get value of attribute
function GetAttribString (const aName: DOMString; const aDefault: String): String;
function GetAttribStringW (const aName: DOMString; const aDefault: WideString): WideString;
function GetAttribStringU (const aName: DOMString; const aDefault: UnicodeString): UnicodeString;
function GetAttribInt (const aName: DOMString; const aDefault: Int64): Int64;
function GetAttribFloat (const aName: DOMString; const aDefault: Double): Double;
function GetAttribBool (const aName: DOMString; const aDefault: Boolean): Boolean;
function GetAttribString (const aName: DOMString; const aDefault: String): String;
function GetAttribStringW (const aName: DOMString; const aDefault: WideString): WideString;
function GetAttribStringU (const aName: DOMString; const aDefault: UnicodeString): UnicodeString;
function GetAttribInt (const aName: DOMString; const aDefault: Int64): Int64;
function GetAttribFloat (const aName: DOMString; const aDefault: Double): Double;
function GetAttribBool (const aName: DOMString; const aDefault: Boolean): Boolean;

// get value of attribute
function TryGetAttribString (const aName: DOMString; out aValue: String): Boolean;
function TryGetAttribStringW(const aName: DOMString; out aValue: WideString): Boolean;
function TryGetAttribStringU(const aName: DOMString; out aValue: UnicodeString): Boolean;
function TryGetAttribInt (const aName: DOMString; out aValue: Int64): Boolean;
function TryGetAttribFloat (const aName: DOMString; out aValue: Double): Boolean;
function TryGetAttribBool (const aName: DOMString; out aValue: Boolean): Boolean;

// node operations
function Nodes (const aName: DOMString): IutlNodeEnumerator;
function PrependNode (const aName: DOMString): TDOMElement;
function AppendNode (const aName: DOMString): TDOMElement;
procedure PrependText (const aText: DOMString);
procedure AppendText (const aText: DOMString);
function Nodes (const aName: DOMString): IutlNodeEnumerator;
function PrependNode (const aName: DOMString): TDOMElement;
function AppendNode (const aName: DOMString): TDOMElement;
procedure PrependText (const aText: DOMString);
procedure AppendText (const aText: DOMString);

private
{%H-}constructor Create; reintroduce;
@@ -155,25 +171,32 @@ type
class function Create(const aElement: TDOMElement): IutlXmlHelper;

public
class function SetString (const aNode: TDOMNode; const aValue: String): TDOMNode; overload;
class function SetString (const aNode: TDOMNode; const aValue: WideString): TDOMNode; overload;
class function SetString (const aNode: TDOMNode; const aValue: UnicodeString): TDOMNode; overload;
class function SetInt (const aNode: TDOMNode; const aValue: Integer): TDOMNode;
class function SetFloat (const aNode: TDOMNode; const aValue: Double): TDOMNode;
class function SetBool (const aNode: TDOMNode; const aValue: Boolean): TDOMNode;

class function GetString (const aNode: TDOMNode; const aDefault: String): String;
class function GetStringW (const aNode: TDOMNode; const aDefault: WideString): WideString;
class function GetStringU (const aNode: TDOMNode; const aDefault: UnicodeString): UnicodeString;
class function GetInt (const aNode: TDOMNode; const aDefault: Int64): Int64;
class function GetFloat (const aNode: TDOMNode; const aDefault: Double): Double;
class function GetBool (const aNode: TDOMNode; const aDefault: Boolean): Boolean;

class function Nodes (const aElement: TDOMElement; const aName: DOMString = ''): IutlNodeEnumerator;
class function PrependNode (const aElement: TDOMElement; const aName: DOMString): TDOMElement;
class function AppendNode (const aElement: TDOMElement; const aName: DOMString): TDOMElement;
class procedure PrependText (const aElement: TDOMElement; const aText: DOMString);
class procedure AppendText (const aElement: TDOMElement; const aText: DOMString);
class function SetString (const aNode: TDOMNode; const aValue: String): TDOMNode; overload;
class function SetString (const aNode: TDOMNode; const aValue: WideString): TDOMNode; overload;
class function SetString (const aNode: TDOMNode; const aValue: UnicodeString): TDOMNode; overload;
class function SetInt (const aNode: TDOMNode; const aValue: Integer): TDOMNode;
class function SetFloat (const aNode: TDOMNode; const aValue: Double): TDOMNode;
class function SetBool (const aNode: TDOMNode; const aValue: Boolean): TDOMNode;

class function GetString (const aNode: TDOMNode; const aDefault: String): String;
class function GetStringW (const aNode: TDOMNode; const aDefault: WideString): WideString;
class function GetStringU (const aNode: TDOMNode; const aDefault: UnicodeString): UnicodeString;
class function GetInt (const aNode: TDOMNode; const aDefault: Int64): Int64;
class function GetFloat (const aNode: TDOMNode; const aDefault: Double): Double;
class function GetBool (const aNode: TDOMNode; const aDefault: Boolean): Boolean;

class function TryGetString (const aNode: TDOMNode; out aValue: String): Boolean;
class function TryGetStringW(const aNode: TDOMNode; out aValue: WideString): Boolean;
class function TryGetStringU(const aNode: TDOMNode; out aValue: UnicodeString): Boolean;
class function TryGetInt (const aNode: TDOMNode; out aValue: Int64): Boolean;
class function TryGetFloat (const aNode: TDOMNode; out aValue: Double): Boolean;
class function TryGetBool (const aNode: TDOMNode; out aValue: Boolean): Boolean;

class function Nodes (const aElement: TDOMElement; const aName: DOMString = ''): IutlNodeEnumerator;
class function PrependNode (const aElement: TDOMElement; const aName: DOMString): TDOMElement;
class function AppendNode (const aElement: TDOMElement; const aName: DOMString): TDOMElement;
class procedure PrependText (const aElement: TDOMElement; const aText: DOMString);
class procedure AppendText (const aElement: TDOMElement; const aText: DOMString);
end;

implementation
@@ -382,6 +405,42 @@ begin
result := TutlXmlHelper.GetBool(fElement.Attributes.GetNamedItem(aName), aDefault);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlXmlHelper.TryGetAttribString(const aName: DOMString; out aValue: String): Boolean;
begin
result := TutlXmlHelper.TryGetString(fElement.Attributes.GetNamedItem(aName), aValue);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlXmlHelper.TryGetAttribStringW(const aName: DOMString; out aValue: WideString): Boolean;
begin
result := TutlXmlHelper.TryGetStringW(fElement.Attributes.GetNamedItem(aName), aValue);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlXmlHelper.TryGetAttribStringU(const aName: DOMString; out aValue: UnicodeString): Boolean;
begin
result := TutlXmlHelper.TryGetStringU(fElement.Attributes.GetNamedItem(aName), aValue);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlXmlHelper.TryGetAttribInt(const aName: DOMString; out aValue: Int64): Boolean;
begin
result := TutlXmlHelper.TryGetInt(fElement.Attributes.GetNamedItem(aName), aValue);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlXmlHelper.TryGetAttribFloat(const aName: DOMString; out aValue: Double): Boolean;
begin
result := TutlXmlHelper.TryGetFloat(fElement.Attributes.GetNamedItem(aName), aValue);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlXmlHelper.TryGetAttribBool(const aName: DOMString; out aValue: Boolean): Boolean;
begin
result := TutlXmlHelper.TryGetBool(fElement.Attributes.GetNamedItem(aName), aValue);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlXmlHelper.Nodes(const aName: DOMString): IutlNodeEnumerator;
begin
@@ -486,73 +545,104 @@ end;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TutlXmlHelper.GetString(const aNode: TDOMNode; const aDefault: String): String;
begin
if not Assigned(aNode)
or ( not aNode.HasChildNodes
and not (aNode is TDOMText))
then result := aDefault
else result := String(aNode.TextContent);
if not TryGetString(aNode, result) then
result := aDefault;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TutlXmlHelper.GetStringW(const aNode: TDOMNode; const aDefault: WideString): WideString;
begin
if not Assigned(aNode)
or ( not aNode.HasChildNodes
and not (aNode is TDOMText))
then result := aDefault
else result := WideString(aNode.TextContent);
if not TryGetStringW(aNode, result) then
result := aDefault;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TutlXmlHelper.GetStringU(const aNode: TDOMNode; const aDefault: UnicodeString): UnicodeString;
begin
if not Assigned(aNode)
or ( not aNode.HasChildNodes
and not (aNode is TDOMText))
then result := aDefault
else result := UnicodeString(aNode.TextContent);
if not TryGetStringU(aNode, result) then
result := aDefault;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TutlXmlHelper.GetInt(const aNode: TDOMNode; const aDefault: Int64): Int64;
begin
if not Assigned(aNode)
or ( not aNode.HasChildNodes
and not (aNode is TDOMText))
or not TryStrToInt64(String(aNode.TextContent), result) then
if not TryGetInt(aNode, result) then
result := aDefault;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TutlXmlHelper.GetFloat(const aNode: TDOMNode; const aDefault: Double): Double;
begin
if not Assigned(aNode)
or ( not aNode.HasChildNodes
and not (aNode is TDOMText))
or not TryStrToFloat(String(aNode.TextContent), result) then
if not TryGetFloat(aNode, result) then
result := aDefault;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TutlXmlHelper.GetBool(const aNode: TDOMNode; const aDefault: Boolean): Boolean;
begin
if not TryGetBool(aNode, result) then
result := aDefault;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TutlXmlHelper.TryGetString(const aNode: TDOMNode; out aValue: String): Boolean;
begin
result := Assigned(aNode)
and ( aNode.HasChildNodes
or (aNode is TDOMText));
if result then
aValue := String(aNode.TextContent);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TutlXmlHelper.TryGetStringW(const aNode: TDOMNode; out aValue: WideString): Boolean;
begin
result := Assigned(aNode)
and ( aNode.HasChildNodes
or (aNode is TDOMText));
if result then
aValue := WideString(aNode.TextContent);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TutlXmlHelper.TryGetStringU(const aNode: TDOMNode; out aValue: UnicodeString): Boolean;
begin
result := Assigned(aNode)
and ( aNode.HasChildNodes
or (aNode is TDOMText));
if result then
aValue := UnicodeString(aNode.TextContent);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TutlXmlHelper.TryGetInt(const aNode: TDOMNode; out aValue: Int64): Boolean;
begin
result := Assigned(aNode)
and ( aNode.HasChildNodes
or (aNode is TDOMText))
and TryStrToInt64(String(aNode.TextContent), aValue);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TutlXmlHelper.TryGetFloat(const aNode: TDOMNode; out aValue: Double): Boolean;
begin
result := Assigned(aNode)
and ( aNode.HasChildNodes
or (aNode is TDOMText))
and TryStrToFloat(String(aNode.TextContent), aValue);
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TutlXmlHelper.TryGetBool(const aNode: TDOMNode; out aValue: Boolean): Boolean;
var
s: String;
begin
if not Assigned(aNode)
or ( not aNode.HasChildNodes
and not (aNode is TDOMText))
then
begin
result := aDefault;
exit;
result := TryGetString(aNode, s);
if result then begin
if (s = 'true') or (s = 't') or (s = '1')
then aValue := true
else aValue := false;
end;
s := LowerCase(String(aNode.TextContent));
if (s = 'true') or (s = 't') or (s = '1') then
result := true
else if (s = 'false') or (s = 'f') or (s = '0') then
result := false
else
result := aDefault;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


Loading…
Cancel
Save