Alien-libpanda

 view release on metacpan or  search on metacpan

src/panda/basic_string.h  view on Meta::CPAN

        }
    }

    void _reserve_save_internal (size_type capacity) {
        if (_storage.internal->refcnt > 1) _detach_cow(capacity);
        else if (_storage.internal->capacity < capacity) _internal_realloc(capacity); // need to grow storage
        else if (_capacity_internal() < capacity) { // may not to grow storage if str is moved to the beginning
            traits_type::move(_storage.internal->start, _str, _length);
            _str = _storage.internal->start;
        }
    }

    void _internal_realloc (size_type capacity) {
        // see if we can reallocate. if _str != start we should not reallocate because we would need
        // either allocate more space than needed or move everything to the beginning before reallocation
        if (_storage.dtor == &Alloc::deallocate && _str == _storage.internal->start) {
            if (capacity > MAX_SIZE) throw std::length_error("basic_string::_internal_realloc");
            _storage.internal = (Buffer*)Alloc::reallocate((CharT*)_storage.internal, capacity + BUF_CHARS, _storage.internal->capacity + BUF_CHARS);
            _str = _storage.internal->start;
            _storage.internal->capacity = capacity;
        } else { // need to allocate/deallocate
            auto old_buf  = _storage.internal;
            auto old_str  = _str;
            auto old_dtor = _storage.dtor;
            _new_auto(capacity);
            traits_type::copy(_str, old_str, _length);
            _free_internal(old_buf, old_dtor);
        }
    }

    void _reserve_save_external (size_type capacity) {
        if (_storage.external->refcnt > 1) _detach_cow(capacity);
        else if (_storage.external->capacity < capacity) _external_realloc(capacity); // need to grow storage, switch to INTERNAL/SSO
        else if (_capacity_external() < capacity) { // may not to grow storage if str is moved to the beginning
            traits_type::move(_storage.external->ptr, _str, _length);
            _str = _storage.external->ptr;
        }
    }

    void _external_realloc (size_type capacity) {
        auto old_buf  = _storage.external;
        auto old_str  = _str;
        auto old_dtor = _storage.dtor;
        _new_auto(capacity);
        traits_type::copy(_str, old_str, _length);
        _free_external(old_buf, old_dtor);
    }

    void _reserve_save_sso (size_type capacity) {
        if (MAX_SSO_CHARS < capacity) {
            _new_internal_from_sso(capacity);
            return;
        }
        else if (_capacity_sso() < capacity) {
            traits_type::move(_sso, _str, _length);
            _str = _sso;
        }
    }

    // splits string into pwo pieces at position 'pos' with insert_count distance between them replacing remove_count chars after pos.
    // Tries its best not to allocate memory. set the length of string to old length + insert_count - remove_count.
    // The content of part [pos, pos+insert_count) is undefined after operation
    void _reserve_middle (size_type pos, size_type remove_count, size_type insert_count) {
        size_type newlen = _length + insert_count - remove_count;

        switch (_state) {
            case State::INTERNAL:
                if (_storage.internal->refcnt > 1) {
                    --_storage.internal->refcnt;
                    _reserve_middle_new(pos, remove_count, insert_count);
                }
                else if (newlen > _storage.internal->capacity) {
                    auto old_buf  = _storage.internal;
                    auto old_dtor = _storage.dtor;
                    _reserve_middle_new(pos, remove_count, insert_count);
                    _release_internal(old_buf, old_dtor);
                }
                else _reserve_middle_move(pos, remove_count, insert_count, _storage.internal->start, _capacity_internal());
                break;
            case State::EXTERNAL:
                if (_storage.external->refcnt > 1) {
                    --_storage.external->refcnt;
                    _reserve_middle_new(pos, remove_count, insert_count);
                }
                else if (newlen > _storage.external->capacity) {
                    auto old_buf  = _storage.external;
                    auto old_dtor = _storage.dtor;
                    _reserve_middle_new(pos, remove_count, insert_count);
                    _release_external(old_buf, old_dtor);
                }
                else _reserve_middle_move(pos, remove_count, insert_count, _storage.external->ptr, _capacity_external());
                break;
            case State::LITERAL:
                _reserve_middle_new(pos, remove_count, insert_count);
                break;
            case State::SSO:
                if (newlen > MAX_SSO_CHARS) _new_internal_from_sso(newlen, pos, remove_count, insert_count);
                else _reserve_middle_move(pos, remove_count, insert_count, _sso, _capacity_sso());
                break;
        }

        _length = newlen;
    }

    void _reserve_middle_new (size_type pos, size_type remove_count, size_type insert_count) {
        auto old_str = _str;
        _new_auto(_length + insert_count - remove_count);
        if (pos) traits_type::copy(_str, old_str, pos);
        traits_type::copy(_str + pos + insert_count, old_str + pos + remove_count, _length - pos - remove_count);
    }

    void _reserve_middle_move (size_type pos, size_type remove_count, size_type insert_count, CharT* ptr_start, size_type capacity_tail) {
        if (remove_count >= insert_count) {
            traits_type::move(_str + pos + insert_count, _str + pos + remove_count, _length - pos - remove_count);
            return;
        }

        auto extra_count = insert_count - remove_count;
        bool has_head_space = _str >= ptr_start + extra_count;
        bool has_tail_space = (capacity_tail - _length) >= extra_count;
        if (has_head_space && has_tail_space) { // move what is shorter



( run in 0.900 second using v1.01-cache-2.11-cpan-adec679a428 )