-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathObjectsMin.pas
13900 lines (13162 loc) · 347 KB
/
ObjectsMin.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/////////////////////////////////////////////////
// //
// Objects 4.17 ( general release ) //
// //
// Data storing and processing classes //
// //
// Copyright (c) 2000, Andrew N. Driazgov //
// e-mail: andrey@asp.tstu.ru //
// //
// Last updated: November 15, 2000 //
// //
/////////////////////////////////////////////////
unit ObjectsMin;
{$PIC ON}
{$IFDEF FPC}
{$MODE Delphi}
{$ELSE}
{$ENDIF}
{$H+} // as objects_a.pas QQQQQQQ 64bit
// QQQQQQQ 64bit {$H+}$LONGSTRINGS local compiler directives have the same meaning and determine whether the compiler interprets the reserved word String as an String.
interface
uses
{$IFDEF WINDOWS}
Windows,
{$ENDIF}
SysUtils, Classes, QStringsMin;
// from NetWait.pas
const
nwNone = 0;
nwCancel = -1;
nwIgnore = -2;
nwRetry = -3;
{ Base constant for ID user objects. This objects indicators must be obtained
by adding some positive constant to stConst
}
stConst = 1000;
{ Constants for registering of standart types. Theese types are registered
in initialization section of this unit
}
rg01_TVCollection = 50;
rg01_TVStringCollection = 51;
rg01_TVUniNumberObj = stConst-21;
rg01_TVUniNumberColl = stConst-22;
rg01_TVUniNameObj = stConst-23;
rg01_TVUniNameColl = stConst-24;
rg01_TVIntegerSet = stConst-25;
rg01_TVWordSet = stConst-26;
rg01_TVRandomGenerator = stConst-27;
rg01_TVApNumberObj = stConst-1;
rg01_TVApNumberColl = stConst-2;
rg01_TVApSortNumberColl = stConst-3;
rg01_TVApNameObj = stConst-4;
rg01_TVApNameColl = stConst-5;
rg01_TVApSortNameColl = stConst-6;
{ Max number of elements in usual (big) collection }
MaxCollectionSize = 536870896;
{ Max number of elements in collection compatible with Turbo Vision }
MaxTVCompatibleCollSize = 16380;
{ Consnt to be used as second argument of function TVStream.Seek }
soFromBeginning = 0; // Positioning respect to the begin of file
soFromCurrent = 1; // Positioning respect to the current position
soFromEnd = 2; // Positioning respect to the end of file
{ File blocking regims}
lkShareExclusive = $0010; // File hot accessible for othe users
lkShareDenyWrite = $0020; // File could be open read only
lkShareDenyRead = $0030; // File could beopen write only
lkShareDenyNone = $0040; // File could be read and written
{ File open regims }
fmOpenReadOnly = fmOpenRead or lkShareDenyNone; // Open to read only
// QQ fmOpenExclusive for ReadOnly now
// fmOpenExclusive = fmOpenRead or lkShareExclusive; // Open in exclusive access
// QQ was
fmOpenExclusive = fmOpenReadWrite or lkShareExclusive; // Open in exclusive access
fmCreate = $FFFF; // Work with just created file (exclusive access)
{ Values, returned by function Load/Save(...)Object, Open(...) }
lsSuccess = 0; // No errors
lsAborted = -1; // File is blocked, "cancel operation" command was chosen
lsIgnored = -2; // File is blocked, "ignore error" command was chosen
lsNewResourceCreated = 1; // New depository or resource is created
{ Default argument for function TVStream.CopyFrom }
cfCopyAllData = -1; // Copy all date
{ Constants for margins including in search }
rtInclude = 0; // Margin is included
rtExclude = 1; // Margin is not included
rtInfinite = 2; // Margin is not checked
{ Standart index of TVCollection }
StdIndex = 'Internal';
{ Index names in collections of types UniColl and ApColl }
IndexBy_Number = 'Number';
IndexBy_Name = 'Name';
{ Index types for the key searches }
itNone = $00; // Nonstandart search
itShortint = $01;
itByte = $02;
itSmallint = $03;
itWord = $04;
itInteger = $05;
itCardinal = $06;
itPointer = $07; // Compared as LongWord
itInt64 = $08;
itCurrency = $09;
itTDateTime = $0A;
itSingle = $0B;
itDouble = $0C;
itComp = $0E;
itString = $0F; // Case sensitive
itPChar = $10; // Case sensitive
itString_I = $20; // Case Insensitive
itPChar_I = $30; // Case Insensitive
itUserCmp = $40; // Comapison function is user-defined
{ Variable TVProtection.Validation meanings}
pvNone = $0000;
pvCRC32 = $0001;
pvSHA1 = $0002;
{ Variable TVProtection.Encryption meanings}
peNone = $0000;
peRC4 = $0001;
peRC6_RC4 = $0009; // Key - RC6(CBC), data - RC4
peCAST6_RC4 = $0011; // Key - CAST-256(CBC), data - RC4
peRC6 = $0002; // CFB
peCAST6 = $0004; // CFB
type
TVUniCollection = class;
TVStream = class;
{
Base class TVObject. Includes object "version". Every object must can
load (with constructor Load) any of its versions. Method Store saves only one
version, which was registered (RegisterTVObject) as saveable. Method Clone
creates the object instance copy (this metod must be overlaped in any descendants
of TVObject, where new fields were added. See for instance TVUniNameObj.Clone
}
TVObject = class(TObject)
public
constructor Create; virtual;
constructor Load(S: TVStream; Version: Word); virtual;
procedure Store(S: TVStream); virtual;
function Clone: Pointer; virtual; // Object cloning
end;
TVObjectClassType = class of TVObject;
PTVItemList = ^TVItemList;
TVItemList = array[0..MaxCollectionSize - 1] of Pointer;
{ Prototype of the function which compares two records.
Return value must be below zero if the first record is smaller than the second one,
above zero if the first record is grater than the second one,
zero if the first record is equal to the second one,
}
TVCollSortCompare = function (Item1, Item2: Pointer): Integer;
{ TVIndexCollection }
TV_KeyOf_Shortint = function(Item: Pointer): Shortint;
TV_KeyOf_Byte = function(Item: Pointer): Byte;
TV_KeyOf_Smallint = function(Item: Pointer): Smallint;
TV_KeyOf_Word = function(Item: Pointer): Word;
TV_KeyOf_Integer = function(Item: Pointer): Integer;
TV_KeyOf_Cardinal = function(Item: Pointer): Cardinal;
TV_KeyOf_Pointer = function(Item: Pointer): Pointer;
TV_KeyOf_Int64 = function(Item: Pointer): Int64;
TV_KeyOf_Currency = function(Item: Pointer): Currency;
TV_KeyOf_TDateTime = function(Item: Pointer): TDateTime;
TV_KeyOf_Single = function(Item: Pointer): Single;
TV_KeyOf_Double = function(Item: Pointer): Double;
TV_KeyOf_Comp = function(Item: Pointer): Comp;
TV_KeyOf_String = function(Item: Pointer): string;
TV_KeyOf_PChar = function(Item: Pointer): PAnsiChar;
TV_KeyOf_String_I = function(Item: Pointer): string;
TV_KeyOf_PChar_I = function(Item: Pointer): PAnsiChar;
TV_UserKeyCompare = function(Item, Key: Pointer): Integer;
// User function which confront record to the key (sopostavlyaet zapisj kljuchu)
// Return value is analogues to TVCollSortCompare.
PTVIndexRec = ^TVIndexRec;
TVIndexRec = record
IndName: String; // Index name
IndList: PTVItemList; // Array of pointers to records (DO NOT CHANGE MANNUALY)
IndCompare: TVCollSortCompare; // Function to compare two records
Active: Boolean; // Active index
Regular: Boolean; // Index is regular (uporjadochennyi)
Descending: Boolean; // Descending index
Unique: Boolean; // Unique index
case IndType: Integer of // Key value type (for record search)
itShortint: (KeyOf_Shortint: TV_KeyOf_Shortint); // Function, wich returns
itByte: (KeyOf_Byte: TV_KeyOf_Byte); // key value for
itSmallint: (KeyOf_Smallint: TV_KeyOf_Smallint); // the record
itWord: (KeyOf_Word: TV_KeyOf_Word);
itInteger: (KeyOf_Integer: TV_KeyOf_Integer);
itCardinal: (KeyOf_Cardinal: TV_KeyOf_Cardinal);
itPointer: (KeyOf_Pointer: TV_KeyOf_Pointer);
itInt64: (KeyOf_Int64: TV_KeyOf_Int64);
itCurrency: (KeyOf_Currency: TV_KeyOf_Currency);
itTDateTime: (KeyOf_TDateTime: TV_KeyOf_TDateTime);
itSingle: (KeyOf_Single: TV_KeyOf_Single);
itDouble: (KeyOf_Double: TV_KeyOf_Double);
itComp: (KeyOf_Comp: TV_KeyOf_Comp);
itString: (KeyOf_String: TV_KeyOf_String);
itPChar: (KeyOf_PChar: TV_KeyOf_PChar);
itString_I: (KeyOf_String_I: TV_KeyOf_String_I);
itPChar_I: (KeyOf_PChar_I: TV_KeyOf_PChar_I);
itUserCmp: (UserKeyCompare: TV_UserKeyCompare);
end;
PTVIndexList = ^TVIndexList;
TVIndexList = array[0..MaxCollectionSize - 1] of PTVIndexRec;
TVIndexCollection = class(TObject)
private
FList: PTVIndexList;
FCount: Integer;
FCapacity: Integer;
public
destructor Destroy; override;
procedure Add(PIR: PTVIndexRec);
procedure DeleteAndFree(PIR: PTVIndexRec);
function Find(const S: String): PTVIndexRec;
end;
{ Base class TVUniCollection (instances of this class is not to be created !!!)
Any collection descendant from TVUniCollection can have many indexes
Indexes are not saved on HDD, but rebuilded during collection loading.
Any index could be active, inactive or current.
Inactive index is not updated during inserting, deleting or changing of records.
Thus it does not allocate memory.
Active index is refreshed during collection loading,inserting, deleting or changing of records.
When user changes some field of a record (collection member) he calls method
UpdateIndexes. This method updates all active indexes. One of active indexes
is the current index (it may be changed with the property CurrIndex. Current index
defines default collection sorting. In acording to this sorting the records
could be returned with properties Items and List. With the current index
methods Add, Delete, DeleteObj, IndexOf,
First, Last, Insert, Exchange, Move, Sort work.
}
TVAskForInsertEvent = procedure(AColl: TVUniCollection; Item: Pointer;
var CanInsert: Boolean) of object;
TVInsertItemEvent = procedure(AColl: TVUniCollection;
Item: Pointer) of object;
TVAskForDeleteEvent = procedure(AColl: TVUniCollection; Item: Pointer;
var CanDelete, DeleteToBin: Boolean) of object;
TVDeleteItemEvent = procedure(AColl: TVUniCollection;
Item: Pointer) of object;
TVSetChangedEvent = procedure(AColl: TVUniCollection;
Value: Boolean) of object;
TVUniCollection = class(TVObject)
private
FList: PTVItemList;
FCount: Integer;
FCapacity: Integer;
FIndexes: TVIndexCollection;
FCurrentIndex: PTVIndexRec;
FBin: TVUniCollection;
FOwner: TVUniCollection;
FOnAskForInsert: TVAskForInsertEvent;
FOnInsertItem: TVInsertItemEvent;
FOnAskForDelete: TVAskForDeleteEvent;
FOnDeleteItem: TVDeleteItemEvent;
FOnSetChanged: TVSetChangedEvent;
FFreeIOD: Boolean;
FBig: Boolean;
FChanged: Boolean;
function AddToIndex(PIR: PTVIndexRec; Item: Pointer): Integer;
procedure DeleteFromIndex(PIR: PTVIndexRec; Item: Pointer);
procedure SetCurrIndex(PIR: PTVIndexRec);
procedure SetChanged(Value: Boolean);
protected
function Get(Index: Integer): Pointer;
procedure SetCapacity(NewCapacity: Integer);
procedure Grow;
procedure DoAskForInsert(Item: Pointer; var CanInsert: Boolean);
procedure DoInsertItem(Item: Pointer); virtual;
procedure DoAskForDelete(Item: Pointer; var CanDelete, DeleteToBin: Boolean); virtual;
procedure DoDeleteItem(Item: Pointer); virtual;
procedure DoSetChanged(Value: Boolean); virtual;
{ Methods whish must be overlapped in descendant collections
to work with objects who are not descendants of TVObject. }
function GetItem(S: TVStream): Pointer; virtual;
procedure PutItem(S: TVStream; Item: Pointer); virtual;
procedure FreeItem(Item: Pointer); virtual;
function CloneItem(Item: Pointer): Pointer; virtual;
public
{ Creat, read, delete, save, clone a collection
(with all elements)
}
constructor Create; override;
destructor Destroy; override;
constructor Load(S: TVStream; Version: Word); override;
procedure Store(S: TVStream); override;
function Clone: Pointer; override;
{ Add and delete elements. Function Add returns the numner (index) of the
added record in current index (the fist has number 0). While deleting
to basket, the record rewritten into collection Bin, which is saved with
main collection
}
function Add(Item: Pointer): Integer;
procedure Delete(Index: Integer; ToBin: Boolean = False);
procedure DeleteAndFree(Index: Integer);
procedure DeleteObj(Item: Pointer; ToBin: Boolean = False);
procedure DeleteObjAndFree(Item: Pointer);
procedure Clear; virtual;
procedure ClearAndFreeItems; virtual;
procedure ClearLights; // property Capacity is not changed
procedure ClearAndFreeItemsLights;
{ IndexOf returns number of pointed record for current index of collection}
function IndexOf(Item: Pointer): Integer;
{ First and last records in current index }
function First: Pointer;
function Last: Pointer;
{ This methods are designed for a work with unordered collections
(which has attribute Requal=False for current index). While calling of
Sort procedure, the first parameter is the function for comparasion
the second parameter is False for grouth (increase) ordering
and True - for decrease ordering
}
procedure Insert(Index: Integer; Item: Pointer);
procedure Exchange(Index1, Index2: Integer);
procedure Move(CurIndex, NewIndex: Integer);
procedure Sort(ACompare: TVCollSortCompare; ADesc: Boolean = False);
procedure ReverseItems;
{ If some fields of this collection are external,relating to another collection,
you for speed increase can add fields pointed to the objects of main collection.
Then with method UpdateLink overlapping you will update these pointers using
foreign key from current collection and main collection, transmitted in parameter
AColl. LinkID - link identifier (any foreign key has its own ID). RemoveLink
is used to remove (assignment of nil) for all pointers.
}
procedure UpdateLink(const LinkID: string; AColl: TVUniCollection); virtual;
procedure RemoveLink(const LinkID: string); virtual;
{ Add, delete, actvate, deactivate indexes.
UpdateIndexes procedure must be called any time when fields which infuence on
sorting are changed. SwitchToIndex makes active the index with name AIndName.
Initially, any record to store index information must be created
with the CreateIndexRec procedure.
}
procedure AddIndex(PIR: PTVIndexRec; SwitchTo: Boolean = False);
procedure DeleteIndex(const AIndName: string);
procedure UpdateIndex(const AIndName: string);
procedure ActivateIndex(const AIndName: string);
procedure DeactivateIndex(const AIndName: string);
procedure ActivateAllIndexes;
procedure DeactivateAllIndexes;
procedure UpdateIndexes;
procedure SwitchToIndex(const AIndName: String);
{ The work with indexes by pointers }
function GetIndexList(const AIndName: String): PTVItemList;
function GetIndexRec(const AIndName: String; Activate: Boolean = True): PTVIndexRec;
procedure ActivateIndexByPIR(PIR: PTVIndexRec);
procedure DeactivateIndexByPIR(PIR: PTVIndexRec);
function IndexOfByIndex(PIR: PTVIndexRec; Item: Pointer): Integer;
procedure UpdateIndexByPIR(PIR: PTVIndexRec);
{
Record seaching on key field. Function SearchIndex_XXX returns number
of record in index which was passed as the PIR parameter. The record is
respective to the Key AKey. If not found returns -1. Record of type
PTVIndexRec for a index can be obtained with the function GetIndexRec.
The first record has number 0.
}
function SearchIndex_Shortint(PIR: PTVIndexRec; AKey: Shortint): Integer;
function SearchIndex_Byte(PIR: PTVIndexRec; AKey: Byte): Integer;
function SearchIndex_Smallint(PIR: PTVIndexRec; AKey: Smallint): Integer;
function SearchIndex_Word(PIR: PTVIndexRec; AKey: Word): Integer;
function SearchIndex_Integer(PIR: PTVIndexRec; AKey: Integer): Integer;
function SearchIndex_Cardinal(PIR: PTVIndexRec; AKey: Cardinal): Integer;
function SearchIndex_Pointer(PIR: PTVIndexRec; AKey: Pointer): Integer;
function SearchIndex_Int64(PIR: PTVIndexRec; AKey: Int64): Integer;
function SearchIndex_Currency(PIR: PTVIndexRec; AKey: Currency): Integer;
function SearchIndex_TDateTime(PIR: PTVIndexRec; AKey: TDateTime): Integer;
function SearchIndex_Single(PIR: PTVIndexRec; AKey: Single): Integer;
function SearchIndex_Double(PIR: PTVIndexRec; AKey: Double): Integer;
function SearchIndex_Comp(PIR: PTVIndexRec; AKey: Comp): Integer;
function SearchIndex_String(PIR: PTVIndexRec; const AKey: String): Integer;
function SearchIndex_PChar(PIR: PTVIndexRec; AKey: PAnsiChar): Integer;
function SearchIndex_String_I(PIR: PTVIndexRec; const AKey: String): Integer;
function SearchIndex_PChar_I(PIR: PTVIndexRec; AKey: PAnsiChar): Integer;
function SearchIndex_UserCmp(PIR: PTVIndexRec; AKey: Pointer): Integer;
{
The Next record seaching on key field. The privious found record index (or -1)
is passed as parameter Index. In the same parameter the new found record number
returns (if the function result is True). If record was not found the function
returns False.
}
function SearchNext_Shortint(PIR: PTVIndexRec; AKey: Shortint; var Index: Integer): Boolean;
function SearchNext_Byte(PIR: PTVIndexRec; AKey: Byte; var Index: Integer): Boolean;
function SearchNext_Smallint(PIR: PTVIndexRec; AKey: Smallint; var Index: Integer): Boolean;
function SearchNext_Word(PIR: PTVIndexRec; AKey: Word; var Index: Integer): Boolean;
function SearchNext_Integer(PIR: PTVIndexRec; AKey: Integer; var Index: Integer): Boolean;
function SearchNext_Cardinal(PIR: PTVIndexRec; AKey: Cardinal; var Index: Integer): Boolean;
function SearchNext_Pointer(PIR: PTVIndexRec; AKey: Pointer; var Index: Integer): Boolean;
function SearchNext_Int64(PIR: PTVIndexRec; AKey: Int64; var Index: Integer): Boolean;
function SearchNext_Currency(PIR: PTVIndexRec; AKey: Currency; var Index: Integer): Boolean;
function SearchNext_TDateTime(PIR: PTVIndexRec; AKey: TDateTime; var Index: Integer): Boolean;
function SearchNext_Single(PIR: PTVIndexRec; AKey: Single; var Index: Integer): Boolean;
function SearchNext_Double(PIR: PTVIndexRec; AKey: Double; var Index: Integer): Boolean;
function SearchNext_Comp(PIR: PTVIndexRec; AKey: Comp; var Index: Integer): Boolean;
function SearchNext_String(PIR: PTVIndexRec; const AKey: String; var Index: Integer): Boolean;
function SearchNext_PChar(PIR: PTVIndexRec; AKey: PAnsiChar; var Index: Integer): Boolean;
function SearchNext_String_I(PIR: PTVIndexRec; const AKey: String; var Index: Integer): Boolean;
function SearchNext_PChar_I(PIR: PTVIndexRec; AKey: PAnsiChar; var Index: Integer): Boolean;
function SearchNext_UserCmp(PIR: PTVIndexRec; AKey: Pointer; var Index: Integer): Boolean;
{ Searchin of record by key which returns pointer to found record
(nil - not found) }
function SearchObj_Shortint(PIR: PTVIndexRec; AKey: Shortint): Pointer;
function SearchObj_Byte(PIR: PTVIndexRec; AKey: Byte): Pointer;
function SearchObj_Smallint(PIR: PTVIndexRec; AKey: Smallint): Pointer;
function SearchObj_Word(PIR: PTVIndexRec; AKey: Word): Pointer;
function SearchObj_Integer(PIR: PTVIndexRec; AKey: Integer): Pointer;
function SearchObj_Cardinal(PIR: PTVIndexRec; AKey: Cardinal): Pointer;
function SearchObj_Pointer(PIR: PTVIndexRec; AKey: Pointer): Pointer;
function SearchObj_Int64(PIR: PTVIndexRec; AKey: Int64): Pointer;
function SearchObj_Currency(PIR: PTVIndexRec; AKey: Currency): Pointer;
function SearchObj_TDateTime(PIR: PTVIndexRec; AKey: TDateTime): Pointer;
function SearchObj_Single(PIR: PTVIndexRec; AKey: Single): Pointer;
function SearchObj_Double(PIR: PTVIndexRec; AKey: Double): Pointer;
function SearchObj_Comp(PIR: PTVIndexRec; AKey: Comp): Pointer;
function SearchObj_String(PIR: PTVIndexRec; const AKey: String): Pointer;
function SearchObj_PChar(PIR: PTVIndexRec; AKey: PAnsiChar): Pointer;
function SearchObj_String_I(PIR: PTVIndexRec; const AKey: String): Pointer;
function SearchObj_PChar_I(PIR: PTVIndexRec; AKey: PAnsiChar): Pointer;
function SearchObj_UserCmp(PIR: PTVIndexRec; AKey: Pointer): Pointer;
{ Searching of records interval where key values are between LeftBound and
RightBound (wether bounds are included depends upon parameters LeftTerm
and RightTerm). Interval relates to the index PIR. If interval is found
parameter Index is the number of first element, and Result is equal to the
total number of records inside the interval. If nothing was founf the function
returns 0. Index PIR must be ordered.
}
function SelectRange_Shortint(PIR: PTVIndexRec; LeftBound, RightBound: Shortint;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_Byte(PIR: PTVIndexRec; LeftBound, RightBound: Byte;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_Smallint(PIR: PTVIndexRec; LeftBound, RightBound: Smallint;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_Word(PIR: PTVIndexRec; LeftBound, RightBound: Word;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_Integer(PIR: PTVIndexRec; LeftBound, RightBound: Integer;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_Cardinal(PIR: PTVIndexRec; LeftBound, RightBound: Cardinal;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_Pointer(PIR: PTVIndexRec; LeftBound, RightBound: Pointer;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_Int64(PIR: PTVIndexRec; LeftBound, RightBound: Int64;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_Currency(PIR: PTVIndexRec; LeftBound, RightBound: Currency;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_TDateTime(PIR: PTVIndexRec; LeftBound, RightBound: TDateTime;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_Single(PIR: PTVIndexRec; LeftBound, RightBound: Single;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_Double(PIR: PTVIndexRec; LeftBound, RightBound: Double;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_Comp(PIR: PTVIndexRec; LeftBound, RightBound: Comp;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_String(PIR: PTVIndexRec; const LeftBound, RightBound: String;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_PChar(PIR: PTVIndexRec; LeftBound, RightBound: PAnsiChar;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_String_I(PIR: PTVIndexRec; const LeftBound, RightBound: String;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_PChar_I(PIR: PTVIndexRec; LeftBound, RightBound: PAnsiChar;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
function SelectRange_UserCmp(PIR: PTVIndexRec; LeftBound, RightBound: Pointer;
var Index: Integer; LeftTerm: Integer = rtInclude; RightTerm: Integer = rtInclude): Integer;
{ If index passed as parameter PIR has type "String" then below functions
can be used to select record interval which have key begining from substring
passed with parameter S or P. Result is as in function SelectRange_XXX.
Index PIR must be ordered.
}
function StartWith_String(PIR: PTVIndexRec; const S: string; var Index: Integer): Integer;
function StartWith_PChar(PIR: PTVIndexRec; P: PAnsiChar; var Index: Integer): Integer;
function StartWith_String_I(PIR: PTVIndexRec; const S: string; var Index: Integer): Integer;
function StartWith_PChar_I(PIR: PTVIndexRec; P: PAnsiChar; var Index: Integer): Integer;
{ Collection-owner of the current collection. Property Changed of owner is set to
True if property Changed of the current collection is set. This property
can be used if the current collection is one of fields of records stored in
another collection, who will be its owner.
(Another collection is owner of the current collection.)
}
property Owner: TVUniCollection read FOwner write FOwner;
{ Basket, where records can be put while deleting. Usually the basket has the
same indexes as main collection (since it is created with method Create of main
collection. You must manually privent unique indexes violation in basket.
}
property Bin: TVUniCollection read FBin;
{ If FreeItemsOnDestroy is set to True (default),then while collection deleting
all its elements are freed (automatically-? with the call of TVObject.Free).
If yuo do not want such set FreeItemsOnDestroy to False
}
property FreeItemsOnDestroy: Boolean read FFreeIOD write FFreeIOD;
{ Current active index of the collection. Any collection must have at least
one active index. One of active indexes is current.
TVUniCollection has no indexes, thus to work with this class instans is impossible
TVUniCollection - abstract class ?
}
property CurrIndex: PTVIndexRec read FCurrentIndex write SetCurrIndex;
{ This property is usually used to access items. }
property Items[Index: Integer]: Pointer read Get; default;
{ This property also could be used to access items. It contains
the pointer to items list for current index. When working with this
property be carefull, since the boundaries do not checked. Dut you should not suppose
that the List wil not change when current index is not changed.
}
property List: PTVItemList read FList;
{ Number of elements for which memory is allocated. }
property Capacity: Integer read FCapacity write SetCapacity;
{ Number of elements in collection. }
property Count: Integer read FCount;
{ If Big=False the collection is saved in format compatible with TurboVision.
Default Big = True. }
property Big: Boolean read FBig write FBig;
{ Modification Flag. It does not work automatically while adding or deleting
record. User must set or unset it manually !!!
}
property Changed: Boolean read FChanged write SetChanged;
{ Next properties can be assigned with procedures to be called
during the query to add or delete a record,
and also during the adding or deleting a record and changing the flag Changed
}
property OnAskForInsert: TVAskForInsertEvent read FOnAskForInsert write FOnAskForInsert;
property OnInsertItem: TVInsertItemEvent read FOnInsertItem write FOnInsertItem;
property OnAskForDelete: TVAskForDeleteEvent read FOnAskForDelete write FOnAskForDelete;
property OnDeleteItem: TVDeleteItemEvent read FOnDeleteItem write FOnDeleteItem;
property OnSetChanged: TVSetChangedEvent read FOnSetChanged write FOnSetChanged;
end;
{ TVCollection - the simplest non-abstract collection (descendant of TVUniCollection),
has one unordered index (unnordered set of items, which can be saved on HDD
}
TVCollection = class(TVUniCollection)
public
constructor Create; override;
constructor CreateRefsList; virtual; // Creation of references ciollection, they are not deallocated automatically
constructor CreateFromList(ListObj: TList); // Creation of collection (analog of CreateRefsList) and copying into it the contents of TList
procedure CopyToList(ListObj: TList); // Copying of all pointers to record into TList
procedure MakeStdIndex; virtual;
end;
{ TVStringCollection - collection of strings }
PTVStringItemList = ^TVStringItemList;
TVStringItemList = array[0..MaxCollectionSize - 1] of String;
TVStringCollection = class(TVObject)
private
FList: PTVStringItemList;
FCount: Integer;
FCapacity: Integer;
FOwner: TVUniCollection;
FDuplicates: Boolean;
FBig: Boolean;
FChanged: Boolean;
procedure SetChanged(Value: Boolean);
function GetTextStr: String;
procedure SetTextStr(const Value: String);
protected
function Get(Index: Integer): String;
procedure SetCapacity(NewCapacity: Integer);
procedure Grow;
public
constructor Create; override;
constructor CreateFromStringList(StrList: TStringList); // Creation from TStringList
destructor Destroy; override;
constructor Load(S: TVStream; Version: Word); override;
procedure Store(S: TVStream); override;
function Clone: Pointer; override;
procedure CopyToStrings(StrList: TStrings); // Copying into TStrings (from Classes unit)
function Add(const S: string): Integer; // Adding a String. Result equal to the index of added String
procedure Clear; // Removing all strings from collection
procedure Delete(Index: Integer); // Removing the String by the number
function Find(const S: string; var Index: Integer): Boolean; // Searching for index
function First: string; // First String
function Last: string; // Last String
procedure ToUpperCase; // UpperCase all strings
procedure ToLowerCase; // LowerCase all strings
procedure ToUpLowerCase; // UpperCase of first letter, lowerCase -other letters all strings
procedure ConvertToAnsi; // All strings - into Windows code
procedure ConvertToOem; // All strings - into DOS (OEM) code
property Owner: TVUniCollection read FOwner write FOwner;
property Duplicates: Boolean read FDuplicates write FDuplicates; // If True, allow duplicates
property Big: Boolean read FBig write FBig; // If False, Turbo Vision format
property Strings[Index: Integer]: String read Get; default; // Items
property Text: String read GetTextStr write SetTextStr; // All strings as one text
property Capacity: Integer read FCapacity write SetCapacity;
property Count: Integer read FCount; // Number of strings in colection
property List: PTVStringItemList read FList;
property Changed: Boolean read FChanged write SetChanged;
end;
{ TVIntegerSet - unnordered set of integers (type Integer). }
PTVIntegerSetItemList = ^TVIntegerSetItemList;
TVIntegerSetItemList = array[0..MaxCollectionSize - 1] of Integer;
TVIntegerSet = class(TVObject)
private
FChanged: Boolean;
procedure SetChanged(Value: Boolean);
protected
function Get(Index: Integer): Integer;
procedure Grow;
public
List: PTVIntegerSetItemList; // List of elements
Count: Integer; // Number of Elements
Capacity: Integer; // Number to which Memory allocated for
Owner: TVUniCollection; // Collection-owner of the set
destructor Destroy; override;
constructor Load(S: TVStream; Version: Word); override;
procedure Store(S: TVStream); override;
function Clone: Pointer; override;
procedure Clear; // Remove all items
procedure Include(Number: Integer); // Include one integer
procedure Exclude(Number: Integer); // Exclude one integer
procedure Complement(Number: Integer); // Include one integer if it is not in the collection, exclude one integer if it is in the collection
function Test(Number: Integer): Boolean; // Test whether the integer in the set
procedure Delete(Index: Integer); // Remove one integer by its index (the first is 0)
procedure ReverseItems; // Reverse internal array
procedure SetCapacity(NewCapacity: Integer);
property Items[Index: Integer]: Integer read Get; default; // Items
property Changed: Boolean read FChanged write SetChanged;
end;
{ TVWordSet - unordered set of integers (type Word). }
PTVWordSetItemList = ^TVWordSetItemList;
TVWordSetItemList = array[0..MaxCollectionSize - 1] of Word;
TVWordSet = class(TVObject)
private
FChanged: Boolean;
procedure SetChanged(Value: Boolean);
protected
function Get(Index: Integer): Word;
procedure Grow;
public
List: PTVWordSetItemList; // List of elements
Count: Integer; // Number of Elements
Capacity: Integer; // Number to which Memory allocated for
Owner: TVUniCollection; // Collection-owner of the set
destructor Destroy; override;
constructor Load(S: TVStream; Version: Word); override;
procedure Store(S: TVStream); override;
function Clone: Pointer; override;
procedure Clear; // Remove all items
procedure Include(Number: Word); // Include one integer
procedure Exclude(Number: Word); // Exclude one integer
procedure Complement(Number: Word); // Include one integer if it is not in the collection, exclude one integer if it is in the collection
function Test(Number: Word): Boolean; // Test whether the integer in the set
procedure Delete(Index: Integer); // Remove one integer by its index (the first is 0)
procedure ReverseItems; // Reverse internal array
procedure SetCapacity(NewCapacity: Integer);
property Items[Index: Integer]: Word read Get; default; // Items
property Changed: Boolean read FChanged write SetChanged;
end;
{ TVRandomGenerator - random number generator Mersenne Twister. This class is used
to incapsulate such generator, save it on disk and load from disk
}
TVRandomGenerator = class(TVObject)
private
FID: TMTID;
public
constructor Create; override; // Initiate with random constant
constructor CreateFixed(Seed: LongWord = 4357); // Initiate with defined constant
destructor Destroy; override;
constructor Load(S: TVStream; Version: Word); override;
procedure Store(S: TVStream); override;
function Clone: Pointer; override;
{ Internal state changing on abitrarial String S and, if UseTSC=True,
on current CPU timer tic count }
procedure Update1(const S: string; UseTSC: Boolean = True); // method CAST-256
procedure Update2(const S: string; UseTSC: Boolean = True); // method RC6
property ID: TMTID read FID write FID; // Sensor ID
end;
TVUniNumberObj = class(TVObject)
private
FNumber: Integer;
public
function Clone: Pointer; override;
constructor Load(S: TVStream; Version: Word); override;
procedure Store(S: TVStream); override;
function IsEqual(Obj: Pointer): Boolean; virtual;
procedure Reconcile(OldObj, NewObj: Pointer); virtual;
property Number: Integer read FNumber write FNumber;
end;
{ TVUniNumberColl - basic collection , a parent for magority of user collections}
TVUniNumberColl = class(TVUniCollection)
private
FLastUsedNumber: Integer;
function GetUniqueNumber: Integer;
public
constructor Create; override;
constructor Load(S: TVStream; Version: Word); override;
procedure Store(S: TVStream); override;
function Clone: Pointer; override;
procedure MakeIndexBy_Number; virtual;
{ Search object by number. }
function SearchNumberObj(N: Integer): Pointer;
{ Search object by number but returns the index for carrrent index or -1. }
function SearchNumberIndex(N: Integer): Integer;
{ Test existense of element with given number. }
function NumberExists(N: Integer): Boolean;
{ Rollback (OTKAT) of last number get from property UniqueNumber. In future
this number will be assigned to another record. }
procedure RollbackNumber(N: Integer);
{ Last number get while reading property UniqueNumber. }
property LastUsedNumber: Integer read FLastUsedNumber write FLastUsedNumber;
{ Uniq number for new record. }
property UniqueNumber: Integer read GetUniqueNumber;
end;
{ TVUniNameObj - descendant of TVUniNumberObj, has field Name.
DB records often have String field which can be used as ID.
TVUniNameObj is used with TVUniNameColl. Field Name is uhique by default.
}
TVUniNameObj = class(TVUniNumberObj)
private
FName: string;
public
function Clone: Pointer; override;
constructor Load(S: TVStream; Version: Word); override;
procedure Store(S: TVStream); override;
function IsEqual(Obj: Pointer): Boolean; override;
procedure Reconcile(OldObj, NewObj: Pointer); override;
property Name: string read FName write FName;
end;
{ TVUniNameColl - collection of objects descendant from TVUniNameObj. }
TVUniNameColl = class(TVUniNumberColl)
public
constructor Create; override;
procedure MakeIndexBy_Name; virtual;
{ Search object by field Name. }
function SearchNameObj(const Name: string): Pointer;
function SearchNameIndex(const Name: string): Integer;
{ Search next object by given field Name. Index parameter
must be equal to index of previous found object or -1}
function SearchNextNameIndex(const Name: string; var Index: Integer): Boolean;
{ Get field Number from field Name and vise versa. }
function GetNumberByName(const Name: string): Integer;
function GetNameByNumber(N: Integer): string;
end;
TVSecurityKey = array[0..47] of Byte; // for peCAST6 and peCAST6_RC4 only first 32 bytes are used [0..31]
{ Structures to protect data from corruption (modificatio) and}
PTVProtection = ^TVProtection;
TVProtection = record
Validation: Word; // Data verificztion
Encryption: Word; // Crypt method
KeyData: TVSecurityKey; // Crypt key in use
KeyLen: Cardinal; // Current Length of key
RandID: TMTID; // PSP generator to form session key
XXX1,XXX2: LongWord; // Reserved
Next: PTVProtection; // Reserved
end;
{ TVStream - class for read/write operations. When opens for read only
it is used fast file in memory projection }
TVStream = class(TObject)
private
FMemoryStream: TMemoryStream; // 64
FHandle: Integer;
FFileName: string;
FDataView: Pointer;
FSecurity: PTVProtection;
FData: Pointer;
FFileSize: Integer;
FMode: Word;
function GetPosition: Integer;
procedure SetPosition(Pos: Integer);
function GetSize: Integer;
procedure SetSize(NewSize: Integer);
public
constructor Create;
destructor Destroy; override;
procedure OpenFile(const AFileName: String; AMode: Word); // Open existent file
procedure CreateFile(const AFileName: String); // Create new file
procedure CloseFile; // Close File
procedure Read(var Buffer; Count: Integer); // Read Count bytes from stream into Buffer
procedure ReadB(var Buffer; Count: Integer); // As above for big fragments
procedure Write(const Buffer; Count: Integer); // Write Count bytes from Buffer into stream
procedure Skip(Count: Integer); // When next readiding omit Count bytes
function Seek(Offset, Origin: Integer): Integer; // Stream positioning
function CopyFrom(Source: TVStream; Count: Integer = cfCopyAllData): Integer; // Copy data from another stream
function Get(Security: PTVProtection = nil): TVObject; // Read object from stream
procedure Put(P: TVObject; Security: PTVProtection = nil); // Write object into stream
procedure Truncate; // Set stream end in current position
procedure Flush; // Write data from cash to disk
function ReadStr: String; // Read String (max 255 chars)
procedure WriteStr(const S: String); // Write String (max 255 chars)
function ReadLongStr: String; // Read String (any length)
procedure WriteLongStr(const S: String); // Write String (any length)
function ReadStrRLE: String; // Read String compressed with RLE method
procedure WriteStrRLE(const S: String); // Write tString compressed with RLE method
function ReadOemStr: String; // Read String in DOS encoding (with converting to ANSI)
procedure WriteOemStr(const S: String); // Write String in DOS encoding (with converting to OEM)
function ReadFixedStr(Len: Byte): String; // Read fixed length String in DOS encoding(with converting to ANSI)
procedure WriteFixedStr(const S: String; Len: Byte); // Write fixed length String in DOS encoding (with converting to Oem)
function StrRead: PAnsiChar; // Read Dos-String of type PAnsiChar (with converting to ANSI)
procedure StrWrite(P: PAnsiChar); // Write Dos-String of type PAnsiChar(with converting to Oem)
function ReadRealAsCurrency: Currency; // Read type Real48 as Currency
procedure WriteCurrencyAsReal(V: Currency); // Write type Currency as Real48
function ReadRealAsDouble: Double; // Read type Real48 as Double
procedure WriteDoubleAsReal(V: Double); // Write type Double as Real48
property Position: Integer read GetPosition write SetPosition; // Current position in stream
property Size: Integer read GetSize write SetSize; // File size in bytes
property FileName: string read FFileName; // Stream FileName
property Handle: Integer read FHandle; // File handle
property Mode: Word read FMode; // File open mode (regim)
end;
{ TVStorage - class-storage. It is a file, wich
simultaneously stores a lot number of different (or one-type) objects
with the access to them by key. The key is of type
Integer. Any object (besides the key) has the corresponding tag - some abitrarily
type Integer for user (programmer) perposes. At any time any number of users
can read data from storage, but to write something into the storage user must
open it in exclusive access (it is made automatically). While deleting/rewriting
into a storage it (the storage) will be fragmented. You can set regim
when it will be automatically compressed (property PackOnFly set True) or
you can set the maximum fragmentation procent before defragmentation
(property MaxGarbagePercent).
}
PTVStorageItem = ^TVStorageItem;
TVStorageItem = record
Key: Integer;
Size: Integer;
Pos: Integer;
Tag: Integer;
end;
PTVStorageItemList = ^TVStorageItemList;
TVStorageItemList = array[0..99999999] of TVStorageItem;
PTVSortStgList = ^TVSortStgList;
TVSortStgList = array[0..99999999] of PTVStorageItem;
TVStorage = class(TObject)
private
FList: PTVStorageItemList;
FCount: Integer;
FCapacity: Integer;
FStream: TVStream;
FIndexPos: Integer;
FInfoStr: string; // QQQQQQ 64bit as objects_a.pas was String
FSizeOfFragments: Integer;
FMaxGarbagePercent: Single;
FPackOnFly: Boolean;
FShrinkOnFlush: Boolean;
FModified: Boolean;
function GetReadOnly: Boolean;
function GetFileName: String;
procedure SetCapacity(NewCapacity: Integer);
function InterGet(Key: Integer): TVObject;
procedure InterPut(Key: Integer; Item: TVObject);
public
constructor Create(AStream: TVStream);
destructor Destroy; override;
function Get(Key: Integer; Security: PTVProtection = nil): TVObject; // Read object
function GetTg(Key: Integer; var ATag: Integer; Security: PTVProtection = nil): TVObject; // Read object and its tag
procedure Put(Key: Integer; Item: TVObject; Security: PTVProtection = nil); // Write object
procedure PutTg(Key: Integer; Item: TVObject; ATag: Integer; Security: PTVProtection = nil); // Write object with its tag
procedure Delete(Key: Integer); // Delete object by key
function Find(AKey: Integer; var Index: Integer): Boolean; // Search Akey key ID in key collection
function KeyExists(Key: Integer): Boolean; // Test key existence in storage
function GetAt(Index: Integer; Security: PTVProtection = nil): TVObject; // Read object by index in keys collection
procedure DeleteAt(Index: Integer); // Delete index in keys collection
function KeyAt(Index: Integer): Integer; // Key by index in keys collection
function TagAt(Index: Integer): Integer; // Tag by index in keys collection
procedure Sweep; // Defragment storage
procedure Flush(ForcedWrite: Boolean = False); // Save data on disk
property FileName: String read GetFileName; // FileName of storage
property SizeOfFragments: Integer read FSizeOfFragments; // The size of fragmented region
property ShrinkOnFlush: Boolean read FShrinkOnFlush write FShrinkOnFlush; // Decrease storage size
property Modified: Boolean read FModified write FModified; // True, - was modified
property ReadOnly: Boolean read GetReadOnly; // True,if open as readonly
property InfoStr: String read FInfoStr write FInfoStr; // String to be written in begin of storage file
property MaxGarbagePercent: Single read FMaxGarbagePercent write FMaxGarbagePercent; // Maximum fragmentation procent
property PackOnFly: Boolean read FPackOnFly write FPackOnFly; // Pack storage on the fly
property List: PTVStorageItemList read FList; // Direct access to items
property Items[Key: Integer]: TVObject read InterGet write InterPut; default; // Access to unprotected objects by key
property Count: Integer read FCount; // Count of elements
property Capacity: Integer read FCapacity write SetCapacity;
end;
{ Objects for compatibility with Turbo Vision. Do NOT use ! }
{ Basic class TVSortedCollection }