modules/up/src/gnug++/unsigned.XPlex.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- unsignedXPlex
- unsignedXPlex
- unsignedXPlex
- make_initial_chunks
- unsignedXPlex
- unsignedXPlex
- 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 "config.h"
24 #include "unsigned.XPlex.h"
25
26
27 unsignedXPlex:: unsignedXPlex()
/* [<][>][^][v][top][bottom][index][help] */
28 {
29 lo = fnc = 0;
30 csize = DEFAULT_INITIAL_CAPACITY;
31 unsigned* data = new unsigned[csize];
32 set_cache(new unsignedIChunk(data, lo, lo, fnc, lo+csize));
33 hd = ch;
34 }
35
36 unsignedXPlex:: unsignedXPlex(int chunksize)
/* [<][>][^][v][top][bottom][index][help] */
37 {
38 if (chunksize == 0) error("invalid constructor specification");
39 lo = fnc = 0;
40 if (chunksize > 0)
41 {
42 csize = chunksize;
43 unsigned* data = new unsigned[csize];
44 set_cache(new unsignedIChunk(data, lo, lo, fnc, csize));
45 hd = ch;
46 }
47 else
48 {
49 csize = -chunksize;
50 unsigned* data = new unsigned[csize];
51 set_cache(new unsignedIChunk(data, chunksize, lo, fnc, fnc));
52 hd = ch;
53 }
54 }
55
56
57 unsignedXPlex:: unsignedXPlex(int l, int chunksize)
/* [<][>][^][v][top][bottom][index][help] */
58 {
59 if (chunksize == 0) error("invalid constructor specification");
60 lo = fnc = l;
61 if (chunksize > 0)
62 {
63 csize = chunksize;
64 unsigned* data = new unsigned[csize];
65 set_cache(new unsignedIChunk(data, lo, lo, fnc, csize+lo));
66 hd = ch;
67 }
68 else
69 {
70 csize = -chunksize;
71 unsigned* data = new unsigned[csize];
72 set_cache(new unsignedIChunk(data, chunksize+lo, lo, fnc, fnc));
73 hd = ch;
74 }
75 }
76
77 void unsignedXPlex::make_initial_chunks(int up)
/* [<][>][^][v][top][bottom][index][help] */
78 {
79 int need = fnc - lo;
80 hd = 0;
81 if (up)
82 {
83 int l = lo;
84 do
85 {
86 int sz;
87 if (need >= csize)
88 sz = csize;
89 else
90 sz = need;
91 unsigned* data = new unsigned [csize];
92 unsignedIChunk* h = new unsignedIChunk(data, l, l, l+sz, l+csize);
93 if (hd != 0)
94 h->link_to_next(hd);
95 else
96 hd = h;
97 l += sz;
98 need -= sz;
99 } while (need > 0);
100 }
101 else
102 {
103 int hi = fnc;
104 do
105 {
106 int sz;
107 if (need >= csize)
108 sz = csize;
109 else
110 sz = need;
111 unsigned* data = new unsigned [csize];
112 unsignedIChunk* h = new unsignedIChunk(data, hi-csize, hi-sz, hi, hi);
113 if (hd != 0)
114 h->link_to_next(hd);
115 hd = h;
116 hi -= sz;
117 need -= sz;
118 } while (need > 0);
119 }
120 set_cache(hd);
121 }
122
123 unsignedXPlex:: unsignedXPlex(int l, int hi, const unsigned initval, int chunksize)
/* [<][>][^][v][top][bottom][index][help] */
124 {
125 lo = l;
126 fnc = hi + 1;
127 if (chunksize == 0)
128 {
129 csize = fnc - l;
130 make_initial_chunks(1);
131 }
132 else if (chunksize < 0)
133 {
134 csize = -chunksize;
135 make_initial_chunks(0);
136 }
137 else
138 {
139 csize = chunksize;
140 make_initial_chunks(1);
141 }
142 fill(initval);
143 }
144
145 unsignedXPlex::unsignedXPlex(const unsignedXPlex& a)
/* [<][>][^][v][top][bottom][index][help] */
146 {
147 lo = a.lo;
148 fnc = a.fnc;
149 csize = a.csize;
150 make_initial_chunks();
151 for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i];
152 }
153
154 void unsignedXPlex::operator= (const unsignedXPlex& a)
155 {
156 if (&a != this)
157 {
158 invalidate();
159 lo = a.lo;
160 fnc = a.fnc;
161 csize = a.csize;
162 make_initial_chunks();
163 for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i];
164 }
165 }
166
167
168 void unsignedXPlex::cache(int idx) const
/* [<][>][^][v][top][bottom][index][help] */
169 {
170 const unsignedIChunk* tail = tl();
171 const unsignedIChunk* t = ch;
172 while (idx >= t->fence_index())
173 {
174 if (t == tail) index_error();
175 t = (t->next());
176 }
177 while (idx < t->low_index())
178 {
179 if (t == hd) index_error();
180 t = (t->prev());
181 }
182 set_cache(t);
183 }
184
185
186 void unsignedXPlex::cache(const unsigned* p) const
/* [<][>][^][v][top][bottom][index][help] */
187 {
188 const unsignedIChunk* old = ch;
189 const unsignedIChunk* t = ch;
190 while (!t->actual_pointer(p))
191 {
192 t = (t->next());
193 if (t == old) index_error();
194 }
195 set_cache(t);
196 }
197
198 int unsignedXPlex::owns(Pix px) const
/* [<][>][^][v][top][bottom][index][help] */
199 {
200 unsigned* p = (unsigned*)px;
201 const unsignedIChunk* old = ch;
202 const unsignedIChunk* t = ch;
203 while (!t->actual_pointer(p))
204 {
205 t = (t->next());
206 if (t == old) { set_cache(t); return 0; }
207 }
208 set_cache(t);
209 return 1;
210 }
211
212
213 unsigned* unsignedXPlex::dosucc(const unsigned* p) const
/* [<][>][^][v][top][bottom][index][help] */
214 {
215 if (p == 0) return 0;
216 const unsignedIChunk* old = ch;
217 const unsignedIChunk* t = ch;
218
219 while (!t->actual_pointer(p))
220 {
221 t = (t->next());
222 if (t == old) return 0;
223 }
224 int i = t->index_of(p) + 1;
225 if (i >= fnc) return 0;
226 if (i >= t->fence_index()) t = (t->next());
227 set_cache(t);
228 return (t->pointer_to(i));
229 }
230
231 unsigned* unsignedXPlex::dopred(const unsigned* p) const
/* [<][>][^][v][top][bottom][index][help] */
232 {
233 if (p == 0) return 0;
234 const unsignedIChunk* old = ch;
235 const unsignedIChunk* t = ch;
236 while (!t->actual_pointer(p))
237 {
238 t = (t->prev());
239 if (t == old) return 0;
240 }
241 int i = t->index_of(p) - 1;
242 if (i < lo) return 0;
243 if (i < t->low_index()) t = (t->prev());
244 set_cache(t);
245 return (t->pointer_to(i));
246 }
247
248
249 int unsignedXPlex::add_high(const unsigned elem)
/* [<][>][^][v][top][bottom][index][help] */
250 {
251 unsignedIChunk* t = tl();
252 if (!t->can_grow_high())
253 {
254 if (t->unsignedIChunk::empty() && one_chunk())
255 t->clear(fnc);
256 else
257 {
258 unsigned* data = new unsigned [csize];
259 t = (new unsignedIChunk(data, fnc, fnc, fnc,fnc+csize));
260 t->link_to_prev(tl());
261 }
262 }
263 *((t->unsignedIChunk::grow_high())) = elem;
264 set_cache(t);
265 return fnc++;
266 }
267
268 int unsignedXPlex::del_high ()
/* [<][>][^][v][top][bottom][index][help] */
269 {
270 if (empty()) empty_error();
271 unsignedIChunk* t = tl();
272 t->unsignedIChunk::shrink_high();
273 if (t->unsignedIChunk::empty() && !one_chunk())
274 {
275 unsignedIChunk* pred = t->prev();
276 del_chunk(t);
277 t = pred;
278 }
279 set_cache(t);
280 return --fnc - 1;
281 }
282
283 int unsignedXPlex::add_low (const unsigned elem)
/* [<][>][^][v][top][bottom][index][help] */
284 {
285 unsignedIChunk* t = hd;
286 if (!t->can_grow_low())
287 {
288 if (t->unsignedIChunk::empty() && one_chunk())
289 t->cleardown(lo);
290 else
291 {
292 unsigned* data = new unsigned [csize];
293 hd = new unsignedIChunk(data, lo-csize, lo, lo, lo);
294 hd->link_to_next(t);
295 t = hd;
296 }
297 }
298 *((t->unsignedIChunk::grow_low())) = elem;
299 set_cache(t);
300 return --lo;
301 }
302
303
304 int unsignedXPlex::del_low ()
/* [<][>][^][v][top][bottom][index][help] */
305 {
306 if (empty()) empty_error();
307 unsignedIChunk* t = hd;
308 t->unsignedIChunk::shrink_low();
309 if (t->unsignedIChunk::empty() && !one_chunk())
310 {
311 hd = t->next();
312 del_chunk(t);
313 t = hd;
314 }
315 set_cache(t);
316 return ++lo;
317 }
318
319 void unsignedXPlex::reverse()
/* [<][>][^][v][top][bottom][index][help] */
320 {
321 unsigned tmp;
322 int l = lo;
323 int h = fnc - 1;
324 unsignedIChunk* loch = hd;
325 unsignedIChunk* hich = tl();
326 while (l < h)
327 {
328 unsigned* lptr = loch->pointer_to(l);
329 unsigned* hptr = hich->pointer_to(h);
330 tmp = *lptr;
331 *lptr = *hptr;
332 *hptr = tmp;
333 if (++l >= loch->fence_index()) loch = loch->next();
334 if (--h < hich->low_index()) hich = hich->prev();
335 }
336 }
337
338 void unsignedXPlex::fill(const unsigned x)
/* [<][>][^][v][top][bottom][index][help] */
339 {
340 for (int i = lo; i < fnc; ++i) (*this)[i] = x;
341 }
342
343 void unsignedXPlex::fill(const unsigned x, int l, int hi)
/* [<][>][^][v][top][bottom][index][help] */
344 {
345 for (int i = l; i <= hi; ++i) (*this)[i] = x;
346 }
347
348
349 void unsignedXPlex::clear()
/* [<][>][^][v][top][bottom][index][help] */
350 {
351 if (fnc != lo)
352 {
353 unsignedIChunk* t = tl();
354 while (t != hd)
355 {
356 unsignedIChunk* prv = t->prev();
357 del_chunk(t);
358 t = prv;
359 }
360 t->unsignedIChunk::clear(lo);
361 set_cache(t);
362 fnc = lo;
363 }
364 }
365
366
367 int unsignedXPlex::OK () const
/* [<][>][^][v][top][bottom][index][help] */
368 {
369 int v = hd != 0 && ch != 0; // at least one chunk
370
371 v &= fnc == tl()->fence_index();// last chunk fence == plex fence
372 v &= lo == ((hd))->unsignedIChunk::low_index(); // first lo == plex lo
373
374 // loop for others:
375 int found_ch = 0; // to make sure ch is in list;
376 const unsignedIChunk* t = (hd);
377 for (;;)
378 {
379 if (t == ch) ++found_ch;
380 v &= t->unsignedIChunk::OK(); // each chunk is OK
381 if (t == tl())
382 break;
383 else // and has indices contiguous to succ
384 {
385 v &= t->top_index() == t->next()->base_index();
386 if (t != hd) // internal chunks full
387 {
388 v &= !t->empty();
389 v &= !t->can_grow_low();
390 v &= !t->can_grow_high();
391 }
392 t = t->next();
393 }
394 }
395 v &= found_ch == 1;
396 if (!v) error("invariant failure");
397 return v;
398 }