113271Sgabeblack@google.com/*****************************************************************************
213271Sgabeblack@google.com
313271Sgabeblack@google.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
413271Sgabeblack@google.com  more contributor license agreements.  See the NOTICE file distributed
513271Sgabeblack@google.com  with this work for additional information regarding copyright ownership.
613271Sgabeblack@google.com  Accellera licenses this file to you under the Apache License, Version 2.0
713271Sgabeblack@google.com  (the "License"); you may not use this file except in compliance with the
813271Sgabeblack@google.com  License.  You may obtain a copy of the License at
913271Sgabeblack@google.com
1013271Sgabeblack@google.com    http://www.apache.org/licenses/LICENSE-2.0
1113271Sgabeblack@google.com
1213271Sgabeblack@google.com  Unless required by applicable law or agreed to in writing, software
1313271Sgabeblack@google.com  distributed under the License is distributed on an "AS IS" BASIS,
1413271Sgabeblack@google.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1513271Sgabeblack@google.com  implied.  See the License for the specific language governing
1613271Sgabeblack@google.com  permissions and limitations under the License.
1713271Sgabeblack@google.com
1813271Sgabeblack@google.com *****************************************************************************/
1913271Sgabeblack@google.com
2012852Sgabeblack@google.com/*
2112852Sgabeblack@google.com * Copyright 2018 Google, Inc.
2212852Sgabeblack@google.com *
2312852Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
2412852Sgabeblack@google.com * modification, are permitted provided that the following conditions are
2512852Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
2612852Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
2712852Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
2812852Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
2912852Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
3012852Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
3112852Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
3212852Sgabeblack@google.com * this software without specific prior written permission.
3312852Sgabeblack@google.com *
3412852Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3512852Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3612852Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3712852Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3812852Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3912852Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4012852Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4112852Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4212852Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4312852Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
4412852Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4512852Sgabeblack@google.com *
4612852Sgabeblack@google.com * Authors: Gabe Black
4712852Sgabeblack@google.com */
4812852Sgabeblack@google.com
4912852Sgabeblack@google.com#ifndef __SYSTEMC_EXT_UTIL_SC_VECTOR_HH__
5012852Sgabeblack@google.com#define __SYSTEMC_EXT_UTIL_SC_VECTOR_HH__
5112852Sgabeblack@google.com
5212852Sgabeblack@google.com#include <stdint.h>
5312852Sgabeblack@google.com
5412852Sgabeblack@google.com#include <exception>
5512872Sgabeblack@google.com#include <iterator>
5612852Sgabeblack@google.com#include <vector>
5712852Sgabeblack@google.com
5813271Sgabeblack@google.com#include "../core/sc_module.hh"
5912852Sgabeblack@google.com#include "../core/sc_object.hh"
6013322Sgabeblack@google.com#include "messages.hh"
6112852Sgabeblack@google.com
6212872Sgabeblack@google.comnamespace sc_gem5
6312872Sgabeblack@google.com{
6412872Sgabeblack@google.com
6512872Sgabeblack@google.com// Goop for supporting sc_vector_iter, simplified from the Accellera version.
6612872Sgabeblack@google.com
6712872Sgabeblack@google.com#if __cplusplus >= 201103L
6812872Sgabeblack@google.com
6912872Sgabeblack@google.comusing std::enable_if;
7012872Sgabeblack@google.comusing std::remove_const;
7112872Sgabeblack@google.comusing std::is_same;
7212872Sgabeblack@google.comusing std::is_const;
7312872Sgabeblack@google.com
7412872Sgabeblack@google.com#else
7512872Sgabeblack@google.com
7612872Sgabeblack@google.comtemplate<bool Cond, typename T=void>
7712872Sgabeblack@google.comstruct enable_if
7812872Sgabeblack@google.com{};
7912872Sgabeblack@google.com
8012872Sgabeblack@google.comtemplate<typename T>
8112872Sgabeblack@google.comstruct enable_if<true, T>
8212872Sgabeblack@google.com{
8312872Sgabeblack@google.com    typedef T type;
8412872Sgabeblack@google.com};
8512872Sgabeblack@google.com
8612872Sgabeblack@google.comtemplate <typename T>
8712872Sgabeblack@google.comstruct remove_const
8812872Sgabeblack@google.com{
8912872Sgabeblack@google.com    typedef T type;
9012872Sgabeblack@google.com};
9112872Sgabeblack@google.comtemplate <typename T>
9212872Sgabeblack@google.comstruct remove_const<const T>
9312872Sgabeblack@google.com{
9412872Sgabeblack@google.com    typedef T type;
9512872Sgabeblack@google.com};
9612872Sgabeblack@google.com
9712872Sgabeblack@google.comtemplate <typename T, typename U>
9812872Sgabeblack@google.comstruct is_same
9912872Sgabeblack@google.com{
10012872Sgabeblack@google.com    static const bool value = false;
10112872Sgabeblack@google.com};
10212872Sgabeblack@google.comtemplate <typename T>
10312872Sgabeblack@google.comstruct is_same<T, T>
10412872Sgabeblack@google.com{
10512872Sgabeblack@google.com    static const bool value = true;
10612872Sgabeblack@google.com};
10712872Sgabeblack@google.com
10812872Sgabeblack@google.comtemplate <typename T>
10912872Sgabeblack@google.comstruct is_const
11012872Sgabeblack@google.com{
11112872Sgabeblack@google.com    static const bool value = false;
11212872Sgabeblack@google.com};
11312872Sgabeblack@google.comtemplate <typename T>
11412872Sgabeblack@google.comstruct is_const<const T>
11512872Sgabeblack@google.com{
11612872Sgabeblack@google.com    static const bool value = true;
11712872Sgabeblack@google.com};
11812872Sgabeblack@google.com
11912872Sgabeblack@google.com#endif
12012872Sgabeblack@google.com
12112872Sgabeblack@google.comtemplate <typename CT, typename T>
12212872Sgabeblack@google.comstruct is_more_const
12312872Sgabeblack@google.com{
12412872Sgabeblack@google.com    static const bool value =
12512872Sgabeblack@google.com        is_same<typename remove_const<CT>::type,
12612872Sgabeblack@google.com                typename remove_const<T>::type>::value &&
12712872Sgabeblack@google.com        is_const<CT>::value >= is_const<T>::value;
12812872Sgabeblack@google.com};
12912872Sgabeblack@google.com
13012872Sgabeblack@google.comstruct special_result
13112872Sgabeblack@google.com{};
13212872Sgabeblack@google.com
13312872Sgabeblack@google.comtemplate <typename T>
13412872Sgabeblack@google.comstruct remove_special_fptr
13512872Sgabeblack@google.com{};
13612872Sgabeblack@google.com
13712872Sgabeblack@google.comtemplate <typename T>
13812872Sgabeblack@google.comstruct remove_special_fptr<special_result & (*)(T)>
13912872Sgabeblack@google.com{
14012872Sgabeblack@google.com    typedef T type;
14112872Sgabeblack@google.com};
14212872Sgabeblack@google.com
14312872Sgabeblack@google.com#define SC_RPTYPE_(Type) \
14412872Sgabeblack@google.com    ::sc_gem5::remove_special_fptr< \
14512872Sgabeblack@google.com        ::sc_gem5::special_result & (*) Type>::type::value
14612872Sgabeblack@google.com
14712872Sgabeblack@google.com#define SC_ENABLE_IF_(Cond) \
14812872Sgabeblack@google.com    typename ::sc_gem5::enable_if<SC_RPTYPE_(Cond)>::type * = NULL
14912872Sgabeblack@google.com
15012872Sgabeblack@google.com} // namespace sc_gem5
15112872Sgabeblack@google.com
15212852Sgabeblack@google.comnamespace sc_core
15312852Sgabeblack@google.com{
15412852Sgabeblack@google.com
15512852Sgabeblack@google.comtemplate <typename T, typename MT>
15612852Sgabeblack@google.comclass sc_vector_assembly;
15712852Sgabeblack@google.com
15812852Sgabeblack@google.comtemplate <typename T>
15912852Sgabeblack@google.comclass sc_vector;
16012852Sgabeblack@google.com
16112852Sgabeblack@google.comtemplate <typename T, typename MT>
16212852Sgabeblack@google.comsc_vector_assembly<T, MT> sc_assemble_vector(
16312852Sgabeblack@google.com        sc_vector<T> &, MT(T::* member_ptr));
16412852Sgabeblack@google.com
16512852Sgabeblack@google.comclass sc_vector_base : public sc_object
16612852Sgabeblack@google.com{
16712852Sgabeblack@google.com  public:
16812852Sgabeblack@google.com    typedef size_t size_type;
16912852Sgabeblack@google.com
17013271Sgabeblack@google.com    sc_vector_base(const char *_name) : sc_object(_name) {}
17113271Sgabeblack@google.com
17212852Sgabeblack@google.com    virtual const char *kind() const { return "sc_vector"; }
17312852Sgabeblack@google.com    size_type size() const;
17412852Sgabeblack@google.com    const std::vector<sc_object *> &get_elements() const;
17513271Sgabeblack@google.com
17613271Sgabeblack@google.com  protected:
17713271Sgabeblack@google.com    std::vector<void *> objs;
17813271Sgabeblack@google.com
17913271Sgabeblack@google.com    // What's returned by get_elements, which really returns the elemenets
18013271Sgabeblack@google.com    // which are also objects.
18113271Sgabeblack@google.com    mutable std::vector<sc_object *> elements;
18213271Sgabeblack@google.com
18313271Sgabeblack@google.com    sc_object *implicitCast(sc_object *p) const { return p; }
18413271Sgabeblack@google.com    sc_object *implicitCast(...) const
18513271Sgabeblack@google.com    {
18613322Sgabeblack@google.com        SC_REPORT_ERROR(SC_ID_VECTOR_NONOBJECT_ELEMENTS_, name());
18713271Sgabeblack@google.com        return nullptr;
18813271Sgabeblack@google.com    }
18913271Sgabeblack@google.com    virtual sc_object *objectCast(void *) const = 0;
19013271Sgabeblack@google.com
19113271Sgabeblack@google.com    void checkIndex(size_type index) const;
19213271Sgabeblack@google.com    void forceParent() const;
19313271Sgabeblack@google.com    void unforceParent() const;
19413271Sgabeblack@google.com
19513271Sgabeblack@google.com    void reportEmpty(const char *kind_, bool empty_dest) const;
19612852Sgabeblack@google.com};
19712852Sgabeblack@google.com
19812872Sgabeblack@google.com
19912872Sgabeblack@google.com/*
20012872Sgabeblack@google.com * Non-standard iterator access adapters. Without using these, the classes as
20112872Sgabeblack@google.com * defined in the standard won't compile because of redundant bind() overloads.
20212872Sgabeblack@google.com */
20312872Sgabeblack@google.com
20412872Sgabeblack@google.comtemplate <typename Element>
20512872Sgabeblack@google.comclass sc_direct_access
20612872Sgabeblack@google.com{
20712872Sgabeblack@google.com  public:
20812872Sgabeblack@google.com    typedef Element ElementType;
20912872Sgabeblack@google.com    typedef ElementType Type;
21012872Sgabeblack@google.com    typedef typename sc_gem5::remove_const<ElementType>::type PlainType;
21112872Sgabeblack@google.com
21212872Sgabeblack@google.com    typedef sc_direct_access<ElementType> Policy;
21312872Sgabeblack@google.com    typedef sc_direct_access<PlainType> NonConstPolicy;
21412872Sgabeblack@google.com    typedef sc_direct_access<const PlainType> ConstPolicy;
21512872Sgabeblack@google.com
21612872Sgabeblack@google.com    sc_direct_access() {}
21712872Sgabeblack@google.com    sc_direct_access(const NonConstPolicy &) {}
21812872Sgabeblack@google.com
21912872Sgabeblack@google.com    template <typename U>
22012872Sgabeblack@google.com    sc_direct_access(const U &,
22112872Sgabeblack@google.com        SC_ENABLE_IF_((
22212872Sgabeblack@google.com            sc_gem5::is_more_const<
22312872Sgabeblack@google.com                    ElementType, typename U::Policy::ElementType>
22412872Sgabeblack@google.com        ))
22512872Sgabeblack@google.com    )
22612872Sgabeblack@google.com    {}
22712872Sgabeblack@google.com
22812872Sgabeblack@google.com    ElementType *
22912872Sgabeblack@google.com    get(ElementType *this_) const
23012872Sgabeblack@google.com    {
23112872Sgabeblack@google.com        return this_;
23212872Sgabeblack@google.com    }
23312872Sgabeblack@google.com};
23412872Sgabeblack@google.com
23512872Sgabeblack@google.comtemplate <typename Element, typename Access>
23612872Sgabeblack@google.comclass sc_member_access
23712872Sgabeblack@google.com{
23812872Sgabeblack@google.com  public:
23912872Sgabeblack@google.com    template <typename, typename>
24012872Sgabeblack@google.com    friend class sc_member_access;
24112872Sgabeblack@google.com
24212872Sgabeblack@google.com    typedef Element ElementType;
24312872Sgabeblack@google.com    typedef Access AccessType;
24412872Sgabeblack@google.com    typedef AccessType (ElementType::*MemberType);
24512872Sgabeblack@google.com    typedef AccessType Type;
24612872Sgabeblack@google.com    typedef typename sc_gem5::remove_const<AccessType>::type PlainType;
24712872Sgabeblack@google.com    typedef typename sc_gem5::remove_const<ElementType>::type PlainElemType;
24812872Sgabeblack@google.com
24912872Sgabeblack@google.com    typedef sc_member_access<ElementType, AccessType> Policy;
25012872Sgabeblack@google.com    typedef sc_member_access<PlainElemType, PlainType> NonConstPolicy;
25112872Sgabeblack@google.com    typedef sc_member_access<const PlainElemType, const PlainType> ConstPolicy;
25212872Sgabeblack@google.com
25312872Sgabeblack@google.com    sc_member_access(MemberType ptr) : ptr_(ptr) {}
25412872Sgabeblack@google.com    sc_member_access(const NonConstPolicy &other) : ptr_(other.ptr_) {}
25512872Sgabeblack@google.com
25612872Sgabeblack@google.com    AccessType *get(ElementType *this_) const { return &(this_->*ptr_); }
25712872Sgabeblack@google.com
25812872Sgabeblack@google.com  private:
25912872Sgabeblack@google.com    MemberType ptr_;
26012872Sgabeblack@google.com};
26112872Sgabeblack@google.com
26212872Sgabeblack@google.comtemplate <typename Element,
26312872Sgabeblack@google.com          typename AccessPolicy=sc_direct_access<Element> >
26412852Sgabeblack@google.comclass sc_vector_iter :
26512872Sgabeblack@google.com        public std::iterator<std::random_access_iterator_tag,
26612872Sgabeblack@google.com                             typename AccessPolicy::Type>,
26712872Sgabeblack@google.com        private AccessPolicy
26812852Sgabeblack@google.com{
26912872Sgabeblack@google.com  private:
27012872Sgabeblack@google.com    typedef Element ElementType;
27112872Sgabeblack@google.com    typedef typename AccessPolicy::Policy Policy;
27212872Sgabeblack@google.com    typedef typename AccessPolicy::NonConstPolicy NonConstPolicy;
27312872Sgabeblack@google.com    typedef typename AccessPolicy::ConstPolicy ConstPolicy;
27412872Sgabeblack@google.com    typedef typename Policy::Type AccessType;
27512872Sgabeblack@google.com
27612872Sgabeblack@google.com    typedef typename sc_gem5::remove_const<ElementType>::type PlainType;
27712872Sgabeblack@google.com    typedef const PlainType ConstPlainType;
27812872Sgabeblack@google.com    typedef typename sc_direct_access<PlainType>::ConstPolicy
27912872Sgabeblack@google.com        ConstDirectPolicy;
28012872Sgabeblack@google.com
28112872Sgabeblack@google.com    friend class sc_vector<PlainType>;
28212872Sgabeblack@google.com    template <typename, typename>
28312872Sgabeblack@google.com    friend class sc_vector_assembly;
28412872Sgabeblack@google.com    template <typename, typename>
28512872Sgabeblack@google.com    friend class sc_vector_iter;
28612872Sgabeblack@google.com
28712872Sgabeblack@google.com    typedef std::iterator<std::random_access_iterator_tag, AccessType>
28812872Sgabeblack@google.com        BaseType;
28912872Sgabeblack@google.com    typedef sc_vector_iter ThisType;
29012872Sgabeblack@google.com    typedef sc_vector<PlainType> VectorType;
29112872Sgabeblack@google.com    typedef std::vector<void *> StorageType;
29212872Sgabeblack@google.com
29312872Sgabeblack@google.com    template <typename U>
29412872Sgabeblack@google.com    struct SelectIter
29512872Sgabeblack@google.com    {
29612872Sgabeblack@google.com        typedef typename std::vector<void *>::iterator type;
29712872Sgabeblack@google.com    };
29812872Sgabeblack@google.com    template <typename U>
29912872Sgabeblack@google.com    struct SelectIter<const U>
30012872Sgabeblack@google.com    {
30112872Sgabeblack@google.com        typedef typename std::vector<void *>::const_iterator type;
30212872Sgabeblack@google.com    };
30312872Sgabeblack@google.com    typedef typename SelectIter<ElementType>::type RawIterator;
30412872Sgabeblack@google.com    typedef sc_vector_iter<ConstPlainType, ConstPolicy> ConstIterator;
30512872Sgabeblack@google.com    typedef sc_vector_iter<ConstPlainType, ConstDirectPolicy>
30612872Sgabeblack@google.com        ConstDirectIterator;
30712872Sgabeblack@google.com
30812872Sgabeblack@google.com    RawIterator it_;
30912872Sgabeblack@google.com
31012872Sgabeblack@google.com    sc_vector_iter(RawIterator it, Policy acc=Policy()) :
31112872Sgabeblack@google.com        Policy(acc), it_(it)
31212872Sgabeblack@google.com    {}
31312872Sgabeblack@google.com
31412872Sgabeblack@google.com    Policy const &get_policy() const { return *this; }
31512872Sgabeblack@google.com
31612872Sgabeblack@google.com  public:
31712852Sgabeblack@google.com    // Conforms to Random Access Iterator category.
31812852Sgabeblack@google.com    // See ISO/IEC 14882:2003(E), 24.1 [lib.iterator.requirements]
31912852Sgabeblack@google.com
32012872Sgabeblack@google.com    typedef typename BaseType::difference_type difference_type;
32112872Sgabeblack@google.com    typedef typename BaseType::reference reference;
32212872Sgabeblack@google.com    typedef typename BaseType::pointer pointer;
32312872Sgabeblack@google.com
32412872Sgabeblack@google.com    sc_vector_iter() : Policy(), it_() {}
32512872Sgabeblack@google.com
32612872Sgabeblack@google.com    template <typename It>
32712872Sgabeblack@google.com    sc_vector_iter(const It &it,
32812872Sgabeblack@google.com        SC_ENABLE_IF_((
32912872Sgabeblack@google.com            sc_gem5::is_more_const<
33012872Sgabeblack@google.com                ElementType, typename It::Policy::ElementType>
33112872Sgabeblack@google.com        ))
33212872Sgabeblack@google.com    ) : Policy(it.get_policy()), it_(it.it_)
33312872Sgabeblack@google.com    {}
33412872Sgabeblack@google.com
33512872Sgabeblack@google.com    ThisType &
33612872Sgabeblack@google.com    operator ++ ()
33712872Sgabeblack@google.com    {
33812872Sgabeblack@google.com        ++it_;
33912872Sgabeblack@google.com        return *this;
34012872Sgabeblack@google.com    }
34112872Sgabeblack@google.com    ThisType &
34212872Sgabeblack@google.com    operator -- ()
34312872Sgabeblack@google.com    {
34412872Sgabeblack@google.com        --it_;
34512872Sgabeblack@google.com        return *this;
34612872Sgabeblack@google.com    }
34712872Sgabeblack@google.com    ThisType
34812872Sgabeblack@google.com    operator ++ (int)
34912872Sgabeblack@google.com    {
35012872Sgabeblack@google.com        ThisType old(*this);
35112872Sgabeblack@google.com        ++it_;
35212872Sgabeblack@google.com        return old;
35312872Sgabeblack@google.com    }
35412872Sgabeblack@google.com    ThisType
35512872Sgabeblack@google.com    operator -- (int)
35612872Sgabeblack@google.com    {
35712872Sgabeblack@google.com        ThisType old(*this);
35812872Sgabeblack@google.com        --it_;
35912872Sgabeblack@google.com        return old;
36012872Sgabeblack@google.com    }
36112872Sgabeblack@google.com
36212872Sgabeblack@google.com    ThisType
36312872Sgabeblack@google.com    operator + (difference_type n) const
36412872Sgabeblack@google.com    {
36512872Sgabeblack@google.com        return ThisType(it_ + n, get_policy());
36612872Sgabeblack@google.com    }
36712872Sgabeblack@google.com    ThisType
36812872Sgabeblack@google.com    operator - (difference_type n) const
36912872Sgabeblack@google.com    {
37012872Sgabeblack@google.com        return ThisType(it_ - n, get_policy());
37112872Sgabeblack@google.com    }
37212872Sgabeblack@google.com
37312872Sgabeblack@google.com    ThisType &
37412872Sgabeblack@google.com    operator += (difference_type n)
37512872Sgabeblack@google.com    {
37612872Sgabeblack@google.com        it_ += n;
37712872Sgabeblack@google.com        return *this;
37812872Sgabeblack@google.com    }
37912872Sgabeblack@google.com
38012872Sgabeblack@google.com    ThisType &
38112872Sgabeblack@google.com    operator -= (difference_type n)
38212872Sgabeblack@google.com    {
38312872Sgabeblack@google.com        it_ -= n;
38412872Sgabeblack@google.com        return *this;
38512872Sgabeblack@google.com    }
38612872Sgabeblack@google.com
38712872Sgabeblack@google.com    bool
38812872Sgabeblack@google.com    operator == (const ConstDirectIterator &other) const
38912872Sgabeblack@google.com    {
39012872Sgabeblack@google.com        return it_ == other.it_;
39112872Sgabeblack@google.com    }
39212872Sgabeblack@google.com    bool
39312872Sgabeblack@google.com    operator != (const ConstDirectIterator &other) const
39412872Sgabeblack@google.com    {
39512872Sgabeblack@google.com        return it_ != other.it_;
39612872Sgabeblack@google.com    }
39712872Sgabeblack@google.com    bool
39812872Sgabeblack@google.com    operator <= (const ConstDirectIterator &other) const
39912872Sgabeblack@google.com    {
40012872Sgabeblack@google.com        return it_ <= other.it_;
40112872Sgabeblack@google.com    }
40212872Sgabeblack@google.com    bool
40312872Sgabeblack@google.com    operator >= (const ConstDirectIterator &other) const
40412872Sgabeblack@google.com    {
40512872Sgabeblack@google.com        return it_ >= other.it_;
40612872Sgabeblack@google.com    }
40712872Sgabeblack@google.com    bool
40812872Sgabeblack@google.com    operator < (const ConstDirectIterator &other) const
40912872Sgabeblack@google.com    {
41012872Sgabeblack@google.com        return it_ < other.it_;
41112872Sgabeblack@google.com    }
41212872Sgabeblack@google.com    bool
41312872Sgabeblack@google.com    operator > (const ConstDirectIterator &other) const
41412872Sgabeblack@google.com    {
41512872Sgabeblack@google.com        return it_ > other.it_;
41612872Sgabeblack@google.com    }
41712872Sgabeblack@google.com
41812872Sgabeblack@google.com    reference
41912872Sgabeblack@google.com    operator * () const
42012872Sgabeblack@google.com    {
42112872Sgabeblack@google.com        return *Policy::get(static_cast<ElementType *>((void *)*it_));
42212872Sgabeblack@google.com    }
42312872Sgabeblack@google.com    pointer
42412872Sgabeblack@google.com    operator -> () const
42512872Sgabeblack@google.com    {
42612872Sgabeblack@google.com        return Policy::get(static_cast<ElementType *>((void *)*it_));
42712872Sgabeblack@google.com    }
42812872Sgabeblack@google.com    reference
42912872Sgabeblack@google.com    operator [] (difference_type n) const
43012872Sgabeblack@google.com    {
43112872Sgabeblack@google.com        return *Policy::get(static_cast<ElementType *>((void *)it_[n]));
43212872Sgabeblack@google.com    }
43312872Sgabeblack@google.com
43412872Sgabeblack@google.com    difference_type
43512872Sgabeblack@google.com    operator - (ConstDirectIterator const &other) const
43612872Sgabeblack@google.com    {
43712872Sgabeblack@google.com        return it_ - other.it_;
43812872Sgabeblack@google.com    }
43912852Sgabeblack@google.com};
44012852Sgabeblack@google.com
44112852Sgabeblack@google.comtemplate <typename T>
44212852Sgabeblack@google.comclass sc_vector : public sc_vector_base
44312852Sgabeblack@google.com{
44412852Sgabeblack@google.com  public:
44512852Sgabeblack@google.com    using sc_vector_base::size_type;
44612852Sgabeblack@google.com    typedef sc_vector_iter<T> iterator;
44712852Sgabeblack@google.com    typedef sc_vector_iter<const T> const_iterator;
44812852Sgabeblack@google.com
44913271Sgabeblack@google.com    sc_vector() : sc_vector_base(::sc_core::sc_gen_unique_name("vector")) {}
45013271Sgabeblack@google.com    explicit sc_vector(const char *_name) : sc_vector_base(_name) {}
45113271Sgabeblack@google.com    sc_vector(const char *_name, size_type _size) : sc_vector_base(_name)
45212852Sgabeblack@google.com    {
45313271Sgabeblack@google.com        init(_size);
45412852Sgabeblack@google.com    }
45512852Sgabeblack@google.com    template <typename Creator>
45613271Sgabeblack@google.com    sc_vector(const char *_name, size_type _size, Creator creator) :
45713271Sgabeblack@google.com        sc_vector_base(_name)
45812852Sgabeblack@google.com    {
45913271Sgabeblack@google.com        init(_size, creator);
46012852Sgabeblack@google.com    }
46113271Sgabeblack@google.com    virtual ~sc_vector() { clear(); }
46212852Sgabeblack@google.com
46312852Sgabeblack@google.com    void
46413271Sgabeblack@google.com    init(size_type _size)
46512852Sgabeblack@google.com    {
46613271Sgabeblack@google.com        init(_size, &sc_vector<T>::create_element);
46712852Sgabeblack@google.com    }
46812852Sgabeblack@google.com    static T *
46913271Sgabeblack@google.com    create_element(const char *_name, size_type index)
47012852Sgabeblack@google.com    {
47113271Sgabeblack@google.com        return new T(_name);
47212852Sgabeblack@google.com    }
47312852Sgabeblack@google.com
47412852Sgabeblack@google.com    template <typename Creator>
47512852Sgabeblack@google.com    void
47613271Sgabeblack@google.com    init(size_type _size, Creator creator)
47712852Sgabeblack@google.com    {
47813271Sgabeblack@google.com        forceParent();
47913271Sgabeblack@google.com        try {
48013271Sgabeblack@google.com            for (size_type i = 0; i < _size; i++) {
48113271Sgabeblack@google.com                // XXX The name and scope of these objects needs to be handled
48213271Sgabeblack@google.com                // specially.
48313271Sgabeblack@google.com                T *p = creator(sc_gen_unique_name(basename()), i);
48413271Sgabeblack@google.com                objs.push_back(p);
48513271Sgabeblack@google.com            }
48613271Sgabeblack@google.com        } catch (...) {
48713271Sgabeblack@google.com            unforceParent();
48813271Sgabeblack@google.com            clear();
48913271Sgabeblack@google.com            throw;
49013271Sgabeblack@google.com        }
49113271Sgabeblack@google.com        unforceParent();
49213271Sgabeblack@google.com    }
49313271Sgabeblack@google.com
49413271Sgabeblack@google.com    T &operator [] (size_type index) { return *static_cast<T *>(objs[index]); }
49513271Sgabeblack@google.com    const T &
49613271Sgabeblack@google.com    operator [] (size_type index) const
49713271Sgabeblack@google.com    {
49813271Sgabeblack@google.com        return *static_cast<const T *>(objs[index]);
49912852Sgabeblack@google.com    }
50012852Sgabeblack@google.com
50112852Sgabeblack@google.com    T &
50213271Sgabeblack@google.com    at(size_type index)
50312852Sgabeblack@google.com    {
50413271Sgabeblack@google.com        this->checkIndex(index);
50513271Sgabeblack@google.com        return *static_cast<T *>(objs[index]);
50612852Sgabeblack@google.com    }
50712852Sgabeblack@google.com    const T &
50813271Sgabeblack@google.com    at(size_type index) const
50912852Sgabeblack@google.com    {
51013271Sgabeblack@google.com        this->checkIndex(index);
51113271Sgabeblack@google.com        return *static_cast<const T *>(objs[index]);
51212852Sgabeblack@google.com    }
51312852Sgabeblack@google.com
51413271Sgabeblack@google.com    iterator begin() { return objs.begin(); }
51513271Sgabeblack@google.com    iterator end() { return objs.end(); }
51613271Sgabeblack@google.com    const_iterator begin() const { return objs.begin(); }
51713271Sgabeblack@google.com    const_iterator end() const { return objs.end(); }
51813271Sgabeblack@google.com    const_iterator cbegin() const { return objs.begin(); }
51913271Sgabeblack@google.com    const_iterator cend() const { return objs.end(); }
52012852Sgabeblack@google.com
52112852Sgabeblack@google.com    template <typename ContainerType, typename ArgumentType>
52212852Sgabeblack@google.com    iterator
52313271Sgabeblack@google.com    bind(sc_vector_assembly<ContainerType, ArgumentType> c)
52412852Sgabeblack@google.com    {
52513271Sgabeblack@google.com        return bind(c.begin(), c.end());
52612852Sgabeblack@google.com    }
52712852Sgabeblack@google.com
52812852Sgabeblack@google.com    template <typename BindableContainer>
52912852Sgabeblack@google.com    iterator
53013271Sgabeblack@google.com    bind(BindableContainer &c)
53112852Sgabeblack@google.com    {
53213271Sgabeblack@google.com        return bind(c.begin(), c.end());
53312852Sgabeblack@google.com    }
53412852Sgabeblack@google.com
53512852Sgabeblack@google.com    template <typename BindableIterator>
53612852Sgabeblack@google.com    iterator
53713271Sgabeblack@google.com    bind(BindableIterator first, BindableIterator last)
53812852Sgabeblack@google.com    {
53913271Sgabeblack@google.com        return bind(first, last, this->begin());
54012852Sgabeblack@google.com    }
54112852Sgabeblack@google.com
54212852Sgabeblack@google.com    template <typename BindableIterator>
54312852Sgabeblack@google.com    iterator
54413271Sgabeblack@google.com    bind(BindableIterator first, BindableIterator last, iterator from)
54512852Sgabeblack@google.com    {
54613271Sgabeblack@google.com        if (!size() || from == end() || first == last)
54713271Sgabeblack@google.com            reportEmpty(kind(), from == end());
54813271Sgabeblack@google.com
54913271Sgabeblack@google.com        while (from != end() && first != last)
55013271Sgabeblack@google.com            (*from++).bind(*first++);
55113271Sgabeblack@google.com        return from;
55212852Sgabeblack@google.com    }
55312852Sgabeblack@google.com
55412852Sgabeblack@google.com    template <typename ContainerType, typename ArgumentType>
55512852Sgabeblack@google.com    iterator
55612852Sgabeblack@google.com    operator () (sc_vector_assembly<ContainerType, ArgumentType> c)
55712852Sgabeblack@google.com    {
55813271Sgabeblack@google.com        return (*this)(c.begin(), c.end());
55912852Sgabeblack@google.com    }
56012852Sgabeblack@google.com
56112852Sgabeblack@google.com    template <typename ArgumentContainer>
56212852Sgabeblack@google.com    iterator
56313271Sgabeblack@google.com    operator () (ArgumentContainer &c)
56412852Sgabeblack@google.com    {
56513271Sgabeblack@google.com        return (*this)(c.begin(), c.end());
56612852Sgabeblack@google.com    }
56712852Sgabeblack@google.com
56812852Sgabeblack@google.com    template <typename ArgumentIterator>
56912852Sgabeblack@google.com    iterator
57013271Sgabeblack@google.com    operator () (ArgumentIterator first, ArgumentIterator last)
57112852Sgabeblack@google.com    {
57213271Sgabeblack@google.com        return (*this)(first, last, this->begin());
57312852Sgabeblack@google.com    }
57412852Sgabeblack@google.com
57512852Sgabeblack@google.com    template <typename ArgumentIterator>
57612852Sgabeblack@google.com    iterator
57713271Sgabeblack@google.com    operator () (ArgumentIterator first, ArgumentIterator last, iterator from)
57812852Sgabeblack@google.com    {
57913271Sgabeblack@google.com        if (!size() || from == end() || first == last)
58013271Sgabeblack@google.com            reportEmpty(kind(), from == end());
58113271Sgabeblack@google.com
58213271Sgabeblack@google.com        while (from != end() && first != last)
58313271Sgabeblack@google.com            (*from++)(*first++);
58413271Sgabeblack@google.com        return from;
58512852Sgabeblack@google.com    }
58612852Sgabeblack@google.com
58712852Sgabeblack@google.com  private:
58812852Sgabeblack@google.com    // Disabled
58913381Sgabeblack@google.com    sc_vector(const sc_vector &);
59013381Sgabeblack@google.com    sc_vector &operator = (const sc_vector &);
59113271Sgabeblack@google.com
59213271Sgabeblack@google.com    void
59313271Sgabeblack@google.com    clear()
59413271Sgabeblack@google.com    {
59513271Sgabeblack@google.com        for (auto obj: objs)
59613271Sgabeblack@google.com            delete static_cast<T *>(obj);
59713271Sgabeblack@google.com    }
59813271Sgabeblack@google.com
59913271Sgabeblack@google.com    template <typename, typename>
60013271Sgabeblack@google.com    friend class sc_vector_assembly;
60113271Sgabeblack@google.com
60213271Sgabeblack@google.com    sc_object *
60313271Sgabeblack@google.com    objectCast(void *ptr) const
60413271Sgabeblack@google.com    {
60513271Sgabeblack@google.com        return implicitCast(static_cast<T *>(ptr));
60613271Sgabeblack@google.com    }
60712852Sgabeblack@google.com};
60812852Sgabeblack@google.com
60912852Sgabeblack@google.comtemplate <typename T, typename MT>
61012852Sgabeblack@google.comclass sc_vector_assembly
61112852Sgabeblack@google.com{
61212852Sgabeblack@google.com  public:
61312852Sgabeblack@google.com    friend sc_vector_assembly<T, MT> sc_assemble_vector<>(
61412872Sgabeblack@google.com            sc_vector<T> &, MT (T::*));
61512852Sgabeblack@google.com
61612852Sgabeblack@google.com    typedef size_t size_type;
61712872Sgabeblack@google.com    typedef sc_vector_iter<T, sc_member_access<T, MT> > iterator;
61812872Sgabeblack@google.com    typedef sc_vector_iter<
61912872Sgabeblack@google.com        const T, sc_member_access<const T, const MT> > const_iterator;
62012872Sgabeblack@google.com    typedef MT (T::*MemberType);
62112852Sgabeblack@google.com
62213271Sgabeblack@google.com    sc_vector_assembly(const sc_vector_assembly &other) :
62313271Sgabeblack@google.com        vec_(other.vec_), ptr_(other.ptr_)
62413271Sgabeblack@google.com    {}
62512852Sgabeblack@google.com
62612872Sgabeblack@google.com    iterator begin() { return iterator(vec_->begin().it_, ptr_); }
62712872Sgabeblack@google.com    iterator end() { return iterator(vec_->end().it_, ptr_); }
62812852Sgabeblack@google.com
62912852Sgabeblack@google.com    const_iterator
63012852Sgabeblack@google.com    cbegin() const
63112852Sgabeblack@google.com    {
63212872Sgabeblack@google.com        return const_iterator(vec_->begin().it_, ptr_);
63312852Sgabeblack@google.com    }
63412852Sgabeblack@google.com    const_iterator
63512852Sgabeblack@google.com    cend() const
63612852Sgabeblack@google.com    {
63712872Sgabeblack@google.com        return const_iterator(vec_->end().it_, ptr_);
63812852Sgabeblack@google.com    }
63912852Sgabeblack@google.com
64012872Sgabeblack@google.com    const_iterator
64112872Sgabeblack@google.com    begin() const
64212852Sgabeblack@google.com    {
64312872Sgabeblack@google.com        return const_iterator(vec_->begin().it_, ptr_);
64412852Sgabeblack@google.com    }
64512872Sgabeblack@google.com    const_iterator
64612872Sgabeblack@google.com    end() const
64712872Sgabeblack@google.com    {
64812872Sgabeblack@google.com        return const_iterator(vec_->end().it_, ptr_);
64912872Sgabeblack@google.com    }
65012872Sgabeblack@google.com
65112872Sgabeblack@google.com    size_type size() const { return vec_->size(); }
65212872Sgabeblack@google.com
65312852Sgabeblack@google.com    std::vector<sc_object *>
65412852Sgabeblack@google.com    get_elements() const
65512852Sgabeblack@google.com    {
65613271Sgabeblack@google.com        std::vector<sc_object *> ret;
65713271Sgabeblack@google.com        for (const_iterator it = begin(); it != end(); it++) {
65813271Sgabeblack@google.com            sc_object *obj_ptr = vec_->objectCast(const_cast<MT *>(&*it));
65913271Sgabeblack@google.com
66013271Sgabeblack@google.com            if (obj_ptr)
66113271Sgabeblack@google.com                ret.push_back(obj_ptr);
66213271Sgabeblack@google.com        }
66313271Sgabeblack@google.com        return ret;
66412852Sgabeblack@google.com    }
66512852Sgabeblack@google.com
66612852Sgabeblack@google.com    typename iterator::reference
66712872Sgabeblack@google.com    operator [] (size_type i)
66812852Sgabeblack@google.com    {
66912872Sgabeblack@google.com        return (*vec_)[i].*ptr_;
67012852Sgabeblack@google.com    }
67112852Sgabeblack@google.com    typename const_iterator::reference
67212872Sgabeblack@google.com    operator [] (size_type i) const
67312852Sgabeblack@google.com    {
67412872Sgabeblack@google.com        return (*vec_)[i].*ptr_;
67512852Sgabeblack@google.com    }
67612852Sgabeblack@google.com
67712852Sgabeblack@google.com    typename iterator::reference
67812872Sgabeblack@google.com    at(size_type i)
67912852Sgabeblack@google.com    {
68012872Sgabeblack@google.com        return vec_->at(i).*ptr_;
68112852Sgabeblack@google.com    }
68212852Sgabeblack@google.com    typename const_iterator::reference
68312872Sgabeblack@google.com    at(size_type i) const
68412852Sgabeblack@google.com    {
68512872Sgabeblack@google.com        return vec_->at(i).*ptr_;
68612852Sgabeblack@google.com    }
68712852Sgabeblack@google.com
68812852Sgabeblack@google.com    template <typename ContainerType, typename ArgumentType>
68912852Sgabeblack@google.com    iterator
69013271Sgabeblack@google.com    bind(sc_vector_assembly<ContainerType, ArgumentType> c)
69112852Sgabeblack@google.com    {
69213271Sgabeblack@google.com        return bind(c.begin(), c.end());
69312852Sgabeblack@google.com    }
69412852Sgabeblack@google.com
69512852Sgabeblack@google.com    template <typename BindableContainer>
69612852Sgabeblack@google.com    iterator
69713271Sgabeblack@google.com    bind(BindableContainer &c)
69812852Sgabeblack@google.com    {
69913271Sgabeblack@google.com        return bind(c.begin(), c.end());
70012852Sgabeblack@google.com    }
70112852Sgabeblack@google.com
70212852Sgabeblack@google.com    template <typename BindableIterator>
70312852Sgabeblack@google.com    iterator
70413271Sgabeblack@google.com    bind(BindableIterator first, BindableIterator last)
70512852Sgabeblack@google.com    {
70613271Sgabeblack@google.com        return bind(first, last, this->begin());
70712852Sgabeblack@google.com    }
70812852Sgabeblack@google.com
70912852Sgabeblack@google.com    template <typename BindableIterator>
71012852Sgabeblack@google.com    iterator
71113271Sgabeblack@google.com    bind(BindableIterator first, BindableIterator last, iterator from)
71212852Sgabeblack@google.com    {
71313271Sgabeblack@google.com        if (!size() || from == end() || first == last)
71413271Sgabeblack@google.com            vec_->reportEmpty("sc_vector_assembly", from == end());
71513271Sgabeblack@google.com
71613271Sgabeblack@google.com        while (from != end() && first != last)
71713271Sgabeblack@google.com            (*from++).bind(*first++);
71813271Sgabeblack@google.com        return from;
71912852Sgabeblack@google.com    }
72012852Sgabeblack@google.com
72112852Sgabeblack@google.com    template <typename BindableIterator>
72212852Sgabeblack@google.com    iterator
72313271Sgabeblack@google.com    bind(BindableIterator first, BindableIterator last,
72413271Sgabeblack@google.com            typename sc_vector<T>::iterator from)
72512852Sgabeblack@google.com    {
72613271Sgabeblack@google.com        return bind(first, last, iterator(from.it_, ptr_));
72712852Sgabeblack@google.com    }
72812852Sgabeblack@google.com
72912852Sgabeblack@google.com    template <typename ContainerType, typename ArgumentType>
73012852Sgabeblack@google.com    iterator
73113271Sgabeblack@google.com    operator () (sc_vector_assembly<ContainerType, ArgumentType> c)
73212852Sgabeblack@google.com    {
73313271Sgabeblack@google.com        return (*this)(c.begin(), c.end());
73412852Sgabeblack@google.com    }
73512852Sgabeblack@google.com
73612852Sgabeblack@google.com    template <typename ArgumentContainer>
73712852Sgabeblack@google.com    iterator
73813271Sgabeblack@google.com    operator () (ArgumentContainer &c)
73912852Sgabeblack@google.com    {
74013271Sgabeblack@google.com        return (*this)(c.begin(), c.end());
74112852Sgabeblack@google.com    }
74212852Sgabeblack@google.com
74312852Sgabeblack@google.com    template <typename ArgumentIterator>
74412852Sgabeblack@google.com    iterator
74513271Sgabeblack@google.com    operator () (ArgumentIterator first, ArgumentIterator last)
74612852Sgabeblack@google.com    {
74713271Sgabeblack@google.com        return (*this)(first, last, this->begin());
74812852Sgabeblack@google.com    }
74912852Sgabeblack@google.com
75012852Sgabeblack@google.com    template <typename ArgumentIterator>
75112852Sgabeblack@google.com    iterator
75213271Sgabeblack@google.com    operator () (ArgumentIterator first, ArgumentIterator last, iterator from)
75312852Sgabeblack@google.com    {
75413271Sgabeblack@google.com        if (!size() || from == end() || first == last)
75513271Sgabeblack@google.com            vec_->reportEmpty("sc_vector_assembly", from == end());
75613271Sgabeblack@google.com
75713271Sgabeblack@google.com        while (from != end() && first != last)
75813271Sgabeblack@google.com            (*from++)(*first++);
75913271Sgabeblack@google.com        return from;
76012852Sgabeblack@google.com    }
76112852Sgabeblack@google.com
76212852Sgabeblack@google.com    template <typename ArgumentIterator>
76312852Sgabeblack@google.com    iterator
76413271Sgabeblack@google.com    operator () (ArgumentIterator first, ArgumentIterator last,
76513271Sgabeblack@google.com                 typename sc_vector<T>::iterator from)
76612852Sgabeblack@google.com    {
76713271Sgabeblack@google.com        return (*this)(first, last, iterator(from.it_, ptr_));
76812852Sgabeblack@google.com    }
76912852Sgabeblack@google.com
77012852Sgabeblack@google.com  private:
77112872Sgabeblack@google.com    sc_vector_assembly(sc_vector<T> &v, MemberType ptr) :
77212872Sgabeblack@google.com        vec_(&v), ptr_(ptr)
77312872Sgabeblack@google.com    {}
77412872Sgabeblack@google.com
77512872Sgabeblack@google.com    sc_vector<T> *vec_;
77612872Sgabeblack@google.com    MemberType ptr_;
77712852Sgabeblack@google.com};
77812852Sgabeblack@google.com
77912852Sgabeblack@google.comtemplate <typename T, typename MT>
78012852Sgabeblack@google.comsc_vector_assembly<T, MT>
78112872Sgabeblack@google.comsc_assemble_vector(sc_vector<T> &v, MT (T::*ptr))
78212852Sgabeblack@google.com{
78312872Sgabeblack@google.com    return sc_vector_assembly<T, MT>(v, ptr);
78412852Sgabeblack@google.com}
78512852Sgabeblack@google.com
78612852Sgabeblack@google.com} // namespace sc_core
78712852Sgabeblack@google.com
78812852Sgabeblack@google.com#endif  //__SYSTEMC_EXT_UTIL_SC_VECTOR_HH__
789