@@ -168,8 +168,8 @@ TLoopStackItem = class
168
168
DataSourceName: String;
169
169
LoopExpression: String;
170
170
FullPath: String;
171
- IteratorName: String;
172
171
IteratorPosition: Integer;
172
+ IteratorName: String;
173
173
function IncrementIteratorPosition : Integer;
174
174
constructor Create(DataSourceName: String; LoopExpression: String; FullPath: String; IteratorName: String);
175
175
end ;
@@ -199,7 +199,6 @@ TTProCompiledTemplate = class(TInterfacedObject, ITProCompiledTemplate)
199
199
function IsTruthy (const Value : TValue): Boolean;
200
200
function GetVarAsString (const Name : string): string;
201
201
function GetTValueVarAsString (const Value : PValue; const VarName: string = ' ' ): String;
202
- function GetTValueFromPath (const aObject: TObject; FullPropertyPath: String): TValue;
203
202
function GetNullableTValueAsTValue (const Value : PValue; const VarName: string = ' ' ): TValue;
204
203
function GetVarAsTValue (const aName: string): TValue;
205
204
function GetDataSetFieldAsTValue (const aDataSet: TDataSet; const FieldName: String): TValue;
@@ -294,6 +293,7 @@ TTProConfiguration = class sealed
294
293
function HTMLEncode (s: string): string;
295
294
function HandleTemplateSectionStateMachine (const aTokenValue1: String; var aTemplateSectionType: TTProTemplateSectionType;
296
295
out aErrorMessage: String): Boolean;
296
+ function GetTValueFromPath (const aObject: TObject; FullPropertyPath: String): TValue;
297
297
298
298
implementation
299
299
@@ -701,60 +701,6 @@ function TTProCompiledTemplate.GetPseudoVariable(const VarIterator: Integer; con
701
701
end ;
702
702
end ;
703
703
704
- function TTProCompiledTemplate.GetTValueFromPath (const aObject: TObject; FullPropertyPath: String): TValue;
705
- var
706
- lObjAsList: ITProWrappedList;
707
- lIdx: Integer;
708
- lPropName: string;
709
- lTmpValue: TValue;
710
- function FetchUpTo (const aChar: Char): String;
711
- var
712
- lFirst: Integer;
713
- begin
714
- lFirst := FullPropertyPath.IndexOf(aChar);
715
- if lFirst = -1 then
716
- begin
717
- Result := FullPropertyPath;
718
- end
719
- else
720
- begin
721
- Result := FullPropertyPath.Substring(0 , lFirst);
722
- end ;
723
- FullPropertyPath := FullPropertyPath.Substring(Length(Result) + 1 );
724
- end ;
725
- begin
726
- if FullPropertyPath.StartsWith(' [' ) then // the main object must be a list!
727
- begin
728
- lObjAsList := WrapAsList(aObject);
729
- FullPropertyPath := FullPropertyPath.Remove(0 ,1 );
730
- lIdx := FetchUpTo(' ]' ).ToInteger;
731
- if FullPropertyPath.IsEmpty then
732
- begin
733
- raise ETProException.Create(' Invalid Path - No property name after index' );
734
- end ;
735
- Result := GetTValueFromPath(lObjAsList.GetItem(lIdx), FullPropertyPath);
736
- end
737
- else
738
- begin
739
- if FullPropertyPath.StartsWith(' .' ) then
740
- begin
741
- FullPropertyPath := FullPropertyPath.Remove(0 ,1 );
742
- end ;
743
- lPropName := FetchUpTo(' .' );
744
- lTmpValue := TTProRTTIUtils.GetProperty(aObject, lPropName);
745
- if (not FullPropertyPath.IsEmpty) then
746
- begin
747
- if not lTmpValue.IsObject then
748
- raise ETProException.Create(' Invalid Path - cannot read property of a non object' );
749
- Result := GetTValueFromPath(lTmpValue.AsObject, FullPropertyPath);
750
- end
751
- else
752
- begin
753
- Result := lTmpValue;
754
- end ;
755
- end ;
756
- end ;
757
-
758
704
function TTProCompiledTemplate.GetTValueVarAsString (const Value : PValue; const VarName: string): String;
759
705
var
760
706
lIsObject: Boolean;
@@ -2823,6 +2769,9 @@ function TTProCompiledTemplate.Render: String;
2823
2769
lErrorMessage: String;
2824
2770
lBlockReturnAddress: Int64;
2825
2771
lCurrentBlockName: string;
2772
+ lObj: TValue;
2773
+ lLastOpenBracket: Integer;
2774
+ lCount: Integer;
2826
2775
2827
2776
begin
2828
2777
lBlockReturnAddress := -1 ;
@@ -2848,6 +2797,7 @@ function TTProCompiledTemplate.Render: String;
2848
2797
the real information about the iterator }
2849
2798
if WalkThroughLoopStack(lVarName, lBaseVarName, lFullPath) then
2850
2799
begin
2800
+ if not lVarMember.IsEmpty then
2851
2801
lFullPath := lFullPath + ' .' + lVarMember;
2852
2802
PushLoop(TLoopStackItem.Create(lBaseVarName, fTokens[lIdx].Value1, lFullPath, fTokens[lIdx].Value2));
2853
2803
end
@@ -2884,16 +2834,18 @@ function TTProCompiledTemplate.Render: String;
2884
2834
end
2885
2835
else if viListOfObject in lVariable.VarOption then
2886
2836
begin
2887
- lWrapped := WrapAsList(lVariable.VarValue.AsObject);
2888
2837
// if lVariable.VarIterator = lWrapped.Count - 1 then
2889
- if lForLoopItem.IteratorPosition = lWrapped.Count - 1 then
2838
+ lObj := GetTValueFromPath(lVariable.VarValue.AsObject, lForLoopItem.FullPath);
2839
+ lWrapped := WrapAsList(lObj.AsObject);
2840
+ lCount := lWrapped.Count;
2841
+ if (lCount = 0 ) or (lForLoopItem.IteratorPosition = lCount - 1 ) then
2890
2842
begin
2891
2843
lIdx := fTokens[lIdx].Ref1; // skip to endif
2892
2844
Continue;
2893
2845
end
2894
2846
else
2895
2847
begin
2896
- PeekLoop .IncrementIteratorPosition;
2848
+ lForLoopItem .IncrementIteratorPosition;
2897
2849
// lVariable.VarIterator := lVariable.VarIterator + 1;
2898
2850
end ;
2899
2851
end
@@ -2980,7 +2932,9 @@ function TTProCompiledTemplate.Render: String;
2980
2932
end
2981
2933
else if viListOfObject in lVariable.VarOption then
2982
2934
begin
2983
- lWrapped := TTProDuckTypedList.Wrap(lVariable.VarValue.AsObject);
2935
+ { TODO -oDanieleT -cGeneral : We need only .Count here. Could we use something lighter than WrapAsList?}
2936
+ lObj := GetTValueFromPath(lVariable.VarValue.AsObject, lForLoopItem.FullPath);
2937
+ lWrapped := WrapAsList(lObj.AsObject);
2984
2938
if lForLoopItem.IteratorPosition < lWrapped.Count - 1 then
2985
2939
begin
2986
2940
lIdx := fTokens[lIdx].Ref1; // skip to loop
@@ -3159,6 +3113,7 @@ function TTProCompiledTemplate.GetVarAsTValue(const aName: string): TValue;
3159
3113
lHandled: Boolean;
3160
3114
lFullPath: string;
3161
3115
lValue: TValue;
3116
+ lTmpList: ITProWrappedList;
3162
3117
begin
3163
3118
lCurrentIterator := nil ;
3164
3119
SplitVariableName(aName, lVarName, lVarMembers);
@@ -3329,13 +3284,28 @@ function TTProCompiledTemplate.GetVarAsTValue(const aName: string): TValue;
3329
3284
begin
3330
3285
lFullPath := lCurrentIterator.FullPath;
3331
3286
lValue := GetTValueFromPath(lVariable.VarValue.AsObject, lFullPath);
3332
- Result := TTProRTTIUtils.GetProperty(WrapAsList(lValue.AsObject)
3333
- .GetItem(lCurrentIterator.IteratorPosition), lVarMembers)
3287
+ lTmpList := WrapAsList(lValue.AsObject);
3288
+ if Assigned(lTmpList)then
3289
+ Result := TTProRTTIUtils.GetProperty(lTmpList.GetItem(lCurrentIterator.IteratorPosition), lVarMembers)
3290
+ else
3291
+ Result := TTProRTTIUtils.GetProperty(lValue.AsObject, lVarMembers)
3334
3292
end ;
3335
3293
end
3336
3294
else
3337
3295
begin
3296
+ if lCurrentIterator.FullPath.IsEmpty then
3297
+ begin
3338
3298
Result := WrapAsList(lVariable.VarValue.AsObject).GetItem(lCurrentIterator.IteratorPosition);
3299
+ end
3300
+ else
3301
+ begin
3302
+ lValue := GetTValueFromPath(lVariable.VarValue.AsObject, lCurrentIterator.FullPath);
3303
+ lTmpList := WrapAsList(lValue.AsObject);
3304
+ if Assigned(lTmpList)then
3305
+ Result := TTProRTTIUtils.GetProperty(lTmpList.GetItem(lCurrentIterator.IteratorPosition), lVarMembers)
3306
+ else
3307
+ Result := TTProRTTIUtils.GetProperty(lValue.AsObject, lVarMembers)
3308
+ end ;
3339
3309
end ;
3340
3310
end
3341
3311
else
@@ -4119,6 +4089,78 @@ function TTProEqualityComparer.GetHashCode(const Value: String): Integer;
4119
4089
Result := Length(Value );
4120
4090
end ;
4121
4091
4092
+
4093
+
4094
+ function GetTValueFromPath (const aObject: TObject; FullPropertyPath: String): TValue;
4095
+ var
4096
+ lObjAsList: ITProWrappedList;
4097
+ lIdx: Integer;
4098
+ lPropName: string;
4099
+ lTmpValue: TValue;
4100
+ function FetchUpTo (const aChar: Char): String;
4101
+ var
4102
+ lFirst: Integer;
4103
+ begin
4104
+ lFirst := FullPropertyPath.IndexOf(aChar);
4105
+ if lFirst = -1 then
4106
+ begin
4107
+ Result := FullPropertyPath;
4108
+ end
4109
+ else
4110
+ begin
4111
+ Result := FullPropertyPath.Substring(0 , lFirst);
4112
+ end ;
4113
+ FullPropertyPath := FullPropertyPath.Substring(Length(Result) + 1 );
4114
+ end ;
4115
+ begin
4116
+ if FullPropertyPath = ' .' then
4117
+ begin
4118
+ Exit(aObject);
4119
+ end ;
4120
+
4121
+ if FullPropertyPath.StartsWith(' [' ) then // the main object must be a list!
4122
+ begin
4123
+ lObjAsList := WrapAsList(aObject);
4124
+ FullPropertyPath := FullPropertyPath.Remove(0 ,1 );
4125
+ lIdx := FetchUpTo(' ]' ).ToInteger;
4126
+ Result := GetTValueFromPath(lObjAsList.GetItem(lIdx), FullPropertyPath);
4127
+ end
4128
+ else
4129
+ begin
4130
+ if FullPropertyPath.StartsWith(' .' ) then
4131
+ begin
4132
+ FullPropertyPath := FullPropertyPath.Remove(0 ,1 );
4133
+ end ;
4134
+ if FullPropertyPath.StartsWith(' [' ) then
4135
+ begin
4136
+ Result := GetTValueFromPath(aObject, FullPropertyPath);
4137
+ end
4138
+ else
4139
+ begin
4140
+ lPropName := FetchUpTo(' .' );
4141
+ if lPropName.IsEmpty then
4142
+ begin
4143
+ Result := aObject;
4144
+ end
4145
+ else
4146
+ begin
4147
+ lTmpValue := TTProRTTIUtils.GetProperty(aObject, lPropName);
4148
+ if (not FullPropertyPath.IsEmpty) then
4149
+ begin
4150
+ if not lTmpValue.IsObject then
4151
+ raise ETProException.Create(' Invalid Path - cannot read property of a non object' );
4152
+ Result := GetTValueFromPath(lTmpValue.AsObject, FullPropertyPath);
4153
+ end
4154
+ else
4155
+ begin
4156
+ Result := lTmpValue;
4157
+ end ;
4158
+ end ;
4159
+ end ;
4160
+ end ;
4161
+ end ;
4162
+
4163
+
4122
4164
initialization
4123
4165
4124
4166
GlContext := TRttiContext.Create;
0 commit comments