1 (* Copyright (C) DooM 2D:Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *)
16 {$INCLUDE a_modes.inc}
17 {.$DEFINE IDPOOL_CHECKS}
20 interface
22 // ////////////////////////////////////////////////////////////////////////// //
23 type
24 //TODO: implement getting n sequential ids
26 public
29 private
30 type
35 private
41 private
50 public
56 // returns InvalidId if there are no more free ids (or throws)
59 // it is NOT ok to release already released id
65 public
78 implementation
80 uses
81 SysUtils;
84 // ////////////////////////////////////////////////////////////////////////// //
86 begin
94 begin
101 var
103 begin
106 begin
109 if (f > 0) and (mRanges[f-1].last >= mRanges[f].first) then raise Exception.Create('invalid range order');
110 if (f > 0) and (mRanges[f-1].last+1 = mRanges[f].first) then raise Exception.Create('unmerged ranges');
117 var
119 begin
121 begin
125 if (f > 0) and (mRanges[f-1].last >= mRanges[f].first) then raise Exception.Create('invalid range order');
126 if (f > 0) and (mRanges[f-1].last+1 = mRanges[f].first) then raise Exception.Create('unmerged ranges');
132 begin
141 function TIdPool.getFreeIds (): Integer; inline; begin result := Integer(mMaxId+1-mUsedIds); end;
146 var
149 begin
152 // -1: not found
156 // yay! use binary search to find the range
160 begin
162 //!assert((mid >= 0) and (mid < len));
173 var
175 begin
185 var
187 begin
191 if (ii >= 0) then result := not ((aid >= mRanges[ii].first) and (aid <= mRanges[ii].last)) else result := true;
195 // returns InvalidId if there are no more free ids (or throws)
197 var
199 begin
201 begin
202 // no more ids
205 exit;
208 // delete first range?
210 begin
213 end
214 else
215 begin
223 // it is NOT ok to release already released id
225 var
227 begin
228 if (aid > mMaxId) then raise Exception.Create(Format('TIdPool: cannot release invalid id %u', [aid]));
229 // no available ids?
231 begin
232 // just create new range
239 exit;
241 // before first available id?
243 begin
244 // can we grow first range?
246 begin
247 // yep
249 end
250 else
251 begin
252 // nope, insert new first range
262 exit;
264 // after last available id?
266 begin
267 // can we grow last range?
269 begin
270 // yep
272 end
273 else
274 begin
275 // nope, insert new last range
284 exit;
286 // alas, no more easy cases; find the nearest range
288 if (ii < 0) then raise Exception.Create(Format('TIdPool: cannot release invalid id %u', [aid]));
289 if (aid >= mRanges[ii].first) and (aid <= mRanges[ii].last) then raise Exception.Create(Format('TIdPool: cannot release unallocated id %u', [aid]));
290 // ii should contain range where `first` is less than `aid`
293 {$IF DEFINED(IDPOOL_DEBUG_DUMPS)}writeln('aid=', aid, '; ii=', ii, ': [', mRanges[ii].first, '-', mRanges[ii].last, ']');{$ENDIF}
294 // can grow this range at the end?
296 begin
298 // yep; can merge ranges?
300 begin
301 // merge
306 end
307 else
308 begin
309 // change
311 {$IF DEFINED(IDPOOL_DEBUG_DUMPS)}if (ii+1 < mRangeUsed) then writeln(' ii+1=', ii+1, ': [', mRanges[ii+1].first, '-', mRanges[ii+1].last, ']');{$ENDIF}
316 exit;
318 // can grow next range at the start?
320 begin
321 // yep; can merge ranges?
323 begin
324 // merge
328 end
329 else
330 begin
331 // change
336 exit;
338 // cannot grow anything, insert empty range after ii