-
Notifications
You must be signed in to change notification settings - Fork 1
/
adtcontbase_impl.i
201 lines (171 loc) · 5.07 KB
/
adtcontbase_impl.i
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
{@discard
This file is a part of the PascalAdt library, which provides
commonly used algorithms and data structures for the FPC and Delphi
compilers.
Copyright (C) 2004, 2005 by Lukasz Czajka
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA }
{@discard
adtcontbase_impl.inc::prefix=&_mcp_prefix&::item_type=&ItemType&
}
&include adtcontbase.defs
&include adtcontbase_impl.mcp
&define Identity &_mcp_prefix&Identity
{ TContainerAdt members }
constructor TContainerAdt.Create;
begin
FDisposer := &_mcp_default_disposer(&ItemType);
FOwnsItems := true;
FGrabageCollector := TGrabageCollector.Create;
end;
constructor TContainerAdt.CreateCopy(const cont : TContainerAdt);
begin
Assert(cont <> nil, msgNilObject);
FDisposer := cont.FDisposer;
FOwnsItems := cont.FOwnsItems;
FGrabageCollector := TGrabageCollector.Create;
end;
destructor TContainerAdt.Destroy;
begin
FGrabageCollector.Free;
end;
procedure TContainerAdt.SetOwnsItems(b : Boolean);
begin
FOwnsItems := b;
end;
procedure TContainerAdt.SetDisposer(const proc : IUnaryFunctor);
begin
FDisposer := proc;
end;
function TContainerAdt.GetDisposer : IUnaryFunctor;
begin
Result := FDisposer;
end;
procedure TContainerAdt.BasicSwap(cont : TContainerAdt);
begin
ExchangePtr(FDisposer, cont.FDisposer);
ExchangeData(FOwnsItems, cont.FOwnsItems, SizeOf(Boolean));
end;
{$ifdef TEST_PASCAL_ADT }
procedure TContainerAdt.WriteLog(msg : String);
begin
WriteLogStream(msg);
end;
procedure TContainerAdt.WriteLog;
begin
WriteLogStream('');
end;
procedure TContainerAdt.LogStatus(mName : String);
begin
Inc(logNumber);
WriteLog;
WriteLog;
WriteLog('----------------------------------------------');
WriteLog('(' + IntToStr(logNumber) + ')');
WriteLog(mName);
WriteLog;
WriteLog('Size: ' + IntToStr(Size));
if FOwnsItems then
WriteLog('OwnsItems: true')
else
WriteLog('OwnsItems: false');
WriteLog('Existing iterators: ' +
IntToStr(FGrabageCollector.RegisteredObjects));
end;
function TContainerAdt.FormatItem(aitem : ItemType) : String;
begin
&if (&ItemType == String)
Result := aitem;
&elseif (&ItemType == TObject)
if aitem is TTestObject then
Result := IntToStr(TTestObject(aitem).Value)
else
Result := Format('<object address: %X>', [PointerValueType(aitem)]);
&elseif (&ItemType == Real)
Result := FloatToStr(aitem);
&elseif (&ItemType == Integer || &ItemType == Cardinal)
Result := IntToStr(aitem);
&elseif (&ItemType == Pointer)
Result := Format('<pointer: %X>', [PointerValueType(aitem)]);
&else
Result := '<not printable>';
&endif
end;
{$endif TEST_PASCAL_ADT }
procedure TContainerAdt.Swap(cont : TContainerAdt);
var
temp : TDynamicBuffer;
cont1, cont2 : TContainerAdt;
i : SizeType;
tempSize : SizeType;
aitem : ItemType;
begin
if Size < cont.Size then
begin
cont1 := self;
cont2 := cont;
end else
begin
cont1 := cont;
cont2 := self;
end;
BufferAllocate(temp, cont1.Size);
{ this try..finally produces a linking error with FPC 2.0 for some
strange reason }
// try
i := 0; { for exception handling }
tempSize := 0;
try
while cont1.CanExtract do
begin
aitem := cont1.ExtractItem; { may raise }
temp^.Items[i] := aitem;
Inc(tempSize);
end;
while cont2.CanExtract do
begin
aitem := cont2.ExtractItem; { may raise }
cont1.InsertItem(aitem); { may raise }
end;
for i := 0 to tempSize - 1 do
begin
cont2.InsertItem(temp^.Items[i]); { may raise }
end;
i := tempSize;
except
{ since the exception was probably raised by the InsertItem
routine there is no point in trying to re-insert the items
from temp; the only thing we can do here is to at least
dispose these items safely }
while i <> tempSize do
begin
with cont1 do
DisposeItem(temp^.Items[i]);
Inc(i);
end;
BufferDeallocate(temp);
raise;
end;
BasicSwap(cont);
// finally
BufferDeallocate(temp);
// end;
end;
procedure TContainerAdt.&<DisposeItem>(aitem : ItemType);
begin
&_mcp_dispose_item(aitem, FDisposer.Perform, OwnsItems, FDisposer);
end;
function TContainerAdt.CopySelf : TContainerAdt;
begin
Result := CopySelf(Identity);
end;