Skip to content

Commit 1f17bc8

Browse files
Merge branch 'develop' of https://bitbucket.org/sglienke/spring4d into develop
2 parents 900cadc + 23bc60a commit 1f17bc8

18 files changed

+685
-225
lines changed

Packages/Delphi11/Spring.Base.dproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<MainSource>Spring.Base.dpk</MainSource>
55
<Base>True</Base>
66
<Config Condition="'$(Config)'==''">Debug</Config>
7-
<TargetedPlatforms>3</TargetedPlatforms>
7+
<TargetedPlatforms>131</TargetedPlatforms>
88
<AppType>Package</AppType>
99
<FrameworkType>None</FrameworkType>
1010
<ProjectVersion>19.3</ProjectVersion>
@@ -201,6 +201,7 @@
201201
<Excluded_Packages/>
202202
</Delphi.Personality>
203203
<Platforms>
204+
<Platform value="Linux64">True</Platform>
204205
<Platform value="Win32">True</Platform>
205206
<Platform value="Win64">True</Platform>
206207
</Platforms>

Packages/Delphi11/Spring.Core.dproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<MainSource>Spring.Core.dpk</MainSource>
55
<Base>True</Base>
66
<Config Condition="'$(Config)'==''">Debug</Config>
7-
<TargetedPlatforms>3</TargetedPlatforms>
7+
<TargetedPlatforms>131</TargetedPlatforms>
88
<AppType>Package</AppType>
99
<FrameworkType>None</FrameworkType>
1010
<ProjectVersion>19.3</ProjectVersion>
@@ -170,6 +170,7 @@
170170
<Excluded_Packages/>
171171
</Delphi.Personality>
172172
<Platforms>
173+
<Platform value="Linux64">True</Platform>
173174
<Platform value="Win32">True</Platform>
174175
<Platform value="Win64">True</Platform>
175176
</Platforms>

Packages/Delphi11/Spring.Data.dproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@
135135
<Excluded_Packages/>
136136
</Delphi.Personality>
137137
<Platforms>
138+
<Platform value="Linux64">False</Platform>
138139
<Platform value="Win32">True</Platform>
139140
<Platform value="Win64">True</Platform>
140141
</Platforms>

Packages/Delphi11/Spring.Extensions.dproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@
150150
<Excluded_Packages/>
151151
</Delphi.Personality>
152152
<Platforms>
153+
<Platform value="Linux64">False</Platform>
153154
<Platform value="Win32">True</Platform>
154155
<Platform value="Win64">True</Platform>
155156
</Platforms>

Packages/Delphi11/Spring.Persistence.dproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@
174174
<Excluded_Packages/>
175175
</Delphi.Personality>
176176
<Platforms>
177+
<Platform value="Linux64">False</Platform>
177178
<Platform value="Win32">True</Platform>
178179
<Platform value="Win64">True</Platform>
179180
</Platforms>

Source/Base/Collections/Spring.Collections.Base.pas

Lines changed: 117 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ TEnumerableBase<T> = class abstract(TEnumerableBase)
185185
function Min(const comparer: IComparer<T>): T; overload;
186186
function Min(const comparer: TComparison<T>): T; overload;
187187

188+
function Memoize: IEnumerable<T>;
189+
188190
function Ordered: IEnumerable<T>; overload;
189191
function Ordered(const comparer: IComparer<T>): IEnumerable<T>; overload;
190192
function Ordered(const comparer: TComparison<T>): IEnumerable<T>; overload;
@@ -260,7 +262,7 @@ TCollectionWrapper = class(TEnumerableWrapper, ICollection)
260262

261263
TIteratorKind = (
262264
Partition, &Array,
263-
Concat, Ordered, Reversed, Shuffled,
265+
Concat, Memoize, Ordered, Reversed, Shuffled,
264266
SkipWhile, SkipWhileIndex,
265267
TakeWhile, TakeWhileIndex,
266268
Where, WhereIndex, Select);
@@ -292,6 +294,7 @@ TIteratorBlock = record
292294

293295
function GetEnumerator: Boolean;
294296
function GetEnumeratorAndSkip: Boolean;
297+
function GetEnumeratorMemoize: Boolean;
295298

296299
function _Release: Integer; stdcall;
297300
function MoveNext: Boolean;
@@ -309,6 +312,15 @@ TIteratorBase = record
309312
function GetCountFast: Integer;
310313
end;
311314

