TDurationRemotable implementation and tests

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@530 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
inoussa 2008-08-18 14:49:20 +00:00
parent 1a7f321de7
commit 1e53041c77
2 changed files with 713 additions and 10 deletions

View File

@ -350,10 +350,46 @@ type
property Second : Integer read FSecond;
end;
TDurationRemotable = class(TBaseDateRemotable)
protected
//class function FormatDate(const ADate : TDateTime):string;override;
//class function ParseDate(const ABuffer : string):TDateTime;override;
{ TDurationRemotable }
TDurationRemotable = class(TAbstractSimpleRemotable)
private
FDay : PtrUInt;
FFractionalSecond : PtrUInt;
FHour : PtrUInt;
FMinute : PtrUInt;
FMonth : PtrUInt;
FNegative : Boolean;
FSecond : PtrUInt;
FYear : PtrUInt;
public
class procedure Save(
AObject : TBaseRemotable;
AStore : IFormatterBase;
const AName : string;
const ATypeInfo : PTypeInfo
);override;
class procedure Load(
var AObject : TObject;
AStore : IFormatterBase;
var AName : string;
const ATypeInfo : PTypeInfo
);override;
procedure Assign(Source: TPersistent); override;
function Equal(const ACompareTo : TBaseRemotable) : Boolean;override;
procedure Clear();
procedure Parse(const ABuffer : string);
function AsString() : string;
property Negative : Boolean read FNegative write FNegative;
property Year : PtrUInt read FYear write FYear;
property Month : PtrUInt read FMonth write FMonth;
property Day : PtrUInt read FDay write FDay;
property Hour : PtrUInt read FHour write FHour;
property Minute : PtrUInt read FMinute write FMinute;
property Second : PtrUInt read FSecond write FSecond;
property FractionalSecond : PtrUInt read FFractionalSecond write FFractionalSecond;
end;
TTimeRemotable = class(TBaseDateRemotable)
@ -5710,6 +5746,223 @@ begin
end;
{ TDurationRemotable }
class procedure TDurationRemotable.Save(
AObject : TBaseRemotable;
AStore : IFormatterBase;
const AName : string;
const ATypeInfo : PTypeInfo
);
var
buffer : string;
begin
buffer := TDurationRemotable(AObject).AsString();
AStore.BeginObject(AName,ATypeInfo);
try
AStore.PutScopeInnerValue(TypeInfo(string),buffer);
finally
AStore.EndScope();
end;
end;
class procedure TDurationRemotable.Load(
var AObject : TObject;
AStore : IFormatterBase;
var AName : string;
const ATypeInfo : PTypeInfo
);
var
strBuffer : string;
begin
if ( AStore.BeginObjectRead(AName,ATypeInfo) >= 0 ) then begin
try
strBuffer := '';
AStore.GetScopeInnerValue(TypeInfo(string),strBuffer);
TDurationRemotable(AObject).Parse(strBuffer);
finally
AStore.EndScopeRead();
end;
end;
end;
procedure TDurationRemotable.Assign(Source : TPersistent);
var
src : TDurationRemotable;
begin
if ( Source <> nil ) and Source.InheritsFrom(TDurationRemotable) then begin
src := TDurationRemotable(Source);
Self.FYear := src.FYear;
Self.FMonth := src.FMonth;
Self.FDay := src.FDay;
Self.FHour := src.FHour;
Self.FMinute := src.FMinute;
Self.FSecond := src.FSecond;
Self.FFractionalSecond := src.FFractionalSecond;
end else begin
inherited Assign(Source);
end;
end;
function TDurationRemotable.Equal(const ACompareTo : TBaseRemotable) : Boolean;
var
src : TDurationRemotable;
begin
if ( Self = ACompareTo ) then begin
Result := True;
end else begin
if ( ACompareTo <> nil ) and ACompareTo.InheritsFrom(TDurationRemotable) then begin
src := TDurationRemotable(ACompareTo);
Result := ( Self.FYear = src.FYear ) and
( Self.FMonth = src.FMonth ) and
( Self.FDay = src.FDay ) and
( Self.FHour = src.FHour ) and
( Self.FMinute = src.FMinute ) and
( Self.FSecond = src.FSecond ) and
( Self.FFractionalSecond = src.FFractionalSecond );
end else begin
Result := inherited Equal(ACompareTo);
end;
end;
end;
procedure TDurationRemotable.Clear();
begin
FYear := 0;
FMonth := 0;
FDay := 0;
FHour := 0;
FMinute := 0;
FSecond := 0;
FFractionalSecond := 0;
FNegative := False;
end;
type TDatePart = ( dpNone, dpYear, dpMonth, dpDay, dpHour, dpMinute, dpSecond, dpFractionalSecond );
procedure TDurationRemotable.Parse(const ABuffer : string);
procedure RaiseInvalidBuffer();{$IFDEF USE_INLINE}inline;{$ENDIF}
begin
raise EConvertError.CreateFmt('Invalid duration string : ',[ABuffer]);
end;
var
pc : PChar;
locIntBuffer : array[dpYear..dpFractionalSecond] of PtrUInt;
i, bufferLength, lastPos : PtrInt;
localBuffer : string;
part, oldPart : TDatePart;
inTimePart : Boolean;
isNeg : Boolean;
begin
bufferLength := Length(ABuffer);
if ( bufferLength < 3 ) then
RaiseInvalidBuffer();
pc := PChar(ABuffer);
i := 1;
isNeg := False;
if ( pc^ = '-' ) then begin
Inc(pc); Inc(i);
isNeg := True;
end;
if ( pc^ <> 'P' ) then
RaiseInvalidBuffer();
Inc(pc); Inc(i); //eat 'P'
FillChar(locIntBuffer,SizeOf(locIntBuffer),#0);
part := dpNone;
inTimePart := False;
if ( pc^ = 'T' ) then begin
inTimePart := True;
Inc(pc); Inc(i);
end;
repeat
lastPos := i;
while ( i < bufferLength ) and ( pc^ in ['0'..'9'] ) do begin
Inc(pc); Inc(i);
end;
if ( ( lastPos = i ) and ( pc^ <> 'T' ) ) then
RaiseInvalidBuffer();
localBuffer := Copy(ABuffer,lastPos,( i - lastPos ));
oldPart := part;
case pc^ of
'Y' : part := dpYear;
'M' :
begin
if inTimePart then
part := dpMinute
else
part := dpMonth;
end;
'D' : part := dpDay;
'H' : part := dpHour;
'S', '.' :
begin
if ( part < dpSecond ) then
part := dpSecond
else
part := dpFractionalSecond;
end;
'T' :
begin
inTimePart := True;
oldPart := dpNone;
part := dpNone;
end;
else
RaiseInvalidBuffer();
end;
if inTimePart and ( part in [dpYear..dpDay] ) then
RaiseInvalidBuffer();
if ( part > dpNone ) then begin
if ( part < oldPart ) then
RaiseInvalidBuffer();
locIntBuffer[part] := StrToInt(localBuffer);
end;
Inc(pc); Inc(i);
until ( i >= bufferLength );
if ( i = bufferLength ) then
RaiseInvalidBuffer();
FNegative := isNeg;
FYear := locIntBuffer[dpYear];
FMonth := locIntBuffer[dpMonth];
FDay := locIntBuffer[dpDay];
FHour := locIntBuffer[dpHour];
FMinute := locIntBuffer[dpMinute];
FSecond := locIntBuffer[dpSecond];
FFractionalSecond := locIntBuffer[dpFractionalSecond];
end;
function TDurationRemotable.AsString() : string;
var
strTime, strDate : string;
begin
if ( FractionalSecond > 0 ) then begin
strTime := IntToStr(Second) + '.' + IntToStr(FractionalSecond) + 'S';
end else begin
if ( Second > 0 ) then
strTime := IntToStr(Second) + 'S';
end;
if ( Minute > 0 ) then
strTime := IntToStr(Minute) + 'M' + strTime;
if ( Hour > 0 ) then
strTime := IntToStr(Hour) + 'H' + strTime;
if ( Day > 0 ) then
strDate := IntToStr(Day) + 'D';
if ( Month > 0 ) then
strDate := IntToStr(Month) + 'M' + strDate;
if ( Year > 0 ) then
strDate := IntToStr(Year) + 'Y' + strDate;
if ( strTime <> '' ) then
Result := 'T' + strTime;
Result := strDate + Result;
if ( Result = '' ) then
Result := '0Y';
Result := 'P' + Result;
if Negative and ( ( strDate <> '' ) or ( strTime <> '' ) ) then
Result := '-' + Result;
end;
initialization
initialize_base_service_intf();

View File

@ -311,8 +311,21 @@ type
TTest_TDurationRemotable = class(TTestCase)
published
procedure FormatDate();
procedure ParseDate();
procedure Clear();
procedure AsString_empty();
procedure AsString_not_empty();
procedure AsString_date_only();
procedure AsString_time_only();
procedure Parse_non_empty();
procedure Parse_time_only();
procedure Parse_zero();
procedure parse_negative();
procedure parse_invalid_1();
procedure parse_invalid_2();
procedure parse_invalid_3();
procedure parse_invalid_4();
procedure parse_invalid_5();
procedure parse_empty();
end;
{ TTest_TTimeRemotable }
@ -2258,14 +2271,451 @@ end;
{ TTest_TDurationRemotable }
procedure TTest_TDurationRemotable.FormatDate();
procedure TTest_TDurationRemotable.Clear();
var
x : TDurationRemotable;
begin
Fail('Write me!');
x := TDurationRemotable.Create();
try
x.Negative := True;
x.Year := 1;
x.Month := 2;
x.Day := 3;
x.Hour := 4;
x.Minute := 5;
x.Second := 6;
x.FractionalSecond := 7;
x.Clear();
CheckEquals(False,x.Negative);
CheckEquals(0,x.Year);
CheckEquals(0,x.Month);
CheckEquals(0,x.Day);
CheckEquals(0,x.Hour);
CheckEquals(0,x.Minute);
CheckEquals(0,x.Second);
CheckEquals(0,x.FractionalSecond);
finally
x.Free();
end;
end;
procedure TTest_TDurationRemotable.ParseDate();
procedure TTest_TDurationRemotable.AsString_empty();
var
x : TDurationRemotable;
begin
Fail('Write me!');
x := TDurationRemotable.Create();
try
CheckEquals('P0Y', x.AsString());
x.Negative := True;
CheckEquals('P0Y', x.AsString());
finally
x.Free();
end;
end;
procedure TTest_TDurationRemotable.AsString_not_empty();
var
x : TDurationRemotable;
begin
x := TDurationRemotable.Create();
try
x.Year := 1;
x.Month := 2;
x.Day := 3;
x.Hour := 4;
x.Minute := 5;
x.Second := 6;
CheckEquals('P1Y2M3DT4H5M6S',x.AsString());
x.FractionalSecond := 7;
CheckEquals('P1Y2M3DT4H5M6.7S',x.AsString());
x.Negative := True;
CheckEquals('-P1Y2M3DT4H5M6.7S',x.AsString());
finally
x.Free();
end;
end;
procedure TTest_TDurationRemotable.AsString_date_only();
var
x : TDurationRemotable;
begin
x := TDurationRemotable.Create();
try
x.Year := 1;
CheckEquals('P1Y', x.AsString());
x.Month := 2;
CheckEquals('P1Y2M', x.AsString());
x.Day := 3;
CheckEquals('P1Y2M3D', x.AsString());
x.Negative := True;
CheckEquals('-P1Y2M3D', x.AsString());
FreeAndNil(x);
x := TDurationRemotable.Create();
x.Month := 12;
CheckEquals('P12M',x.AsString());
FreeAndNil(x);
x := TDurationRemotable.Create();
x.Day := 34;
CheckEquals('P34D',x.AsString());
FreeAndNil(x);
x := TDurationRemotable.Create();
x.Month := 12;
x.Day := 3;
CheckEquals('P12M3D',x.AsString());
FreeAndNil(x);
x := TDurationRemotable.Create();
x.Year := 2;
x.Month := 34;
CheckEquals('P2Y34M',x.AsString());
FreeAndNil(x);
x := TDurationRemotable.Create();
x.Year := 12;
x.Day := 56;
CheckEquals('P12Y56D',x.AsString());
finally
x.Free();
end;
end;
procedure TTest_TDurationRemotable.AsString_time_only();
var
x : TDurationRemotable;
begin
x := TDurationRemotable.Create();
try
x.Hour := 1;
CheckEquals('PT1H', x.AsString());
x.Minute := 2;
CheckEquals('PT1H2M', x.AsString());
x.Second := 3;
CheckEquals('PT1H2M3S', x.AsString());
x.FractionalSecond := 4;
CheckEquals('PT1H2M3.4S', x.AsString());
x.Negative := True;
CheckEquals('-PT1H2M3.4S', x.AsString());
FreeAndNil(x);
x := TDurationRemotable.Create();
x.Minute := 12;
CheckEquals('PT12M',x.AsString());
FreeAndNil(x);
x := TDurationRemotable.Create();
x.Second := 34;
CheckEquals('PT34S',x.AsString());
FreeAndNil(x);
x := TDurationRemotable.Create();
x.Minute := 12;
x.Second := 3;
CheckEquals('PT12M3S',x.AsString());
FreeAndNil(x);
x := TDurationRemotable.Create();
x.Hour := 2;
x.Minute := 34;
CheckEquals('PT2H34M',x.AsString());
FreeAndNil(x);
x := TDurationRemotable.Create();
x.Hour := 12;
x.Second := 56;
CheckEquals('PT12H56S',x.AsString());
finally
x.Free();
end;
end;
procedure TTest_TDurationRemotable.Parse_non_empty();
var
x : TDurationRemotable;
begin
x := TDurationRemotable.Create();
try
x.Parse('P1Y2M3DT4H5M6S');
CheckEquals(False,x.Negative);
CheckEquals(1,x.Year);
CheckEquals(2,x.Month);
CheckEquals(3,x.Day);
CheckEquals(4,x.Hour);
CheckEquals(5,x.Minute);
CheckEquals(6,x.Second);
CheckEquals(0,x.FractionalSecond);
FreeAndNil(x);
x := TDurationRemotable.Create();
x.Parse('-P1Y2M3DT4H5M6S');
CheckEquals(True,x.Negative);
CheckEquals(1,x.Year);
CheckEquals(2,x.Month);
CheckEquals(3,x.Day);
CheckEquals(4,x.Hour);
CheckEquals(5,x.Minute);
CheckEquals(6,x.Second);
CheckEquals(0,x.FractionalSecond);
FreeAndNil(x);
x := TDurationRemotable.Create();
x.Parse('P1Y2M3DT4H5M6.7S');
CheckEquals(False,x.Negative);
CheckEquals(1,x.Year);
CheckEquals(2,x.Month);
CheckEquals(3,x.Day);
CheckEquals(4,x.Hour);
CheckEquals(5,x.Minute);
CheckEquals(6,x.Second);
CheckEquals(7,x.FractionalSecond);
x := TDurationRemotable.Create();
x.Parse('-P1Y2M3DT4H5M6.7S');
CheckEquals(True,x.Negative);
CheckEquals(1,x.Year);
CheckEquals(2,x.Month);
CheckEquals(3,x.Day);
CheckEquals(4,x.Hour);
CheckEquals(5,x.Minute);
CheckEquals(6,x.Second);
CheckEquals(7,x.FractionalSecond);
FreeAndNil(x);
finally
x.Free();
end;
end;
procedure TTest_TDurationRemotable.Parse_time_only();
var
x : TDurationRemotable;
begin
x := TDurationRemotable.Create();
try
x.Parse('PT1H2M3.4S');
CheckEquals(False,x.Negative);
CheckEquals(0,x.Year);
CheckEquals(0,x.Month);
CheckEquals(0,x.Day);
CheckEquals(1,x.Hour);
CheckEquals(2,x.Minute);
CheckEquals(3,x.Second);
CheckEquals(4,x.FractionalSecond);
FreeAndNil(x);
x := TDurationRemotable.Create();
x.Parse('-PT1H2M3.4S');
CheckEquals(True,x.Negative);
CheckEquals(0,x.Year);
CheckEquals(0,x.Month);
CheckEquals(0,x.Day);
CheckEquals(1,x.Hour);
CheckEquals(2,x.Minute);
CheckEquals(3,x.Second);
CheckEquals(4,x.FractionalSecond);
FreeAndNil(x);
x := TDurationRemotable.Create();
x.Parse('PT1H');
CheckEquals(False,x.Negative);
CheckEquals(0,x.Year);
CheckEquals(0,x.Month);
CheckEquals(0,x.Day);
CheckEquals(1,x.Hour);
CheckEquals(0,x.Minute);
CheckEquals(0,x.Second);
CheckEquals(0,x.FractionalSecond);
FreeAndNil(x);
x := TDurationRemotable.Create();
x.Parse('PT1S');
CheckEquals(False,x.Negative);
CheckEquals(0,x.Year);
CheckEquals(0,x.Month);
CheckEquals(0,x.Day);
CheckEquals(0,x.Hour);
CheckEquals(0,x.Minute);
CheckEquals(1,x.Second);
CheckEquals(0,x.FractionalSecond);
FreeAndNil(x);
finally
x.Free();
end;
end;
procedure TTest_TDurationRemotable.Parse_zero();
var
x : TDurationRemotable;
begin
x := TDurationRemotable.Create();
try
x.Negative := True;
x.Year := 1;
x.Month := 2;
x.Day := 3;
x.Hour := 4;
x.Minute := 5;
x.Second := 6;
x.FractionalSecond := 7;
x.Parse('P0Y');
CheckEquals(False,x.Negative);
CheckEquals(0,x.Year);
CheckEquals(0,x.Month);
CheckEquals(0,x.Day);
CheckEquals(0,x.Hour);
CheckEquals(0,x.Minute);
CheckEquals(0,x.Second);
CheckEquals(0,x.FractionalSecond);
finally
x.Free();
end;
end;
procedure TTest_TDurationRemotable.parse_negative();
var
x : TDurationRemotable;
begin
x := TDurationRemotable.Create();
try
x.Parse('-P3YT4S');
CheckEquals(True,x.Negative);
CheckEquals(3,x.Year);
CheckEquals(0,x.Month);
CheckEquals(0,x.Day);
CheckEquals(0,x.Hour);
CheckEquals(0,x.Minute);
CheckEquals(4,x.Second);
CheckEquals(0,x.FractionalSecond);
finally
x.Free();
end;
end;
procedure TTest_TDurationRemotable.parse_invalid_1();
const S_EXPR = 'P-1347M';
var
x : TDurationRemotable;
ok : Boolean;
begin
x := TDurationRemotable.Create();
try
ok := False;
try
x.Parse(S_EXPR);
except
on e : EConvertError do
ok := True;
end;
Check(ok, Format('Must fail with : "%s"',[S_EXPR]));
finally
x.Free();
end;
end;
procedure TTest_TDurationRemotable.parse_invalid_2();
const S_EXPR = 'P1Y2MT';
var
x : TDurationRemotable;
ok : Boolean;
begin
x := TDurationRemotable.Create();
try
ok := False;
try
x.Parse(S_EXPR);
except
on e : EConvertError do
ok := True;
end;
Check(ok, Format('Must fail with : "%s"',[S_EXPR]));
finally
x.Free();
end;
end;
procedure TTest_TDurationRemotable.parse_invalid_3();
const S_EXPR = 'XOJDQJKJ';
var
x : TDurationRemotable;
ok : Boolean;
begin
x := TDurationRemotable.Create();
try
ok := False;
try
x.Parse(S_EXPR);
except
on e : EConvertError do
ok := True;
end;
Check(ok, Format('Must fail with : "%s"',[S_EXPR]));
finally
x.Free();
end;
end;
procedure TTest_TDurationRemotable.parse_invalid_4();
const S_EXPR = 'P';
var
x : TDurationRemotable;
ok : Boolean;
begin
x := TDurationRemotable.Create();
try
ok := False;
try
x.Parse(S_EXPR);
except
on e : EConvertError do
ok := True;
end;
Check(ok, Format('Must fail with : "%s"',[S_EXPR]));
finally
x.Free();
end;
end;
procedure TTest_TDurationRemotable.parse_invalid_5();
const S_EXPR = 'P45DH';
var
x : TDurationRemotable;
ok : Boolean;
begin
x := TDurationRemotable.Create();
try
ok := False;
try
x.Parse(S_EXPR);
except
on e : EConvertError do
ok := True;
end;
Check(ok, Format('Must fail with : "%s"',[S_EXPR]));
finally
x.Free();
end;
end;
procedure TTest_TDurationRemotable.parse_empty();
const S_EXPR = '';
var
x : TDurationRemotable;
ok : Boolean;
begin
x := TDurationRemotable.Create();
try
ok := False;
try
x.Parse(S_EXPR);
except
on e : EConvertError do
ok := True;
end;
Check(ok, Format('Must fail with : "%s"',[S_EXPR]));
finally
x.Free();
end;
end;
{ TTest_TTimeRemotable }