From 1e53041c77d47c479fc419d262f2da52bc3c2011 Mon Sep 17 00:00:00 2001 From: inoussa Date: Mon, 18 Aug 2008 14:49:20 +0000 Subject: [PATCH] TDurationRemotable implementation and tests git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@530 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- wst/trunk/base_service_intf.pas | 261 ++++++++++- wst/trunk/tests/test_suite/test_support.pas | 462 +++++++++++++++++++- 2 files changed, 713 insertions(+), 10 deletions(-) diff --git a/wst/trunk/base_service_intf.pas b/wst/trunk/base_service_intf.pas index ba23508ec..d8c1b194b 100644 --- a/wst/trunk/base_service_intf.pas +++ b/wst/trunk/base_service_intf.pas @@ -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(); diff --git a/wst/trunk/tests/test_suite/test_support.pas b/wst/trunk/tests/test_suite/test_support.pas index 0a32e6f27..90d73de28 100644 --- a/wst/trunk/tests/test_suite/test_support.pas +++ b/wst/trunk/tests/test_suite/test_support.pas @@ -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 }