315+
TMemoizeIterator<T> = record
316+
// only used via pointer internally
317+
// field layout has to match with TIteratorBase
318+
Source: IEnumerable;
319+
Enumerator: IEnumerator<T>;
320+
Items: TArray<T>;
321+
Index, Count: Integer;
322+
end;
323+
312324
TIteratorBase<T> = class abstract(TEnumerableBase<T>)
313325
private
314326
function HasLimit: Boolean; inline;
@@ -361,6 +373,7 @@ TIteratorBlock<T> = record
361373
function GetCurrent: T;
362374

363375
function MoveNextConcat: Boolean;
376+
function MoveNextMemoize: Boolean;
364377
function MoveNextOrdered: Boolean;
365378
function MoveNextReversed: Boolean;
366379
function MoveNextSkipWhile: Boolean;
@@ -1505,6 +1518,16 @@ function TEnumerableBase<T>.Min(const comparer: TComparison<T>): T;
15051518
Result := IEnumerable<T>(this).Min(IComparer<T>(PPointer(@comparer)^));
15061519
end;
15071520

1521+
function TEnumerableBase<T>.Memoize: IEnumerable<T>;
1522+
begin
1523+
if (GetInterfaceEntry(ICollectionOfTGuid) <> nil)
1524+
or (GetInterfaceEntry(IReadOnlyCollectionOfTGuid) <> nil) then
1525+
Result := IEnumerable<T>(this)
1526+
else
1527+
Result := TEnumerableIterator<T>.Create(IEnumerable<T>(this),
1528+
0, 0, nil, TIteratorKind.Memoize);
1529+
end;
1530+
15081531
function TEnumerableBase<T>.Ordered: IEnumerable<T>;
15091532
begin
15101533
Result := TEnumerableIterator<T>.Create(IEnumerable<T>(this),
@@ -1693,30 +1716,28 @@ function TEnumerableBase<T>.SkipWhile(
16931716
end;
16941717

16951718
function TEnumerableBase<T>.Sum: T;
1696-
var
1697-
enumerator: IEnumerator<T>;
1698-
item: T;
16991719
begin
1700-
Result := Default(T);
1701-
enumerator := IEnumerable<T>(this).GetEnumerator;
1702-
while enumerator.MoveNext do
1703-
begin
1704-
{$IFDEF RSP31615}
1705-
if IsManagedType(T) then
1706-
IEnumeratorInternal(enumerator).GetCurrent(item)
1707-
else
1720+
if TypeInfo(T) = TypeInfo(Integer) then
1721+
PInteger(@Result)^ := TEnumerable.Sum(IEnumerable<Integer>(this))
1722+
else if TypeInfo(T) = TypeInfo(Int64) then
1723+
PInt64(@Result)^ := TEnumerable.Sum(IEnumerable<Int64>(this))
1724+
else if TypeInfo(T) = TypeInfo(NativeInt) then
1725+
{$IFDEF CPU32BITS}
1726+
PInteger(@Result)^ := TEnumerable.Sum(IEnumerable<Integer>(this))
1727+
{$ELSE}
1728+
PInt64(@Result)^ := TEnumerable.Sum(IEnumerable<Int64>(this))
17081729
{$ENDIF}
1709-
item := enumerator.Current;
1710-
case TType.Kind<T> of
1711-
tkInteger: PInteger(@Result)^ := PInteger(@Result)^ + PInteger(@item)^;
1712-
tkInt64: PInt64(@Result)^ := PInt64(@Result)^ + PInt64(@item)^;
1713-
tkFloat:
1714-
case GetTypeData(TypeInfo(T)).FloatType of
1715-
ftSingle: PSingle(@Result)^ := PSingle(@Result)^ + PSingle(@item)^;
1716-
ftDouble: PDouble(@Result)^ := PDouble(@Result)^ + PDouble(@item)^;
1717-
end;
1718-
end;
1719-
end;
1730+
else if TypeInfo(T) = TypeInfo(System.Single) then
1731+
PSingle(@Result)^ := TEnumerable.Sum(IEnumerable<System.Single>(this))
1732+
else if TypeInfo(T) = TypeInfo(Double) then
1733+
PDouble(@Result)^ := TEnumerable.Sum(IEnumerable<Double>(this))
1734+
else if TypeInfo(T) = TypeInfo(Currency) then
1735+
PCurrency(@Result)^ := TEnumerable.Sum(IEnumerable<Currency>(this))
1736+
else
1737+
// if T is not of any of the above types this way of calling Sum is not supported
1738+
// consider using TEnumerable.Sum with a selector function to turn the values
1739+
// to any of the supported types for calculating the sum
1740+
RaiseHelper.NotSupported;
17201741
end;
17211742

17221743
function TEnumerableBase<T>.Take(count: Integer): IEnumerable<T>;
@@ -3040,6 +3061,21 @@ function TIteratorBlock.GetEnumeratorAndSkip: Boolean;
30403061
end;
30413062
end;
30423063

3064+
function TIteratorBlock.GetEnumeratorMemoize: Boolean;
3065+
begin
3066+
if PIteratorBase(Predicate).fCount = 0 then
3067+
begin
3068+
{$IFDEF MSWINDOWS}
3069+
IEnumerableInternal(Source).GetEnumerator(IEnumerator(PIteratorBase(Predicate).fPredicate));
3070+
{$ELSE}
3071+
IEnumerator(PIteratorBase(Predicate).fPredicate) := Source.GetEnumerator;
3072+
{$ENDIF}
3073+
PIteratorBase(Predicate).fCount := PIteratorBase(Predicate).fCount or not CountMask;
3074+
end;
3075+
DoMoveNext := Methods.MoveNext;
3076+
Result := DoMoveNext(@Self);
3077+
end;
3078+
30433079
function TIteratorBlock.MoveNextEmpty: Boolean;
30443080
begin
30453081
Result := False;
@@ -3072,6 +3108,8 @@ class function TIteratorBlock<T>.Create(const iterator: TIteratorBase<T>): IEnum
30723108
Count := iterator.fCount;
30733109
Kind := iterator.fKind;
30743110
Methods.Finalize := @TIteratorBlock<T>.Finalize;
3111+
if Kind = Memoize then
3112+
Pointer(Predicate) := @iterator.fSource;
30753113
end;
30763114
rec.InitMethods;
30773115
rec.InitVtable;
@@ -3118,6 +3156,16 @@ procedure TIteratorBlock<T>.InitMethods;
31183156
Methods.MoveNext := @TIteratorBlock<T>.MoveNextConcat;
31193157
DoMoveNext := @TIteratorBlock.GetEnumerator;
31203158
end;
3159+
TIteratorKind.Memoize:
3160+
begin
3161+
if Count = 0 then
3162+
begin
3163+
Methods.MoveNext := @TIteratorBlock<T>.MoveNextMemoize;
3164+
DoMoveNext := @TIteratorBlock.GetEnumeratorMemoize;
3165+
end
3166+
else
3167+
DoMoveNext := @TIteratorBlock<T>.MoveNextMemoize;
3168+
end;
31213169
TIteratorKind.Ordered:
31223170
begin
31233171
Methods.MoveNext := @TIteratorBlock<T>.MoveNextOrdered;
@@ -3179,7 +3227,10 @@ function TIteratorBlock<T>.Finalize: Boolean;
31793227
begin
31803228
Enumerator := nil;
31813229
Source := nil;
3182-
Predicate := nil;
3230+
if Kind <> Memoize then
3231+
Predicate := nil
3232+
else
3233+
Pointer(Predicate) := nil;
31833234
Items := nil;
31843235
{$IFDEF DELPHIXE7_UP}
31853236
if IsManagedType(T) then
@@ -3227,7 +3278,7 @@ function TIteratorBlock<T>.MoveNextConcat: Boolean;
32273278
{$IFDEF MSWINDOWS}
32283279
IEnumerableInternal(Predicate).GetEnumerator(IEnumerator(Enumerator));
32293280
{$ELSE}
3230-
Enumerator := IEnumerable(Predicate).GetEnumerator;
3281+
Enumerator := IEnumerable<T>(Predicate).GetEnumerator;
32313282
{$ENDIF}
32323283
Predicate := nil;
32333284
until False;
@@ -3282,6 +3333,44 @@ function TIteratorBlock<T>.MoveNextIndexed: Boolean;
32823333
end;
32833334
end;
32843335

3336+
function TIteratorBlock<T>.MoveNextMemoize: Boolean;
3337+
var
3338+
iterator: ^TMemoizeIterator<T>;
3339+
count, capacity: NativeInt;
3340+
begin
3341+
iterator := Pointer(Predicate);
3342+
count := iterator.Count and CountMask;
3343+
if Index >= count then
3344+
begin
3345+
if iterator.Enumerator = nil then
3346+
Exit(False);
3347+
3348+
if not iterator.Enumerator.MoveNext then
3349+
begin
3350+
iterator.Enumerator := nil;
3351+
Exit(False);
3352+
end;
3353+
3354+
capacity := DynArrayLength(iterator.Items);
3355+
if count >= capacity then
3356+
begin
3357+
capacity := GrowCapacity(capacity);
3358+
SetLength(iterator.Items, capacity);
3359+
end;
3360+
{$IF defined(DELPHIXE7_UP) and defined(MSWINDOWS)}
3361+
if IsManagedType(T) then
3362+
IEnumeratorInternal(iterator.Enumerator).GetCurrent(iterator.Items[count])
3363+
else
3364+
{$IFEND}
3365+
iterator.Items[count] := iterator.Enumerator.Current;
3366+
Inc(iterator.Count);
3367+
end;
3368+
3369+
Current := iterator.Items[Index];
3370+
Inc(Index);
3371+
Result := True;
3372+
end;
3373+
32853374
function TIteratorBlock<T>.MoveNextOrdered: Boolean;
32863375
begin
32873376
if Index < Count then
@@ -3416,12 +3505,10 @@ function TIteratorBlock<T>.MoveNextWhereIndex: Boolean;
34163505
function TIteratorBlock<T>.ToArray: Boolean;
34173506
begin
34183507
Items := Source.ToArray;
3419-
Count := Length(Items);
3508+
Count := DynArrayLength(Items);
34203509
case Kind of
34213510
TIteratorKind.Ordered:
34223511
TArray.Sort<T>(Items, IComparer<T>(Predicate));
3423-
TIteratorKind.Reversed:
3424-
Count := Length(Items);
34253512
TIteratorKind.Shuffled:
34263513
TArray.Shuffle<T>(Items, DynArrayHigh(Items));
34273514
end;
@@ -3624,7 +3711,7 @@ function TIteratorBase<T>.ToArray: TArray<T>;
36243711
TIteratorKind.Array:
36253712
begin
36263713
Result := fItems;
3627-
SetLength(Result, Length(Result));
3714+
SetLength(Result, DynArrayLength(Result));
36283715
Exit;
36293716
end;
36303717
TIteratorKind.Ordered:
@@ -3810,7 +3897,7 @@ procedure TArrayIterator<T>.CopyTo(var values: TArray<T>; index: Integer);
38103897
var
38113898
count: Integer;
38123899
begin
3813-
count := Length(fItems);
3900+
count := DynArrayLength(fItems);
38143901
if count > 0 then
38153902
if TType.IsManaged<T> then
38163903
MoveManaged(@fItems[0], @values[index], TypeInfo(T), count)

Source/Base/Collections/Spring.Collections.Extensions.pas

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ TRangeIterator = class(TEnumerableBase<Integer>,
235235
TEnumerator = record
236236
Vtable: Pointer;
237237
RefCount: Integer;
238-
fCurrent, fMax: Integer;
238+
fCurrent, fEnd: Integer;
239239
function GetCurrent: Integer;
240240
function MoveNext: Boolean;
241241
function _Release: Integer; stdcall;
@@ -1559,8 +1559,8 @@ class function TRangeIterator.TEnumerator.Create(start, count: Integer): IEnumer
15591559
RefCount := 1;
15601560
{$Q-}
15611561
fCurrent := start - 1;
1562+
fEnd := start + count;
15621563
{$IFDEF OVERFLOWCHECKS_ON}{$Q+}{$ENDIF}
1563-
fMax := fCurrent + count;
15641564
end;
15651565
end;
15661566

@@ -1570,9 +1570,15 @@ function TRangeIterator.TEnumerator.GetCurrent: Integer;
15701570
end;
15711571

15721572
function TRangeIterator.TEnumerator.MoveNext: Boolean;
1573-
begin
1574-
Result := fCurrent < fMax;
1575-
Inc(fCurrent, Byte(Result));
1573+
var
1574+
current: Integer;
1575+
begin
1576+
current := fCurrent;
1577+
{$Q-}
1578+
Inc(current);
1579+
{$IFDEF OVERFLOWCHECKS_ON}{$Q+}{$ENDIF}
1580+
fCurrent := current;
1581+
Result := current <> fEnd;
15761582
end;
15771583

15781584
function TRangeIterator.TEnumerator._Release: Integer;

0 commit comments

Comments
 (0)