## modules/up/src/gnug++/unsigned.XPlex.cc

/* [<][>][^][v][top][bottom][index][help] */

## FUNCTIONS

This source file includes following functions.

1. unsignedXPlex
2. unsignedXPlex
3. unsignedXPlex
4. make_initial_chunks
5. unsignedXPlex
6. unsignedXPlex
7. cache
8. cache
9. owns
10. dosucc
11. dopred
12. add_high
13. del_high
14. add_low
15. del_low
16. reverse
17. fill
18. fill
19. clear
20. 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 }

/* [<][>][^][v][top][bottom][index][help] */