00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #ifdef HAVE_CONFIG_H
00058 # include "config.h"
00059 #endif
00060 #if NEED_GNUG_PRAGMAS
00061 # pragma implementation
00062 #endif
00063
00064 #include "GContainer.h"
00065
00066
00067 #ifdef HAVE_NAMESPACES
00068 namespace DJVU {
00069 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00070 }
00071 #endif
00072 #endif
00073
00074
00075
00076
00077
00078
00079
00080 GArrayBase::GArrayBase(const GArrayBase &ref)
00081 : traits(ref.traits),
00082 gdata(data,0,1),
00083 minlo(ref.minlo), maxhi(ref.maxhi),
00084 lobound(ref.lobound), hibound(ref.hibound)
00085 {
00086 if (maxhi >= minlo)
00087 gdata.resize(traits.size * (maxhi - minlo + 1),1);
00088 if (hibound >= lobound)
00089 traits.copy(traits.lea(data, lobound-minlo),
00090 traits.lea(ref.data, lobound-minlo),
00091 hibound - lobound + 1, 0);
00092 }
00093
00094
00095 GArrayBase::GArrayBase(const GCONT Traits &traits)
00096 : traits(traits),
00097 gdata(data,0,1),
00098 minlo(0), maxhi(-1),
00099 lobound(0), hibound(-1)
00100 {
00101 }
00102
00103
00104 GArrayBase::GArrayBase(const GCONT Traits &traits, int lobound, int hibound)
00105 : traits(traits),
00106 gdata(data,0,1),
00107 minlo(0), maxhi(-1),
00108 lobound(0), hibound(-1)
00109 {
00110 resize(lobound, hibound);
00111 }
00112
00113
00114 GArrayBase::~GArrayBase()
00115 {
00116 G_TRY { empty(); } G_CATCH_ALL { } G_ENDCATCH;
00117 }
00118
00119
00120 GArrayBase &
00121 GArrayBase::operator= (const GArrayBase &ga)
00122 {
00123 if (this == &ga)
00124 return *this;
00125 empty();
00126 if (ga.hibound >= ga.lobound)
00127 {
00128 resize(ga.lobound, ga.hibound);
00129 traits.copy( traits.lea(data, lobound-minlo),
00130 traits.lea(ga.data, ga.lobound-ga.minlo),
00131 hibound - lobound + 1, 0 );
00132 }
00133 return *this;
00134 }
00135
00136
00137 void
00138 GArrayBase::steal(GArrayBase &ga)
00139 {
00140 if (this != &ga)
00141 {
00142 empty();
00143 lobound = ga.lobound;
00144 hibound = ga.hibound;
00145 minlo = ga.minlo;
00146 maxhi = ga.maxhi;
00147 data = ga.data;
00148 ga.data = 0;
00149 ga.lobound = ga.minlo = 0;
00150 ga.hibound = ga.maxhi = -1;
00151 }
00152 }
00153
00154
00155 void
00156 GArrayBase::empty()
00157 {
00158 resize(0, -1);
00159 }
00160
00161
00162 void
00163 GArrayBase::touch(int n)
00164 {
00165 int nlo = (n<lobound ? n : lobound);
00166 int nhi = (n>hibound ? n : hibound);
00167 if (hibound < lobound)
00168 nlo = nhi = n;
00169 resize(nlo, nhi);
00170 }
00171
00172
00173 void
00174 GArrayBase::resize(int lo, int hi)
00175 {
00176
00177 int nsize = hi - lo + 1;
00178 if (nsize < 0)
00179 G_THROW( ERR_MSG("GContainer.bad_args") );
00180
00181 if (nsize == 0)
00182 {
00183 if (hibound >= lobound)
00184 traits.fini( traits.lea(data, lobound-minlo), hibound-lobound+1 );
00185 if (data)
00186 gdata.resize(0,1);
00187 lobound = minlo = 0;
00188 hibound = maxhi = -1;
00189 return;
00190 }
00191
00192 if (lo >= minlo && hi <= maxhi)
00193 {
00194 if (lobound > lo)
00195 traits.init( traits.lea(data,lo-minlo), lobound-lo );
00196 else if (lo > lobound)
00197 traits.fini( traits.lea(data,lobound-minlo), lo-lobound );
00198 if (hi > hibound)
00199 traits.init( traits.lea(data,hibound-minlo+1), hi-hibound );
00200 else if (hibound > hi)
00201 traits.fini( traits.lea(data,hi-minlo+1), hibound-hi );
00202 lobound = lo;
00203 hibound = hi;
00204 return;
00205 }
00206
00207 int nminlo = minlo;
00208 int nmaxhi = maxhi;
00209 if (nminlo > nmaxhi)
00210 nminlo = nmaxhi = lo;
00211 while (nminlo > lo) {
00212 int incr = nmaxhi - nminlo;
00213 nminlo -= (incr < 8 ? 8 : (incr > 32768 ? 32768 : incr));
00214 }
00215 while (nmaxhi < hi) {
00216 int incr = nmaxhi - nminlo;
00217 nmaxhi += (incr < 8 ? 8 : (incr > 32768 ? 32768 : incr));
00218 }
00219
00220 int beg = lo;
00221 int end = hi;
00222 int bytesize = traits.size * (nmaxhi-nminlo+1);
00223 void *ndata;
00224 GPBufferBase gndata(ndata,bytesize,1);
00225 #if GCONTAINER_ZERO_FILL
00226 memset(ndata, 0, bytesize);
00227 #endif
00228 if (lo < lobound)
00229 { traits.init( traits.lea(ndata,lo-nminlo), lobound-lo ); beg=lobound; }
00230 else if (lobound < lo)
00231 { traits.fini( traits.lea(data,lobound-minlo), lo-lobound); }
00232 if (hibound < hi)
00233 { traits.init( traits.lea(ndata,hibound-nminlo+1), hi-hibound ); end=hibound; }
00234 else if (hi < hibound)
00235 { traits.fini( traits.lea(data, hi-minlo+1), hibound-hi ); }
00236 if (end >= beg)
00237 { traits.copy( traits.lea(ndata, beg-nminlo),
00238 traits.lea(data, beg-minlo),
00239 end-beg+1, 1 ); }
00240
00241 void *tmp=data;
00242 data=ndata;
00243 ndata=tmp;
00244 minlo = nminlo;
00245 maxhi = nmaxhi;
00246 lobound = lo;
00247 hibound = hi;
00248 }
00249
00250
00251 void
00252 GArrayBase::shift(int disp)
00253 {
00254 lobound += disp;
00255 hibound += disp;
00256 minlo += disp;
00257 maxhi += disp;
00258 }
00259
00260
00261 void
00262 GArrayBase::del(int n, int howmany)
00263 {
00264 if (howmany < 0)
00265 G_THROW( ERR_MSG("GContainer.bad_howmany") );
00266 if (howmany == 0)
00267 return;
00268 if ( n < lobound || n+(int)howmany-1 > hibound)
00269 G_THROW( ERR_MSG("GContainer.bad_sub2") );
00270 traits.fini( traits.lea(data, n-minlo), howmany );
00271 if ( n+howmany-1 < hibound)
00272 traits.copy( traits.lea(data, n-minlo),
00273 traits.lea(data, n-minlo+howmany),
00274 hibound - (n+howmany-1), 1 );
00275 hibound = hibound - howmany;
00276 }
00277
00278
00279 static inline void *
00280 nextptr(void *p, int elsize)
00281 {
00282 return (void*)(((char*)p) + elsize);
00283 }
00284
00285
00286 static inline void *
00287 prevptr(void *p, int elsize)
00288 {
00289 return (void*)(((char*)p) - elsize);
00290 }
00291
00292
00293 void
00294 GArrayBase::ins(int n, const void *src, int howmany)
00295 {
00296 if (howmany < 0)
00297 G_THROW( ERR_MSG("GContainer.bad_howmany") );
00298 if (howmany == 0)
00299 return;
00300
00301 if (hibound+howmany > maxhi)
00302 {
00303 int nmaxhi = maxhi;
00304 while (nmaxhi < hibound+howmany)
00305 nmaxhi += (nmaxhi < 8 ? 8 : (nmaxhi > 32768 ? 32768 : nmaxhi));
00306 int bytesize = traits.size * (nmaxhi-minlo+1);
00307 void *ndata;
00308 GPBufferBase gndata(ndata,bytesize,1);
00309 memset(ndata, 0, bytesize);
00310 if (hibound >= lobound)
00311 traits.copy( traits.lea(ndata, lobound-minlo),
00312 traits.lea(data, lobound-minlo),
00313 hibound-lobound+1, 1 );
00314 maxhi = nmaxhi;
00315 void *tmp=data;
00316 data = ndata;
00317 ndata=tmp;
00318 }
00319
00320 int elsize = traits.size;
00321 void *pdst = traits.lea(data, hibound+howmany-minlo);
00322 void *psrc = traits.lea(data, hibound-minlo);
00323 void *pend = traits.lea(data, n-minlo);
00324 while ((char*)psrc >= (char*)pend)
00325 {
00326 traits.copy( pdst, psrc, 1, 1 );
00327 pdst = prevptr(pdst, elsize);
00328 psrc = prevptr(psrc, elsize);
00329 }
00330 hibound += howmany;
00331
00332 if (! src)
00333 {
00334 traits.init( traits.lea(data, n-minlo), howmany );
00335 hibound += howmany;
00336 return;
00337 }
00338
00339 pdst = traits.lea(data, n-minlo);
00340 pend = traits.lea(data, n+howmany-minlo);
00341 while ((char*)pdst < (char*)pend)
00342 {
00343 traits.copy( pdst, src, 1, 0);
00344 pdst = nextptr(pdst, elsize);
00345 }
00346 }
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 void
00357 GPosition::throw_invalid(void *c) const
00358 {
00359 if (c != cont)
00360 G_THROW( ERR_MSG("GContainer.bad_pos_cont") );
00361 else if (! ptr)
00362 G_THROW( ERR_MSG("GContainer.bad_pos_null") );
00363 else
00364 G_THROW( ERR_MSG("GContainer.bad_pos") );
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374 GListBase::GListBase(const Traits& traits)
00375 : traits(traits)
00376 {
00377 nelem = 0;
00378 head.next = head.prev = 0;
00379 }
00380
00381
00382 GListBase::GListBase(const GListBase &ref)
00383 : traits(ref.traits)
00384 {
00385 nelem = 0;
00386 head.next = head.prev = 0;
00387 GListBase::operator= (ref);
00388 }
00389
00390 #include <stdio.h>
00391 GListBase::~GListBase()
00392 {
00393 G_TRY
00394 {
00395 empty();
00396 }
00397 G_CATCH_ALL
00398 {
00399 }
00400 G_ENDCATCH;
00401 }
00402
00403
00404 void
00405 GListBase::append(Node *n)
00406 {
00407
00408 n->next = 0;
00409 n->prev = head.prev;
00410 head.prev = n;
00411 if (n->prev)
00412 n->prev->next = n;
00413 else
00414 head.next = n;
00415
00416 nelem += 1;
00417 }
00418
00419
00420 void
00421 GListBase::prepend(Node *n)
00422 {
00423
00424 n->next = head.next;
00425 n->prev = 0;
00426 head.next = n;
00427 if (n->next)
00428 n->next->prev = n;
00429 else
00430 head.prev = n;
00431
00432 nelem += 1;
00433 }
00434
00435
00436 void
00437 GListBase::insert_after(GPosition pos, Node *n)
00438 {
00439
00440 if (pos.ptr)
00441 {
00442 if (pos.cont != (void*)this)
00443 pos.throw_invalid((void*)this);
00444 Node *p = pos.ptr;
00445 n->prev = p;
00446 n->next = p->next;
00447 }
00448 else
00449 {
00450 n->prev = 0;
00451 n->next = head.next;
00452 }
00453
00454 if (n->prev)
00455 n->prev->next = n;
00456 else
00457 head.next = n;
00458 if (n->next)
00459 n->next->prev = n;
00460 else
00461 head.prev = n;
00462
00463 nelem += 1;
00464 }
00465
00466
00467 void
00468 GListBase::insert_before(GPosition pos, Node *n)
00469 {
00470
00471 if (pos.ptr)
00472 {
00473 if (pos.cont != (void*)this)
00474 pos.throw_invalid((void*)this);
00475 Node *p = pos.ptr;
00476 n->prev = p->prev;
00477 n->next = p;
00478 }
00479 else
00480 {
00481 n->prev = head.prev;
00482 n->next = 0;
00483 }
00484
00485 if (n->prev)
00486 n->prev->next = n;
00487 else
00488 head.next = n;
00489 if (n->next)
00490 n->next->prev = n;
00491 else
00492 head.prev = n;
00493
00494 nelem += 1;
00495 }
00496
00497
00498 void
00499 GListBase::insert_before(GPosition pos, GListBase &fromlist, GPosition &frompos)
00500 {
00501
00502 if (!frompos.ptr || frompos.cont != (void*)&fromlist)
00503 frompos.throw_invalid((void*)&fromlist);
00504 if (pos.ptr && pos.cont != (void*)this)
00505 pos.throw_invalid((void*)this);
00506
00507 Node *n = frompos.ptr;
00508 frompos.ptr = n->next;
00509 if (pos.ptr == n) return;
00510
00511 if (n->next)
00512 n->next->prev = n->prev;
00513 else
00514 fromlist.head.prev = n->prev;
00515 if (n->prev)
00516 n->prev->next = n->next;
00517 else
00518 fromlist.head.next = n->next;
00519 fromlist.nelem -= 1;
00520
00521 if (pos.ptr)
00522 {
00523 Node *p = pos.ptr;
00524 n->prev = p->prev;
00525 n->next = p;
00526 }
00527 else
00528 {
00529 n->prev = head.prev;
00530 n->next = 0;
00531 }
00532
00533 if (n->prev)
00534 n->prev->next = n;
00535 else
00536 head.next = n;
00537 if (n->next)
00538 n->next->prev = n;
00539 else
00540 head.prev = n;
00541 nelem += 1;
00542 }
00543
00544
00545 void
00546 GListBase::del(GPosition &pos)
00547 {
00548
00549 if (!pos.ptr || pos.cont != (void*)this) return;
00550
00551 Node *n = pos.ptr;
00552 if (n->next)
00553 n->next->prev = n->prev;
00554 else
00555 head.prev = n->prev;
00556 if (n->prev)
00557 n->prev->next = n->next;
00558 else
00559 head.next = n->next;
00560
00561 nelem -= 1;
00562 traits.fini( (void*)n, 1);
00563 operator delete ( (void*)n );
00564 pos.ptr = 0;
00565 }
00566
00567
00568 GPosition
00569 GListBase::nth(unsigned int n) const
00570 {
00571 Node *p = 0;
00572 if ((int)n < nelem)
00573 for (p=head.next; p; p=p->next)
00574 if ( n-- == 0)
00575 break;
00576 return GPosition(p, (void*)this);
00577 }
00578
00579
00580 void
00581 GListBase::empty()
00582 {
00583 Node *n=head.next;
00584 while (n)
00585 {
00586 Node *p = n->next;
00587 traits.fini( (void*)n, 1 );
00588 operator delete ( (void*)n );
00589 n = p;
00590 }
00591 head.next = head.prev = 0;
00592 nelem = 0;
00593 }
00594
00595
00596 GListBase &
00597 GListBase::operator= (const GListBase & ref)
00598 {
00599 if (this == &ref)
00600 return *this;
00601 empty();
00602 for(Node *n = ref.head.next; n; n=n->next)
00603 {
00604 Node *m = (Node*) operator new (traits.size);
00605 traits.copy( (void*)m, (void*)n, 1, 0);
00606 append(m);
00607 }
00608 return *this;
00609 }
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 GSetBase::GSetBase(const Traits &traits)
00623 : traits(traits), nelems(0), nbuckets(0),
00624 gtable(table), first(0)
00625 {
00626 rehash(17);
00627 }
00628
00629
00630 GSetBase::GSetBase(const GSetBase &ref)
00631 : traits(ref.traits),
00632 nelems(0), nbuckets(0), gtable(table), first(0)
00633 {
00634 GSetBase::operator= (ref);
00635 }
00636
00637
00638 GSetBase::~GSetBase()
00639 {
00640 G_TRY { empty(); } G_CATCH_ALL { } G_ENDCATCH;
00641
00642 }
00643
00644
00645 GCONT HNode *
00646 GSetBase::hashnode(unsigned int hashcode) const
00647 {
00648 int bucket = hashcode % nbuckets;
00649 return table[bucket];
00650 }
00651
00652 GCONT HNode *
00653 GSetBase::installnode(HNode *n)
00654 {
00655
00656 if (nelems*3 > nbuckets*2)
00657 rehash( 2*nbuckets - 1 );
00658
00659 insertnode(n);
00660 return n;
00661 }
00662
00663 void
00664 GSetBase::insertnode(HNode *n)
00665 {
00666 int bucket = n->hashcode % nbuckets;
00667 n->prev = n->hprev = table[bucket];
00668 if (n->prev)
00669 {
00670
00671 n->next = n->prev->next;
00672 n->prev->next = n;
00673 if (n->next)
00674 n->next->prev = n;
00675 }
00676 else
00677 {
00678
00679 n->next = first;
00680 first = n;
00681 if (n->next)
00682 n->next->prev = n;
00683 }
00684
00685 table[bucket] = n;
00686 nelems += 1;
00687 }
00688
00689
00690 void
00691 GSetBase::deletenode(GCONT HNode *n)
00692 {
00693 if (n == 0)
00694 return;
00695 int bucket = n->hashcode % nbuckets;
00696
00697 if (n->next)
00698 n->next->prev = n->prev;
00699 if (n->prev)
00700 n->prev->next = n->next;
00701 else
00702 first = (HNode*)(n->next);
00703
00704 if (table[bucket] == n)
00705 table[bucket] = n->hprev;
00706 else
00707 ((HNode*)(n->next))->hprev = n->hprev;
00708
00709 traits.fini( (void*)n, 1 );
00710 operator delete ( (void*)n );
00711 nelems -= 1;
00712 }
00713
00714
00715 void
00716 GSetBase::rehash(int newbuckets)
00717 {
00718
00719 Node *n = first;
00720
00721 nelems = 0;
00722 first = 0;
00723
00724
00725 gtable.resize(0);
00726 nbuckets = newbuckets;
00727 typedef HNode *HNodePtr;
00728
00729 gtable.resize(nbuckets);
00730 gtable.clear();
00731
00732
00733
00734 while (n)
00735 {
00736 Node *p = n->next;
00737 insertnode((HNode*)n);
00738 n = p;
00739 }
00740 }
00741
00742
00743 GSetBase&
00744 GSetBase::operator=(const GSetBase &ref)
00745 {
00746 if (this == &ref)
00747 return *this;
00748 empty();
00749 rehash(ref.nbuckets);
00750 for (Node *n = ref.first; n; n=n->next)
00751 {
00752 HNode *m = (HNode*) operator new (traits.size);
00753 traits.copy( (void*)m, (void*)n, 1, 0);
00754 insertnode(m);
00755 }
00756 return *this;
00757 }
00758
00759
00760 GPosition
00761 GSetBase::firstpos() const
00762 {
00763 return GPosition(first, (void*)this);
00764 }
00765
00766
00767 void
00768 GSetBase::del(GPosition &pos)
00769 {
00770 if (pos.ptr && pos.cont==(void*)this)
00771 {
00772 deletenode((HNode*)pos.ptr);
00773 pos.ptr = 0;
00774 }
00775 }
00776
00777 void
00778 GSetBase::empty()
00779 {
00780 HNode *n = first;
00781 while (n)
00782 {
00783 HNode *p = (HNode*)(n->next);
00784 traits.fini( (void*)n, 1 );
00785 operator delete ( (void*)n );
00786 n = p;
00787 }
00788 first = 0;
00789 nelems = 0;
00790 gtable.clear();
00791
00792
00793 }
00794
00795
00796 #ifdef HAVE_NAMESPACES
00797 }
00798 # ifndef NOT_USING_DJVU_NAMESPACE
00799 using namespace DJVU;
00800 # endif
00801 #endif
00802