modules/up/src/rpsl/gnu/PrefixRange.XPlex.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- PrefixRangeXPlex
- PrefixRangeXPlex
- PrefixRangeXPlex
- make_initial_chunks
- PrefixRangeXPlex
- PrefixRangeXPlex
- cache
- cache
- owns
- dosucc
- dopred
- add_high
- del_high
- add_low
- del_low
- reverse
- fill
- fill
- clear
- OK
1 // This may look like C code, but it is really -*- C++ -*-
2 /*
3 Copyright (C) 1988 Free Software Foundation
4 written by Doug Lea (dl@rocky.oswego.edu)
5 based on code by Marc Shapiro (shapiro@sor.inria.fr)
6
7 This file is part of the GNU C++ Library. This library is free
8 software; you can redistribute it and/or modify it under the terms of
9 the GNU Library General Public License as published by the Free
10 Software Foundation; either version 2 of the License, or (at your
11 option) any later version. This library is distributed in the hope
12 that it will be useful, but WITHOUT ANY WARRANTY; without even the
13 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the GNU Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #ifdef __GNUG__
21 #pragma implementation
22 #endif
23 #include "PrefixRange.XPlex.h"
24
25
26 PrefixRangeXPlex:: PrefixRangeXPlex()
/* [<][>][^][v][top][bottom][index][help] */
27 {
28 lo = fnc = 0;
29 csize = DEFAULT_INITIAL_CAPACITY;
30 PrefixRange* data = new PrefixRange[csize];
31 set_cache(new PrefixRangeIChunk(data, lo, lo, fnc, lo+csize));
32 hd = ch;
33 }
34
35 PrefixRangeXPlex:: PrefixRangeXPlex(int chunksize)
/* [<][>][^][v][top][bottom][index][help] */
36 {
37 if (chunksize == 0) error("invalid constructor specification");
38 lo = fnc = 0;
39 if (chunksize > 0)
40 {
41 csize = chunksize;
42 PrefixRange* data = new PrefixRange[csize];
43 set_cache(new PrefixRangeIChunk(data, lo, lo, fnc, csize));
44 hd = ch;
45 }
46 else
47 {
48 csize = -chunksize;
49 PrefixRange* data = new PrefixRange[csize];
50 set_cache(new PrefixRangeIChunk(data, chunksize, lo, fnc, fnc));
51 hd = ch;
52 }
53 }
54
55
56 PrefixRangeXPlex:: PrefixRangeXPlex(int l, int chunksize)
/* [<][>][^][v][top][bottom][index][help] */
57 {
58 if (chunksize == 0) error("invalid constructor specification");
59 lo = fnc = l;
60 if (chunksize > 0)
61 {
62 csize = chunksize;
63 PrefixRange* data = new PrefixRange[csize];
64 set_cache(new PrefixRangeIChunk(data, lo, lo, fnc, csize+lo));
65 hd = ch;
66 }
67 else
68 {
69 csize = -chunksize;
70 PrefixRange* data = new PrefixRange[csize];
71 set_cache(new PrefixRangeIChunk(data, chunksize+lo, lo, fnc, fnc));
72 hd = ch;
73 }
74 }
75
76 void PrefixRangeXPlex::make_initial_chunks(int up)
/* [<][>][^][v][top][bottom][index][help] */
77 {
78 int need = fnc - lo;
79 hd = 0;
80 if (up)
81 {
82 int l = lo;
83 do
84 {
85 int sz;
86 if (need >= csize)
87 sz = csize;
88 else
89 sz = need;
90 PrefixRange* data = new PrefixRange [csize];
91 PrefixRangeIChunk* h = new PrefixRangeIChunk(data, l, l, l+sz, l+csize);
92 if (hd != 0)
93 h->link_to_next(hd);
94 else
95 hd = h;
96 l += sz;
97 need -= sz;
98 } while (need > 0);
99 }
100 else
101 {
102 int hi = fnc;
103 do
104 {
105 int sz;
106 if (need >= csize)
107 sz = csize;
108 else
109 sz = need;
110 PrefixRange* data = new PrefixRange [csize];
111 PrefixRangeIChunk* h = new PrefixRangeIChunk(data, hi-csize, hi-sz, hi, hi);
112 if (hd != 0)
113 h->link_to_next(hd);
114 hd = h;
115 hi -= sz;
116 need -= sz;
117 } while (need > 0);
118 }
119 set_cache(hd);
120 }
121
122 PrefixRangeXPlex:: PrefixRangeXPlex(int l, int hi, const PrefixRange& initval, int chunksize)
/* [<][>][^][v][top][bottom][index][help] */
123 {
124 lo = l;
125 fnc = hi + 1;
126 if (chunksize == 0)
127 {
128 csize = fnc - l;
129 make_initial_chunks(1);
130 }
131 else if (chunksize < 0)
132 {
133 csize = -chunksize;
134 make_initial_chunks(0);
135 }
136 else
137 {
138 csize = chunksize;
139 make_initial_chunks(1);
140 }
141 fill(initval);
142 }
143
144 PrefixRangeXPlex::PrefixRangeXPlex(const PrefixRangeXPlex& a)
/* [<][>][^][v][top][bottom][index][help] */
145 {
146 lo = a.lo;
147 fnc = a.fnc;
148 csize = a.csize;
149 make_initial_chunks();
150 for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i];
151 }
152
153 void PrefixRangeXPlex::operator= (const PrefixRangeXPlex& a)
154 {
155 if (&a != this)
156 {
157 invalidate();
158 lo = a.lo;
159 fnc = a.fnc;
160 csize = a.csize;
161 make_initial_chunks();
162 for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i];
163 }
164 }
165
166
167 void PrefixRangeXPlex::cache(int idx) const
/* [<][>][^][v][top][bottom][index][help] */
168 {
169 const PrefixRangeIChunk* tail = tl();
170 const PrefixRangeIChunk* t = ch;
171 while (idx >= t->fence_index())
172 {
173 if (t == tail) index_error();
174 t = (t->next());
175 }
176 while (idx < t->low_index())
177 {
178 if (t == hd) index_error();
179 t = (t->prev());
180 }
181 set_cache(t);
182 }
183
184
185 void PrefixRangeXPlex::cache(const PrefixRange* p) const
/* [<][>][^][v][top][bottom][index][help] */
186 {
187 const PrefixRangeIChunk* old = ch;
188 const PrefixRangeIChunk* t = ch;
189 while (!t->actual_pointer(p))
190 {
191 t = (t->next());
192 if (t == old) index_error();
193 }
194 set_cache(t);
195 }
196
197 int PrefixRangeXPlex::owns(Pix px) const
/* [<][>][^][v][top][bottom][index][help] */
198 {
199 PrefixRange* p = (PrefixRange*)px;
200 const PrefixRangeIChunk* old = ch;
201 const PrefixRangeIChunk* t = ch;
202 while (!t->actual_pointer(p))
203 {
204 t = (t->next());
205 if (t == old) { set_cache(t); return 0; }
206 }
207 set_cache(t);
208 return 1;
209 }
210
211
212 PrefixRange* PrefixRangeXPlex::dosucc(const PrefixRange* p) const
/* [<][>][^][v][top][bottom][index][help] */
213 {
214 if (p == 0) return 0;
215 const PrefixRangeIChunk* old = ch;
216 const PrefixRangeIChunk* t = ch;
217
218 while (!t->actual_pointer(p))
219 {
220 t = (t->next());
221 if (t == old) return 0;
222 }
223 int i = t->index_of(p) + 1;
224 if (i >= fnc) return 0;
225 if (i >= t->fence_index()) t = (t->next());
226 set_cache(t);
227 return (t->pointer_to(i));
228 }
229
230 PrefixRange* PrefixRangeXPlex::dopred(const PrefixRange* p) const
/* [<][>][^][v][top][bottom][index][help] */
231 {
232 if (p == 0) return 0;
233 const PrefixRangeIChunk* old = ch;
234 const PrefixRangeIChunk* t = ch;
235 while (!t->actual_pointer(p))
236 {
237 t = (t->prev());
238 if (t == old) return 0;
239 }
240 int i = t->index_of(p) - 1;
241 if (i < lo) return 0;
242 if (i < t->low_index()) t = (t->prev());
243 set_cache(t);
244 return (t->pointer_to(i));
245 }
246
247
248 int PrefixRangeXPlex::add_high(const PrefixRange& elem)
/* [<][>][^][v][top][bottom][index][help] */
249 {
250 PrefixRangeIChunk* t = tl();
251 if (!t->can_grow_high())
252 {
253 if (t->PrefixRangeIChunk::empty() && one_chunk())
254 t->clear(fnc);
255 else
256 {
257 PrefixRange* data = new PrefixRange [csize];
258 t = (new PrefixRangeIChunk(data, fnc, fnc, fnc,fnc+csize));
259 t->link_to_prev(tl());
260 }
261 }
262 *((t->PrefixRangeIChunk::grow_high())) = elem;
263 set_cache(t);
264 return fnc++;
265 }
266
267 int PrefixRangeXPlex::del_high ()
/* [<][>][^][v][top][bottom][index][help] */
268 {
269 if (empty()) empty_error();
270 PrefixRangeIChunk* t = tl();
271 t->PrefixRangeIChunk::shrink_high();
272 if (t->PrefixRangeIChunk::empty() && !one_chunk())
273 {
274 PrefixRangeIChunk* pred = t->prev();
275 del_chunk(t);
276 t = pred;
277 }
278 set_cache(t);
279 return --fnc - 1;
280 }
281
282 int PrefixRangeXPlex::add_low (const PrefixRange& elem)
/* [<][>][^][v][top][bottom][index][help] */
283 {
284 PrefixRangeIChunk* t = hd;
285 if (!t->can_grow_low())
286 {
287 if (t->PrefixRangeIChunk::empty() && one_chunk())
288 t->cleardown(lo);
289 else
290 {
291 PrefixRange* data = new PrefixRange [csize];
292 hd = new PrefixRangeIChunk(data, lo-csize, lo, lo, lo);
293 hd->link_to_next(t);
294 t = hd;
295 }
296 }
297 *((t->PrefixRangeIChunk::grow_low())) = elem;
298 set_cache(t);
299 return --lo;
300 }
301
302
303 int PrefixRangeXPlex::del_low ()
/* [<][>][^][v][top][bottom][index][help] */
304 {
305 if (empty()) empty_error();
306 PrefixRangeIChunk* t = hd;
307 t->PrefixRangeIChunk::shrink_low();
308 if (t->PrefixRangeIChunk::empty() && !one_chunk())
309 {
310 hd = t->next();
311 del_chunk(t);
312 t = hd;
313 }
314 set_cache(t);
315 return ++lo;
316 }
317
318 void PrefixRangeXPlex::reverse()
/* [<][>][^][v][top][bottom][index][help] */
319 {
320 PrefixRange tmp;
321 int l = lo;
322 int h = fnc - 1;
323 PrefixRangeIChunk* loch = hd;
324 PrefixRangeIChunk* hich = tl();
325 while (l < h)
326 {
327 PrefixRange* lptr = loch->pointer_to(l);
328 PrefixRange* hptr = hich->pointer_to(h);
329 tmp = *lptr;
330 *lptr = *hptr;
331 *hptr = tmp;
332 if (++l >= loch->fence_index()) loch = loch->next();
333 if (--h < hich->low_index()) hich = hich->prev();
334 }
335 }
336
337 void PrefixRangeXPlex::fill(const PrefixRange& x)
/* [<][>][^][v][top][bottom][index][help] */
338 {
339 for (int i = lo; i < fnc; ++i) (*this)[i] = x;
340 }
341
342 void PrefixRangeXPlex::fill(const PrefixRange& x, int l, int hi)
/* [<][>][^][v][top][bottom][index][help] */
343 {
344 for (int i = l; i <= hi; ++i) (*this)[i] = x;
345 }
346
347
348 void PrefixRangeXPlex::clear()
/* [<][>][^][v][top][bottom][index][help] */
349 {
350 if (fnc != lo)
351 {
352 PrefixRangeIChunk* t = tl();
353 while (t != hd)
354 {
355 PrefixRangeIChunk* prv = t->prev();
356 del_chunk(t);
357 t = prv;
358 }
359 t->PrefixRangeIChunk::clear(lo);
360 set_cache(t);
361 fnc = lo;
362 }
363 }
364
365
366 int PrefixRangeXPlex::OK () const
/* [<][>][^][v][top][bottom][index][help] */
367 {
368 int v = hd != 0 && ch != 0; // at least one chunk
369
370 v &= fnc == tl()->fence_index();// last chunk fence == plex fence
371 v &= lo == ((hd))->PrefixRangeIChunk::low_index(); // first lo == plex lo
372
373 // loop for others:
374 int found_ch = 0; // to make sure ch is in list;
375 const PrefixRangeIChunk* t = (hd);
376 for (;;)
377 {
378 if (t == ch) ++found_ch;
379 v &= t->PrefixRangeIChunk::OK(); // each chunk is OK
380 if (t == tl())
381 break;
382 else // and has indices contiguous to succ
383 {
384 v &= t->top_index() == t->next()->base_index();
385 if (t != hd) // internal chunks full
386 {
387 v &= !t->empty();
388 v &= !t->can_grow_low();
389 v &= !t->can_grow_high();
390 }
391 t = t->next();
392 }
393 }
394 v &= found_ch == 1;
395 if (!v) error("invariant failure");
396 return v;
397 }