1*4bdff4beSrobert //===----------------------------------------------------------------------===//
246035553Spatrick //
346035553Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
446035553Spatrick // See https://llvm.org/LICENSE.txt for license information.
546035553Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
646035553Spatrick //
746035553Spatrick //===----------------------------------------------------------------------===//
846035553Spatrick
9*4bdff4beSrobert #include <__assert>
10*4bdff4beSrobert #include <__config>
11*4bdff4beSrobert #include <__debug>
12*4bdff4beSrobert #include <__hash_table>
13*4bdff4beSrobert #include <algorithm>
14*4bdff4beSrobert #include <cstdio>
15*4bdff4beSrobert #include <functional>
16*4bdff4beSrobert #include <string>
17*4bdff4beSrobert
1846035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
19*4bdff4beSrobert # include <mutex>
2046035553Spatrick # if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
2146035553Spatrick # pragma comment(lib, "pthread")
2246035553Spatrick # endif
2346035553Spatrick #endif
2446035553Spatrick
2546035553Spatrick _LIBCPP_BEGIN_NAMESPACE_STD
2646035553Spatrick
2746035553Spatrick _LIBCPP_FUNC_VIS
2846035553Spatrick __libcpp_db*
__get_db()2946035553Spatrick __get_db()
3046035553Spatrick {
3146035553Spatrick static _LIBCPP_NO_DESTROY __libcpp_db db;
3246035553Spatrick return &db;
3346035553Spatrick }
3446035553Spatrick
3546035553Spatrick _LIBCPP_FUNC_VIS
3646035553Spatrick const __libcpp_db*
__get_const_db()3746035553Spatrick __get_const_db()
3846035553Spatrick {
3946035553Spatrick return __get_db();
4046035553Spatrick }
4146035553Spatrick
4246035553Spatrick namespace
4346035553Spatrick {
4446035553Spatrick
4546035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
4646035553Spatrick typedef mutex mutex_type;
4746035553Spatrick typedef lock_guard<mutex_type> WLock;
4846035553Spatrick typedef lock_guard<mutex_type> RLock;
4946035553Spatrick
5046035553Spatrick mutex_type&
mut()5146035553Spatrick mut()
5246035553Spatrick {
5346035553Spatrick static _LIBCPP_NO_DESTROY mutex_type m;
5446035553Spatrick return m;
5546035553Spatrick }
5646035553Spatrick #endif // !_LIBCPP_HAS_NO_THREADS
5746035553Spatrick
5846035553Spatrick } // unnamed namespace
5946035553Spatrick
~__i_node()6046035553Spatrick __i_node::~__i_node()
6146035553Spatrick {
6246035553Spatrick if (__next_)
6346035553Spatrick {
6446035553Spatrick __next_->~__i_node();
6546035553Spatrick free(__next_);
6646035553Spatrick }
6746035553Spatrick }
6846035553Spatrick
~__c_node()6946035553Spatrick __c_node::~__c_node()
7046035553Spatrick {
7146035553Spatrick free(beg_);
7246035553Spatrick if (__next_)
7346035553Spatrick {
7446035553Spatrick __next_->~__c_node();
7546035553Spatrick free(__next_);
7646035553Spatrick }
7746035553Spatrick }
7846035553Spatrick
__libcpp_db()7946035553Spatrick __libcpp_db::__libcpp_db()
8046035553Spatrick : __cbeg_(nullptr),
8146035553Spatrick __cend_(nullptr),
8246035553Spatrick __csz_(0),
8346035553Spatrick __ibeg_(nullptr),
8446035553Spatrick __iend_(nullptr),
8546035553Spatrick __isz_(0)
8646035553Spatrick {
8746035553Spatrick }
8846035553Spatrick
~__libcpp_db()8946035553Spatrick __libcpp_db::~__libcpp_db()
9046035553Spatrick {
9146035553Spatrick if (__cbeg_)
9246035553Spatrick {
9346035553Spatrick for (__c_node** p = __cbeg_; p != __cend_; ++p)
9446035553Spatrick {
9546035553Spatrick if (*p != nullptr)
9646035553Spatrick {
9746035553Spatrick (*p)->~__c_node();
9846035553Spatrick free(*p);
9946035553Spatrick }
10046035553Spatrick }
10146035553Spatrick free(__cbeg_);
10246035553Spatrick }
10346035553Spatrick if (__ibeg_)
10446035553Spatrick {
10546035553Spatrick for (__i_node** p = __ibeg_; p != __iend_; ++p)
10646035553Spatrick {
10746035553Spatrick if (*p != nullptr)
10846035553Spatrick {
10946035553Spatrick (*p)->~__i_node();
11046035553Spatrick free(*p);
11146035553Spatrick }
11246035553Spatrick }
11346035553Spatrick free(__ibeg_);
11446035553Spatrick }
11546035553Spatrick }
11646035553Spatrick
11746035553Spatrick void*
__find_c_from_i(void * __i) const11846035553Spatrick __libcpp_db::__find_c_from_i(void* __i) const
11946035553Spatrick {
12046035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
12146035553Spatrick RLock _(mut());
12246035553Spatrick #endif
12346035553Spatrick __i_node* i = __find_iterator(__i);
12446035553Spatrick _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
12546035553Spatrick return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
12646035553Spatrick }
12746035553Spatrick
12846035553Spatrick void
__insert_ic(void * __i,const void * __c)12946035553Spatrick __libcpp_db::__insert_ic(void* __i, const void* __c)
13046035553Spatrick {
13146035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
13246035553Spatrick WLock _(mut());
13346035553Spatrick #endif
13446035553Spatrick if (__cbeg_ == __cend_)
13546035553Spatrick return;
13646035553Spatrick size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
13746035553Spatrick __c_node* c = __cbeg_[hc];
13846035553Spatrick if (c == nullptr)
13946035553Spatrick return;
14046035553Spatrick while (c->__c_ != __c)
14146035553Spatrick {
14246035553Spatrick c = c->__next_;
14346035553Spatrick if (c == nullptr)
14446035553Spatrick return;
14546035553Spatrick }
14646035553Spatrick __i_node* i = __insert_iterator(__i);
14746035553Spatrick c->__add(i);
14846035553Spatrick i->__c_ = c;
14946035553Spatrick }
15046035553Spatrick
15146035553Spatrick void
__insert_c(void * __c,__libcpp_db::_InsertConstruct * __fn)15246035553Spatrick __libcpp_db::__insert_c(void* __c, __libcpp_db::_InsertConstruct *__fn)
15346035553Spatrick {
15446035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
15546035553Spatrick WLock _(mut());
15646035553Spatrick #endif
15746035553Spatrick if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
15846035553Spatrick {
15946035553Spatrick size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
16046035553Spatrick __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(__c_node*)));
16146035553Spatrick if (cbeg == nullptr)
16246035553Spatrick __throw_bad_alloc();
16346035553Spatrick
16446035553Spatrick for (__c_node** p = __cbeg_; p != __cend_; ++p)
16546035553Spatrick {
16646035553Spatrick __c_node* q = *p;
16746035553Spatrick while (q != nullptr)
16846035553Spatrick {
16946035553Spatrick size_t h = hash<void*>()(q->__c_) % nc;
17046035553Spatrick __c_node* r = q->__next_;
17146035553Spatrick q->__next_ = cbeg[h];
17246035553Spatrick cbeg[h] = q;
17346035553Spatrick q = r;
17446035553Spatrick }
17546035553Spatrick }
17646035553Spatrick free(__cbeg_);
17746035553Spatrick __cbeg_ = cbeg;
17846035553Spatrick __cend_ = __cbeg_ + nc;
17946035553Spatrick }
18046035553Spatrick size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
18146035553Spatrick __c_node* p = __cbeg_[hc];
18246035553Spatrick void *buf = malloc(sizeof(__c_node));
18346035553Spatrick if (buf == nullptr)
18446035553Spatrick __throw_bad_alloc();
18546035553Spatrick __cbeg_[hc] = __fn(buf, __c, p);
18646035553Spatrick
18746035553Spatrick ++__csz_;
18846035553Spatrick }
18946035553Spatrick
19046035553Spatrick void
__erase_i(void * __i)19146035553Spatrick __libcpp_db::__erase_i(void* __i)
19246035553Spatrick {
19346035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
19446035553Spatrick WLock _(mut());
19546035553Spatrick #endif
19646035553Spatrick if (__ibeg_ != __iend_)
19746035553Spatrick {
19846035553Spatrick size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
19946035553Spatrick __i_node* p = __ibeg_[hi];
20046035553Spatrick if (p != nullptr)
20146035553Spatrick {
20246035553Spatrick __i_node* q = nullptr;
20346035553Spatrick while (p->__i_ != __i)
20446035553Spatrick {
20546035553Spatrick q = p;
20646035553Spatrick p = p->__next_;
20746035553Spatrick if (p == nullptr)
20846035553Spatrick return;
20946035553Spatrick }
21046035553Spatrick if (q == nullptr)
21146035553Spatrick __ibeg_[hi] = p->__next_;
21246035553Spatrick else
21346035553Spatrick q->__next_ = p->__next_;
21446035553Spatrick __c_node* c = p->__c_;
21546035553Spatrick --__isz_;
21646035553Spatrick if (c != nullptr)
21746035553Spatrick c->__remove(p);
21846035553Spatrick free(p);
21946035553Spatrick }
22046035553Spatrick }
22146035553Spatrick }
22246035553Spatrick
22346035553Spatrick void
__invalidate_all(void * __c)22446035553Spatrick __libcpp_db::__invalidate_all(void* __c)
22546035553Spatrick {
22646035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
22746035553Spatrick WLock _(mut());
22846035553Spatrick #endif
22946035553Spatrick if (__cend_ != __cbeg_)
23046035553Spatrick {
23146035553Spatrick size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
23246035553Spatrick __c_node* p = __cbeg_[hc];
23346035553Spatrick if (p == nullptr)
23446035553Spatrick return;
23546035553Spatrick while (p->__c_ != __c)
23646035553Spatrick {
23746035553Spatrick p = p->__next_;
23846035553Spatrick if (p == nullptr)
23946035553Spatrick return;
24046035553Spatrick }
24146035553Spatrick while (p->end_ != p->beg_)
24246035553Spatrick {
24346035553Spatrick --p->end_;
24446035553Spatrick (*p->end_)->__c_ = nullptr;
24546035553Spatrick }
24646035553Spatrick }
24746035553Spatrick }
24846035553Spatrick
24946035553Spatrick __c_node*
__find_c_and_lock(void * __c) const25046035553Spatrick __libcpp_db::__find_c_and_lock(void* __c) const
25146035553Spatrick {
25246035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
25346035553Spatrick mut().lock();
25446035553Spatrick #endif
25546035553Spatrick if (__cend_ == __cbeg_)
25646035553Spatrick {
25746035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
25846035553Spatrick mut().unlock();
25946035553Spatrick #endif
26046035553Spatrick return nullptr;
26146035553Spatrick }
26246035553Spatrick size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
26346035553Spatrick __c_node* p = __cbeg_[hc];
26446035553Spatrick if (p == nullptr)
26546035553Spatrick {
26646035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
26746035553Spatrick mut().unlock();
26846035553Spatrick #endif
26946035553Spatrick return nullptr;
27046035553Spatrick }
27146035553Spatrick while (p->__c_ != __c)
27246035553Spatrick {
27346035553Spatrick p = p->__next_;
27446035553Spatrick if (p == nullptr)
27546035553Spatrick {
27646035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
27746035553Spatrick mut().unlock();
27846035553Spatrick #endif
27946035553Spatrick return nullptr;
28046035553Spatrick }
28146035553Spatrick }
28246035553Spatrick return p;
28346035553Spatrick }
28446035553Spatrick
28546035553Spatrick __c_node*
__find_c(void * __c) const28646035553Spatrick __libcpp_db::__find_c(void* __c) const
28746035553Spatrick {
28846035553Spatrick size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
28946035553Spatrick __c_node* p = __cbeg_[hc];
29046035553Spatrick _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
29146035553Spatrick while (p->__c_ != __c)
29246035553Spatrick {
29346035553Spatrick p = p->__next_;
29446035553Spatrick _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
29546035553Spatrick }
29646035553Spatrick return p;
29746035553Spatrick }
29846035553Spatrick
29946035553Spatrick void
unlock() const30046035553Spatrick __libcpp_db::unlock() const
30146035553Spatrick {
30246035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
30346035553Spatrick mut().unlock();
30446035553Spatrick #endif
30546035553Spatrick }
30646035553Spatrick
30746035553Spatrick void
__erase_c(void * __c)30846035553Spatrick __libcpp_db::__erase_c(void* __c)
30946035553Spatrick {
31046035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
31146035553Spatrick WLock _(mut());
31246035553Spatrick #endif
31346035553Spatrick if (__cend_ != __cbeg_)
31446035553Spatrick {
31546035553Spatrick size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
31646035553Spatrick __c_node* p = __cbeg_[hc];
31746035553Spatrick if (p == nullptr)
31846035553Spatrick return;
31946035553Spatrick __c_node* q = nullptr;
32046035553Spatrick _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
32146035553Spatrick while (p->__c_ != __c)
32246035553Spatrick {
32346035553Spatrick q = p;
32446035553Spatrick p = p->__next_;
32546035553Spatrick if (p == nullptr)
32646035553Spatrick return;
32746035553Spatrick _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
32846035553Spatrick }
32946035553Spatrick if (q == nullptr)
33046035553Spatrick __cbeg_[hc] = p->__next_;
33146035553Spatrick else
33246035553Spatrick q->__next_ = p->__next_;
33346035553Spatrick while (p->end_ != p->beg_)
33446035553Spatrick {
33546035553Spatrick --p->end_;
33646035553Spatrick (*p->end_)->__c_ = nullptr;
33746035553Spatrick }
33846035553Spatrick free(p->beg_);
33946035553Spatrick free(p);
34046035553Spatrick --__csz_;
34146035553Spatrick }
34246035553Spatrick }
34346035553Spatrick
34446035553Spatrick void
__iterator_copy(void * __i,const void * __i0)34546035553Spatrick __libcpp_db::__iterator_copy(void* __i, const void* __i0)
34646035553Spatrick {
34746035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
34846035553Spatrick WLock _(mut());
34946035553Spatrick #endif
35046035553Spatrick __i_node* i = __find_iterator(__i);
35146035553Spatrick __i_node* i0 = __find_iterator(__i0);
35246035553Spatrick __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
35346035553Spatrick if (i == nullptr && i0 != nullptr)
35446035553Spatrick i = __insert_iterator(__i);
35546035553Spatrick __c_node* c = i != nullptr ? i->__c_ : nullptr;
35646035553Spatrick if (c != c0)
35746035553Spatrick {
35846035553Spatrick if (c != nullptr)
35946035553Spatrick c->__remove(i);
36046035553Spatrick if (i != nullptr)
36146035553Spatrick {
36246035553Spatrick i->__c_ = nullptr;
36346035553Spatrick if (c0 != nullptr)
36446035553Spatrick {
36546035553Spatrick i->__c_ = c0;
36646035553Spatrick i->__c_->__add(i);
36746035553Spatrick }
36846035553Spatrick }
36946035553Spatrick }
37046035553Spatrick }
37146035553Spatrick
37246035553Spatrick bool
__dereferenceable(const void * __i) const37346035553Spatrick __libcpp_db::__dereferenceable(const void* __i) const
37446035553Spatrick {
37546035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
37646035553Spatrick RLock _(mut());
37746035553Spatrick #endif
37846035553Spatrick __i_node* i = __find_iterator(__i);
37946035553Spatrick return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
38046035553Spatrick }
38146035553Spatrick
38246035553Spatrick bool
__decrementable(const void * __i) const38346035553Spatrick __libcpp_db::__decrementable(const void* __i) const
38446035553Spatrick {
38546035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
38646035553Spatrick RLock _(mut());
38746035553Spatrick #endif
38846035553Spatrick __i_node* i = __find_iterator(__i);
38946035553Spatrick return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
39046035553Spatrick }
39146035553Spatrick
39246035553Spatrick bool
__addable(const void * __i,ptrdiff_t __n) const39346035553Spatrick __libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
39446035553Spatrick {
39546035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
39646035553Spatrick RLock _(mut());
39746035553Spatrick #endif
39846035553Spatrick __i_node* i = __find_iterator(__i);
39946035553Spatrick return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
40046035553Spatrick }
40146035553Spatrick
40246035553Spatrick bool
__subscriptable(const void * __i,ptrdiff_t __n) const40346035553Spatrick __libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
40446035553Spatrick {
40546035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
40646035553Spatrick RLock _(mut());
40746035553Spatrick #endif
40846035553Spatrick __i_node* i = __find_iterator(__i);
40946035553Spatrick return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
41046035553Spatrick }
41146035553Spatrick
41246035553Spatrick bool
__less_than_comparable(const void * __i,const void * __j) const41346035553Spatrick __libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
41446035553Spatrick {
41546035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
41646035553Spatrick RLock _(mut());
41746035553Spatrick #endif
41846035553Spatrick __i_node* i = __find_iterator(__i);
41946035553Spatrick __i_node* j = __find_iterator(__j);
42046035553Spatrick __c_node* ci = i != nullptr ? i->__c_ : nullptr;
42146035553Spatrick __c_node* cj = j != nullptr ? j->__c_ : nullptr;
42276d0caaeSpatrick return ci == cj;
42346035553Spatrick }
42446035553Spatrick
42546035553Spatrick void
swap(void * c1,void * c2)42646035553Spatrick __libcpp_db::swap(void* c1, void* c2)
42746035553Spatrick {
42846035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
42946035553Spatrick WLock _(mut());
43046035553Spatrick #endif
43146035553Spatrick size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
43246035553Spatrick __c_node* p1 = __cbeg_[hc];
43346035553Spatrick _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
43446035553Spatrick while (p1->__c_ != c1)
43546035553Spatrick {
43646035553Spatrick p1 = p1->__next_;
43746035553Spatrick _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
43846035553Spatrick }
43946035553Spatrick hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
44046035553Spatrick __c_node* p2 = __cbeg_[hc];
44146035553Spatrick _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
44246035553Spatrick while (p2->__c_ != c2)
44346035553Spatrick {
44446035553Spatrick p2 = p2->__next_;
44546035553Spatrick _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
44646035553Spatrick }
44746035553Spatrick std::swap(p1->beg_, p2->beg_);
44846035553Spatrick std::swap(p1->end_, p2->end_);
44946035553Spatrick std::swap(p1->cap_, p2->cap_);
45046035553Spatrick for (__i_node** p = p1->beg_; p != p1->end_; ++p)
45146035553Spatrick (*p)->__c_ = p1;
45246035553Spatrick for (__i_node** p = p2->beg_; p != p2->end_; ++p)
45346035553Spatrick (*p)->__c_ = p2;
45446035553Spatrick }
45546035553Spatrick
45646035553Spatrick void
__insert_i(void * __i)45746035553Spatrick __libcpp_db::__insert_i(void* __i)
45846035553Spatrick {
45946035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
46046035553Spatrick WLock _(mut());
46146035553Spatrick #endif
46246035553Spatrick __insert_iterator(__i);
46346035553Spatrick }
46446035553Spatrick
46546035553Spatrick void
__add(__i_node * i)46646035553Spatrick __c_node::__add(__i_node* i)
46746035553Spatrick {
46846035553Spatrick if (end_ == cap_)
46946035553Spatrick {
47046035553Spatrick size_t nc = 2*static_cast<size_t>(cap_ - beg_);
47146035553Spatrick if (nc == 0)
47246035553Spatrick nc = 1;
47346035553Spatrick __i_node** beg =
47446035553Spatrick static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
47546035553Spatrick if (beg == nullptr)
47646035553Spatrick __throw_bad_alloc();
47746035553Spatrick
47846035553Spatrick if (nc > 1)
47946035553Spatrick memcpy(beg, beg_, nc/2*sizeof(__i_node*));
48046035553Spatrick free(beg_);
48146035553Spatrick beg_ = beg;
48246035553Spatrick end_ = beg_ + nc/2;
48346035553Spatrick cap_ = beg_ + nc;
48446035553Spatrick }
48546035553Spatrick *end_++ = i;
48646035553Spatrick }
48746035553Spatrick
48846035553Spatrick // private api
48946035553Spatrick
49046035553Spatrick _LIBCPP_HIDDEN
49146035553Spatrick __i_node*
__insert_iterator(void * __i)49246035553Spatrick __libcpp_db::__insert_iterator(void* __i)
49346035553Spatrick {
49446035553Spatrick if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
49546035553Spatrick {
49646035553Spatrick size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
49746035553Spatrick __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(__i_node*)));
49846035553Spatrick if (ibeg == nullptr)
49946035553Spatrick __throw_bad_alloc();
50046035553Spatrick
50146035553Spatrick for (__i_node** p = __ibeg_; p != __iend_; ++p)
50246035553Spatrick {
50346035553Spatrick __i_node* q = *p;
50446035553Spatrick while (q != nullptr)
50546035553Spatrick {
50646035553Spatrick size_t h = hash<void*>()(q->__i_) % nc;
50746035553Spatrick __i_node* r = q->__next_;
50846035553Spatrick q->__next_ = ibeg[h];
50946035553Spatrick ibeg[h] = q;
51046035553Spatrick q = r;
51146035553Spatrick }
51246035553Spatrick }
51346035553Spatrick free(__ibeg_);
51446035553Spatrick __ibeg_ = ibeg;
51546035553Spatrick __iend_ = __ibeg_ + nc;
51646035553Spatrick }
51746035553Spatrick size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
51846035553Spatrick __i_node* p = __ibeg_[hi];
51946035553Spatrick __i_node* r = __ibeg_[hi] =
52046035553Spatrick static_cast<__i_node*>(malloc(sizeof(__i_node)));
52146035553Spatrick if (r == nullptr)
52246035553Spatrick __throw_bad_alloc();
52346035553Spatrick
52446035553Spatrick ::new(r) __i_node(__i, p, nullptr);
52546035553Spatrick ++__isz_;
52646035553Spatrick return r;
52746035553Spatrick }
52846035553Spatrick
52946035553Spatrick _LIBCPP_HIDDEN
53046035553Spatrick __i_node*
__find_iterator(const void * __i) const53146035553Spatrick __libcpp_db::__find_iterator(const void* __i) const
53246035553Spatrick {
53346035553Spatrick __i_node* r = nullptr;
53446035553Spatrick if (__ibeg_ != __iend_)
53546035553Spatrick {
53646035553Spatrick size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
53746035553Spatrick for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
53846035553Spatrick {
53946035553Spatrick if (nd->__i_ == __i)
54046035553Spatrick {
54146035553Spatrick r = nd;
54246035553Spatrick break;
54346035553Spatrick }
54446035553Spatrick }
54546035553Spatrick }
54646035553Spatrick return r;
54746035553Spatrick }
54846035553Spatrick
54946035553Spatrick _LIBCPP_HIDDEN
55046035553Spatrick void
__remove(__i_node * p)55146035553Spatrick __c_node::__remove(__i_node* p)
55246035553Spatrick {
55346035553Spatrick __i_node** r = find(beg_, end_, p);
55446035553Spatrick _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
55546035553Spatrick if (--end_ != r)
55646035553Spatrick memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
55746035553Spatrick }
55846035553Spatrick
55946035553Spatrick _LIBCPP_END_NAMESPACE_STD
560