ArenaZ
625 строк · 16.1 Кб
1(*====< GLZArrayClasses.pas >===================================================@br
2@created(2017-04-17)
3@author(J.Delauney (BeanzMaster) - Peter Dyson (Dicepd) )
4Historique : @br
5@unorderedList(
6@item(21/01/2018 : Creation )
7)
8--------------------------------------------------------------------------------@br
9
10@bold(Description :)@br
11Generics base classes for managing array thrue pointer
12
13------------------------------------------------------------------------------@br
14@bold(Notes) : @br
15
16------------------------------------------------------------------------------@br
17@bold(BUGS :)@br
18@unorderedList(
19@item()
20)
21------------------------------------------------------------------------------@br
22@bold(TODO :)@br
23@unorderedList(
24@item()
25)
26
27------------------------------------------------------------------------------@br
28@bold(Credits :)
29@unorderedList(
30@item(FPC/Lazarus)
31)
32
33------------------------------------------------------------------------------@br
34@bold(LICENCE :) MPL / GPL @br
35@br
36*==============================================================================*)
37unit GLZArrayClasses;
38
39{$mode objfpc}{$H+}
40
41{$IFDEF CPU64}
42{$CODEALIGN LOCALMIN=16} // ??? needed here ????
43{$ENDIF}
44
45interface
46
47uses
48Classes, SysUtils;
49//GLZTypes, GLZClasses, GLZPersistentClasses;
50
51const
52cDefaultListGrowthDelta = 16;
53
54Type
55
56{ TGLZBaseArray }
57
58generic TGLZBaseArray<T> = class //(TGLZPersistentObject)
59private
60F: boolean;
61FTagString : string;
62
63type
64PT = ^ T;
65TArr = array of T;
66PArr = ^TArr;
67
68procedure SetCount(AValue : SizeUInt);
69
70
71protected
72var
73{$CODEALIGN RECORDMIN=16}
74FData: TArr; // The base list pointer (untyped)
75{$CODEALIGN RECORDMIN=4}
76
77FCapacity:SizeUInt;
78FDataSize:SizeUInt;
79FItemSize:SizeUInt; // Must be defined in subclasses
80FGrowthDelta: Integer;
81FParentData: Pointer;
82FHandle: SizeUInt;
83FIsDirty: boolean;
84
85FRevision: LongWord;
86FCount: SizeUInt;
87
88FPosition: SizeUInt;
89FFirstDone: Boolean;
90
91
92Function GetData: Pointer; inline;
93function GetValue(Position: SizeUInt): T; inline;
94procedure SetValue(Position : SizeUInt; const AValue : T);
95
96function GetMutable(Position: SizeUInt): PT; inline;
97procedure IncreaseCapacity; inline;
98
99procedure SetCapacity(NewCapacity: SizeUInt); virtual;
100
101// persistency support.
102//procedure ReadItemsData(AReader : TReader); virtual;
103//procedure WriteItemsData(AWriter : TWriter); virtual;
104//procedure DefineProperties(AFiler: TFiler); override;
105
106public
107{ Public Declarations }
108constructor Create; //override;
109constructor Create(Reserved: SizeUInt); overload;
110constructor CreateParented(AParentData: Pointer; Reserved: SizeUInt); overload;
111destructor Destroy; override;
112//procedure Assign(Src: TPersistent); override;
113
114//procedure WriteToFiler(writer: TVirtualWriter); override;
115//procedure ReadFromFiler(reader: TVirtualReader); override;
116
117function DataSize: SizeUInt; // size of the list
118function ItemSize: Byte; // Size of 1 item
119
120// Management
121function Add(const Value: T):SizeUInt; inline;
122procedure Insert(Position: SizeUInt; const Value: T); inline;
123procedure Delete(Position : SizeUInt); inline;
124
125procedure Exchange(index1, index2: SizeUInt); inline;
126//procedure Move(curIndex, newIndex: SizeUInt); inline;
127procedure Reverse; inline;
128
129//procedure AddNulls(nbVals: Cardinal); inline;
130//procedure InsertNulls(Position : SizeUInt; nbVals: Cardinal); inline;
131
132{ Empties the list without altering capacity. }
133procedure Flush; inline;
134{ Empties the list and release. }
135procedure Clear; inline;
136
137// LIFO
138procedure Push(const Value: T);inline;
139function Pop: T; inline;
140
141// Array Iterators
142function First: T; inline;
143function Last: T; inline;
144function Next: T; inline;
145function Prev: T; inline;
146function Current : T; inline;
147function MoveNext:Boolean; inline;
148function MovePrev:Boolean; inline;
149function MoveFirst:Boolean; inline;
150function MoveLast:Boolean; inline;
151function GetPosition : SizeUInt;
152function Seek(const pos : SizeUInt; const StartAt : Byte) : boolean; inline;
153function MoveTo(Position:SizeUInt) : Boolean; inline;
154function IsEndOfArray : Boolean; inline;
155
156// Array Rasterizer
157// function Scan(CallBack):Boolean;
158// function ScanNext(CallBack):Boolean;
159// function ScanPrev(CallBack):Boolean;
160
161// function ScanMany(nbItem,CallBack):Boolean;
162// function ScanTo(Position,CallBack):Boolean;
163
164// function ScanAll(CallBack):Boolean;
165// function ScanRange(From, To, CallBack):Boolean;
166
167// Array Utils
168
169// function CompareItems(Index1, index2, comparefunc): Integer;
170// procedure Sort(Const Direction : byte);
171// procedure Merge(AnotherArray: TGLZBaseArray<T>);
172// function Clone : TGLZBaseArray<T>;
173// function Extract(From, Nb : SizeUInt): TGLZBaseArray<T>;
174
175// Extra funcs for management
176// function InsertItemsAt(Pos:SizeUInt; AnArray : TGLZBaseArray<T>):Boolean;
177// function InsertItemsAtEnd
178// function InsertItemsAtFirst
179// procedure DeleteItems(Index: SizeUIntr; nbVals: Cardinal); inline;
180
181// Properties
182{ Nb of items in the list. When assigning a Count, added items are reset to zero. }
183property Count: SizeUInt read FCount write SetCount;
184{ Current list capacity.Not persistent. }
185property Capacity: SizeUInt read FCapacity write SetCapacity;
186{ List growth granularity. Not persistent. }
187property GrowthDelta: Integer read FGrowthDelta write FGrowthDelta;
188
189property TagString: string read FTagString write FTagString;
190{ Increase by one after every content changes. }
191property Revision: LongWord read FRevision write FRevision;
192
193property ParentData : Pointer read FParentData;
194property Data : Pointer read GetData;
195property Handle : SizeUInt read FHandle;
196property IsDirty : boolean read FIsDirty write f;
197property Items[i : SizeUInt]: T read getValue write SetValue;// default;
198property Mutable[i : SizeUInt]: PT read getMutable;
199end;
200
201{ TGLZBaseArray2D }
202
203generic TGLZBaseArrayMap2D<T> = class(specialize TGLZBaseArray<T>)
204private
205
206function GetValue2D(x, y : SizeUInt): T;
207procedure SetValue2D(x, y : SizeUInt; AValue: T);
208protected
209FRows, FCols : SizeUInt;
210
211public
212constructor Create(Rows, Cols: SizeUInt); overload;
213constructor CreateParented(AParentData: Pointer; Rows, Cols: SizeUInt); overload;
214
215function MoveTo(Row : Integer; Position : Integer) : Boolean; overload;
216
217property Items[x,y : SizeUInt]: T read GetValue2D write SetValue2D;
218property RowCount : SizeUInt read FRows;
219property ColCount : SizeUInt read FCols;
220
221end;
222
223//generic TGLZBaseArrayMap3D<T> = class(specialize TGLZBaseArray<T>)
224//private
225// function GetValue3D(x, y, z : SizeUInt): T;
226// procedure SetValue3D(x, y, z : SizeUInt; AValue: T);
227//published
228//public
229// constructor Create(Rows, Cols, DCols : SizeUInt); overload;
230// constructor CreateParented(AParentData: Pointer; Rows, Cols, DCols: SizeUInt); overload;
231// property Items[x,y,z : SizeUInt]: T read GetValue3D write SetValue3D;
232//end;
233//
234//generic TGLZBaseArrayMap4D<T> = class(specialize TGLZBaseArray<T>)
235//private
236// function GetValue4D(x, y, z, w : SizeUInt): T;
237// procedure SetValue4D(x, y, z, w : SizeUInt; AValue: T);
238//published
239//public
240// constructor Create(Rows, Cols, DCols, TCols: SizeUInt); overload;
241// constructor CreateParented(AParentData: Pointer; Rows, Cols, DCols, TCols: SizeUInt); overload;
242// property Items[x,y,z,w : SizeUInt]: T read GetValue4D write SetValue4D;
243//end;
244
245
246implementation
247{$ifdef DEBUGLOG}
248uses GLZLogger;
249{$endif}
250{%region%=====[ TGLZBaseArray ]=================================================}
251
252procedure TGLZBaseArray.SetCount(AValue : SizeUInt);
253begin
254{$ifdef DEBUG}
255Assert(AValue >= 0);
256{$endif}
257if FCount = AValue then Exit;
258if AValue> FCapacity then SetCapacity(AValue);
259//if (AValue > FCount) and (bloSetCountResetsMemory in FOptions) then
260// FillChar(FBaseList[FItemSize * FCount], (Val - FCount) * FItemSize, 0);
261FCount := AValue;
262Inc(FRevision);
263end;
264
265function TGLZBaseArray.GetData : Pointer;
266begin
267Result := @FData;
268end;
269
270function TGLZBaseArray.GetValue(Position : SizeUInt) : T;
271begin
272{$ifdef DEBUG}
273Assert((position < size) and (position>=0), SVectorPositionOutOfRange);
274{$endif}
275Result := FData[Position];
276end;
277
278procedure TGLZBaseArray.SetValue(Position : SizeUInt; const AValue : T);
279begin
280{$ifdef DEBUG}
281Assert((position < size) and (position>=0), SVectorPositionOutOfRange);
282{$endif}
283{$ifdef DEBUGLOG}
284GlobalLogger.LogStatus('Set value at : '+Inttostr(Position));
285{$endif}
286//if FData[Position] = AValue then exit;
287FData[Position] := AValue;
288end;
289
290function TGLZBaseArray.GetMutable(Position : SizeUInt) : PT;
291begin
292{$ifdef DEBUG}
293Assert((position < size) and (position>=0), SVectorPositionOutOfRange);
294{$endif}
295Result := @FData[Position];
296end;
297
298procedure TGLZBaseArray.IncreaseCapacity;
299begin
300if FCapacity=0 then SetCapacity(1)
301else
302SetCapacity(FCapacity+FGrowthDelta);
303end;
304
305procedure TGLZBaseArray.SetCapacity(NewCapacity : SizeUInt);
306begin
307if FCapacity = newCapacity then exit;
308//if bloExternalMemory in FOptions then
309//begin
310// Exclude(FOptions, bloExternalMemory);
311// FBaseList := nil;
312//end;
313//ReallocMem(FBaseList, newCapacity * FItemSize);
314FCapacity := newCapacity;
315SetLength(FData, FCapacity);
316Inc(FRevision);
317end;
318
319constructor TGLZBaseArray.Create;
320begin
321inherited Create;
322FCapacity:=0;
323// FItemSize:=Sizeof(T); // Must be defined in subclasses ????
324FGrowthDelta:= cDefaultListGrowthDelta;
325FParentData:=nil;
326FHandle:=0;
327FIsDirty:=false;
328FRevision:=0;
329FCount:=0;
330FPosition:=0;
331FFirstDone:=false;
332end;
333
334constructor TGLZBaseArray.Create(Reserved : SizeUInt);
335begin
336Create;
337FDataSize:=Reserved*ItemSize;
338SetCapacity(Reserved);
339end;
340
341constructor TGLZBaseArray.CreateParented(AParentData : Pointer; Reserved : SizeUInt);
342begin
343Create(Reserved);
344FParentData := AParentData;
345end;
346
347destructor TGLZBaseArray.Destroy;
348begin
349Clear;
350//SetLength(FData, 0);
351FData := nil;
352inherited Destroy;
353end;
354
355function TGLZBaseArray.DataSize : SizeUInt;
356begin
357Result := FCount * ItemSize; //FDataSize;
358end;
359
360function TGLZBaseArray.ItemSize : Byte;
361begin
362Result := Sizeof(T); //FItemSize;
363end;
364
365function TGLZBaseArray.Add(const Value : T) : SizeUInt;
366begin
367
368Result := FCount;
369if Result >= FCapacity then IncreaseCapacity;
370FData[Result] := Value;
371
372Inc(FCount);
373end;
374
375procedure TGLZBaseArray.Insert(Position : SizeUInt; const Value : T);
376begin
377{$ifdef DEBUG}
378Assert(Position < FCount);
379{$endif}
380if FCount = FCapacity then IncreaseCapacity;
381if Position < FCount then
382System.Move(FData[Position], FData[Position + 1], (FCount - Position) * FItemSize);
383FData[Position] := Value;
384Inc(FCount);
385end;
386
387procedure TGLZBaseArray.Delete(Position : SizeUInt);
388begin
389{$ifdef DEBUG}
390Assert(Position < FCount-1);
391{$endif}
392Dec(FCount);
393System.Move(FData[(Position + 1)], // * FItemSize],
394FData[Position], // * FItemSize],
395(FCount - Position)); // * FItemSize);
396Inc(FRevision);
397end;
398
399procedure TGLZBaseArray.Exchange(index1, index2 : SizeUInt);
400var
401temp : T;
402begin
403{$ifdef DEBUG}
404Assert((Index1 < FCount) and (Index2 < FCount));
405{$endif}
406temp := FData[index1];
407FData[index1] := FData[index2];
408FData[index2] := temp;
409Inc(FRevision);
410end;
411
412//procedure TGLZBaseArray.Move(curIndex, newIndex : SizeUInt);
413//begin
414//
415//end;
416
417procedure TGLZBaseArray.Reverse;
418var
419s, e: Integer;
420begin
421s := 0;
422e := FCount - 1;
423while s < e do
424begin
425Exchange(s, e);
426Inc(s);
427Dec(e);
428end;
429Inc(FRevision);
430end;
431
432//procedure TGLZBaseArray.AddNulls(nbVals : Cardinal);
433//begin
434//
435//end;
436//
437//procedure TGLZBaseArray.InsertNulls(Position : SizeUInt; nbVals : Cardinal);
438//begin
439//
440//end;
441
442procedure TGLZBaseArray.Flush;
443begin
444SetCount(0);
445end;
446
447procedure TGLZBaseArray.Clear;
448begin
449SetCount(0);
450SetCapacity(0);
451end;
452
453//procedure TGLZBaseArray.AdjustCapacityToAtLeast(const size: Integer);
454//begin
455// if FCapacity < Size then SetCapacity(size);
456//end;
457
458procedure TGLZBaseArray.Push(const Value : T);
459begin
460Add(Value);
461end;
462
463function TGLZBaseArray.Pop : T;
464begin
465Result := FData[FCount-1];
466end;
467
468function TGLZBaseArray.First : T;
469begin
470Result := FData[0];
471end;
472
473function TGLZBaseArray.Last : T;
474begin
475Result := Pop;
476end;
477
478function TGLZBaseArray.Next : T;
479begin
480Result := FData[FPosition];
481if (FPosition < FCount) then Inc(FPosition);
482end;
483
484function TGLZBaseArray.Prev : T;
485begin
486Result := FData[FPosition];
487if (FPosition > 0) then Dec(FPosition);
488end;
489
490function TGLZBaseArray.Current : T;
491begin
492Result := FData[FPosition];
493end;
494
495function TGLZBaseArray.MoveNext : Boolean;
496begin
497Result := false;
498if (FPosition >= FCount-1) then exit;
499Result := True;
500Inc(FPosition);
501end;
502
503function TGLZBaseArray.MovePrev : Boolean;
504begin
505Result := false;
506if (FPosition <= 0 ) then exit;
507Result := True;
508Dec(FPosition);
509end;
510
511function TGLZBaseArray.MoveFirst : Boolean;
512begin
513{$ifdef DEBUG}
514Assert(FCount>0);
515{$endif}
516result := true;
517FPosition := 0;
518end;
519
520function TGLZBaseArray.MoveLast : Boolean;
521begin
522{$ifdef DEBUG}
523Assert(FCount>0);
524{$endif}
525result := true;
526FPosition := FCount-1;
527end;
528
529function TGLZBaseArray.GetPosition : SizeUInt;
530begin
531Result := FPosition;
532end;
533
534function TGLZBaseArray.Seek(const pos : SizeUInt; const StartAt : Byte) : boolean;
535var
536newpos : SizeUInt;
537begin
538{$ifdef DEBUG}
539Assert(Position < FCount);
540{$endif}
541result := true;
542Case StartAt of
5430: newpos := Pos; // From Beginning
5441:
545begin
546newpos := (FPosition-1) + Pos; // From Current positon
547if newpos >= FCount then
548begin
549//newpos := FCount-1;
550result := false;
551end;
552end;
5532:
554begin
555newpos := (FCount-1) - Pos; // From End;
556if newpos=0 then
557begin
558//newpos := 0;
559result := false;
560end;
561end;
562else newpos := pos;
563end;
564if result then FPosition := newpos;
565end;
566
567function TGLZBaseArray.MoveTo(Position:SizeUInt) : Boolean;
568begin
569result:= Self.Seek(Position, 0);
570end;
571
572function TGLZBaseArray.IsEndOfArray : Boolean;
573begin
574result := (FPosition >= FCount);
575end;
576
577{%endregion%}
578
579{%region%=====[ TGLZBaseArrayMap2D ]============================================}
580
581function TGLZBaseArrayMap2D.GetValue2D(x, y : SizeUInt) : T;
582begin
583{$ifdef DEBUG}
584assert((x<FCols) and (y<FRows));
585{$endif}
586Result := FData[y*FCols+X];
587end;
588
589procedure TGLZBaseArrayMap2D.SetValue2D(x, y : SizeUInt; AValue : T);
590var
591pos : SizeUint;
592begin
593{$ifdef DEBUG}
594assert((x<FCols) and (y<FRows));
595{$endif}
596pos := (y*FCols+x);
597{$ifdef DEBUGLOG}
598GlobalLogger.LogStatus('NbRows, NbCols : '+Inttostr(FRows)+', '+Inttostr(FCols));
599GlobalLogger.LogStatus('Set to : '+Inttostr(x)+', '+Inttostr(y));
600GlobalLogger.LogStatus('Set at : '+Inttostr(pos));
601{$endif}
602if FData[pos] = AValue then exit;
603FData[pos] := AValue;
604end;
605
606constructor TGLZBaseArrayMap2D.Create(Rows, Cols : SizeUInt);
607begin
608Inherited Create(Rows*Cols);
609FRows := Rows;
610FCols := Cols;
611end;
612
613constructor TGLZBaseArrayMap2D.CreateParented(AParentData : Pointer; Rows, Cols : SizeUInt);
614begin
615Inherited CreateParented(AParentData, Rows*Cols);
616end;
617
618function TGLZBaseArrayMap2D.MoveTo(Row : Integer; Position : Integer) : Boolean;
619begin
620result := Inherited MoveTo(Row*Position);
621end;
622
623{%endregion%}
624
625end.
626
627