1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     ut_Children.h
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 #ifndef NW_UT_CHILDREN_H_
19 #define NW_UT_CHILDREN_H_
20 
21 #include <nw/ut/ut_MoveArray.h>
22 
23 #include <nw/ut/ut_Preprocessor.h>
24 #include <nw/ut/ut_TypeTraits.h>
25 
26 namespace nw
27 {
28 namespace ut
29 {
30 
31 //---------------------------------------------------------------------------
32 //! @brief        子を削除するためのクラスです。
33 //!
34 //! @tparam       TChild 削除する子の型です。
35 //---------------------------------------------------------------------------
36 template<typename TChild>
37 class ChildDeleter
38 {
39 public:
ChildDeleter()40     ChildDeleter() : m_Allocator(0) {}
ChildDeleter(os::IAllocator * allocator)41     ChildDeleter(os::IAllocator* allocator) : m_Allocator(allocator) { }
42 
operator()43     void operator() (TChild* child)
44     {
45         child->~TChild();
46         if (m_Allocator)
47         {
48             m_Allocator->Free(child);
49         }
50     }
51 
52     os::IAllocator* m_Allocator;
53 };
54 
55 //---------------------------------------------------------------------------
56 //! @brief        子を外すためのクラスです。
57 //!
58 //! @tparam       TChild 外す子の型です。
59 //---------------------------------------------------------------------------
60 template<typename TChild>
61 class ChildDetacher
62 {
63 public:
ChildDetacher()64     ChildDetacher() {}
ChildDetacher(os::IAllocator * allocator)65     ChildDetacher(os::IAllocator* allocator) { NW_UNUSED_VARIABLE(allocator); }
66 
operator()67     void operator() (TChild* child)
68     {
69         if (child)
70         {
71             child->SetParent(NULL);
72         }
73     }
74 };
75 
76 //---------------------------------------------------------------------------
77 //! @brief        子のリストクラスです。
78 //!
79 //! @tparam       TChild 子の型です。
80 //! @tparam       TParent 親の型です。
81 //! @tparam       TDeleter 削除用の関数オブジェクトです。
82 //! @tparam       TChildList 子のリストの型です。
83 //---------------------------------------------------------------------------
84 template<
85     typename TChild,
86     typename TParent,
87     typename TDeleter = ChildDeleter<TChild>,
88     typename TChildList = MoveArray<TChild*> >
89 class Children
90 {
91 public:
92     typedef TChild*&                                      reference;
93     typedef TChild*                                       difference_type;
94     typedef TChild*                                       value_type;
95     typedef typename TChildList::iterator                 iterator;
96     typedef typename TChildList::const_iterator           const_iterator;
97 
98 #if defined(_MSC_VER) && _MSC_VER <= 1201
99     typedef std::reverse_iterator<iterator, TChild*>       reverse_iterator;
100     typedef std::reverse_iterator<const_iterator, TChild*> const_reverse_iterator;
101 #else
102     typedef std::reverse_iterator<iterator>               reverse_iterator;
103     typedef std::reverse_iterator<const_iterator>         const_reverse_iterator;
104 #endif
105     typedef TDeleter deleter_type;
106     typedef TDeleter& deleter_reference;
107     typedef const TDeleter& deleter_const_reference;
108 
109 public:
Children()110     Children() : m_Children(), m_Deleter() {}
111 
112     //! @brief        コンストラクタです。
113     //!
114     //! @param[in]    parent 親です。
115     //! @param[in]    elements 子のリストとして利用する確保されたメモリです。
116     //! @param[in]    size 子の数です。
117     //! @param[in]    allocator アロケータです。
118     //! @param[in]    kind 子のリストの種類です。
119     //!
120     Children(
121         TParent* parent,
122         void* elements,
123         size_t size,
124         os::IAllocator* allocator = 0,
125         ArrayKind kind = ARRAY_WRAPPER)
m_Parent(parent)126     : m_Parent(parent), m_Children(elements, size, allocator, kind), m_Deleter(allocator) {}
127 
128     //! @brief        コンストラクタです。
129     //!
130     //! @param[in]    parent 親です。
131     //! @param[in]    size 子の数です。
132     //! @param[in]    allocator アロケータです。
133     //! @param[in]    kind 子のリストの種類です。
134     //!
135     Children(
136         TParent* parent,
137         size_t size,
138         os::IAllocator* allocator,
139         ArrayKind kind = ARRAY_WRAPPER)
m_Parent(parent)140     : m_Parent(parent), m_Children(size, allocator, kind), m_Deleter(allocator) {}
141 
142     //! @brief        コンストラクタです。
143     //!
144     //! @param[in]    parent 親です。
145     //! @param[in]    allocator アロケータです。
146     //!
Children(TParent * parent,os::IAllocator * allocator)147     Children(
148         TParent* parent,
149         os::IAllocator* allocator)
150     : m_Parent(parent), m_Children(allocator), m_Deleter(allocator) {}
151 
152     //! @brief        コピーコンストラクタです。
153     //!
154     //! コピー元から要素を移動します。
155     //!
156     //! @param[in]    children コピー元の Children オブジェクトです。
157     //!
Children(const Children & children)158     Children(const Children& children)
159     : m_Parent(children.m_Parent),
160       m_Children(children.m_Children),
161       m_Deleter(children.m_Deleter)
162     {
163     }
164 
165     //! デストラクタです。
~Children()166     ~Children()
167     {
168         std::for_each(this->m_Children.begin(), this->m_Children.end(), m_Deleter);
169     }
170 
171 public:
172     struct SafeBoolHelper { int x; };
173     typedef int SafeBoolHelper::* SafeBool;
SafeBool()174     operator SafeBool() const { return m_Children; }
175 
176     //----------------------------------------
177     //! @name STLコンテナ互換機能
178     //@{
179 
begin()180     iterator begin() { return m_Children.begin(); }
begin()181     const_iterator begin() const { return m_Children.begin(); }
end()182     iterator end() { return m_Children.end(); }
end()183     const_iterator end() const { return m_Children.end(); }
184 
clear()185     void clear()
186     {
187         std::for_each(this->m_Children.begin(), this->m_Children.end(), ChildDetacher<TChild>());
188         this->m_Children.clear();
189     }
190 
Begin()191     iterator Begin() { return this->begin(); }
Begin()192     const_iterator Begin() const { return this->begin(); }
End()193     iterator End() { return this->end(); }
End()194     const_iterator End() const { return this->end(); }
195 
Clear()196     void Clear() { this->clear(); }
197 
198     //@}
199 
200     //! @brief        子を追加します。
201     //!
202     //! @param[in] child 追加する子です。
203     //!
204     //! @return          追加できたら true が返ります。
205     //!
Attach(TChild * child)206     bool Attach(TChild* child)
207     {
208         if (child->GetParent() != 0)
209         {
210             return false;
211         }
212 
213         bool pushed = m_Children.push_back(child);
214         if (pushed)
215         {
216             child->SetParent(m_Parent);
217         }
218 
219         return pushed;
220     }
221 
222     //! @brief        子を取り外します。
223     //!
224     //! @param[in] child 外す子です。
225     //!
226     //! @return          子を外せたら true が返ります。
227     //!
Detach(TChild * child)228     bool Detach(TChild* child)
229     {
230         bool result = m_Children.erase_find(child);
231         if (result)
232         {
233             child->SetParent(NULL);
234         }
235 
236         return result;
237     }
238 
239     //! @brief        親を設定します。
240     //!
241     //! 親が設定できるのは一度きりです。
242     //! すでに設定されている場合は、 ASSERT となります。
243     //!
244     //! @param[in]    parent 親です。
245     //!
SetParent(TParent * parent)246     void SetParent(TParent* parent)
247     {
248         NW_NULL_ASSERT(parent);
249         //NW_ASSERT(m_Children);
250         NW_ASSERT(m_Parent == NULL);
251         m_Parent = parent;
252     }
253 
254     //! @brief デリータを取得します。
GetDeleter()255     deleter_reference GetDeleter() { return m_Deleter; }
256 
257     //! @brief デリータを取得します。
GetDeleter()258     deleter_const_reference GetDeleter() const { return m_Deleter; }
259 
260 private:
261 
262     TParent* m_Parent;
263     TChildList m_Children;
264     deleter_type m_Deleter;
265 };
266 
267 #define NW_CHILD_DECLARE_PARENT(MParent) \
268 public:\
269     const MParent* GetParent() const { return m_Parent; }\
270     MParent* GetParent() { return m_Parent; }\
271     void SetParent(MParent* parent) { m_Parent = parent; }\
272 private:\
273     MParent* m_Parent
274 
275 } // namespace ut
276 } // namespace nw
277 
278 #endif // NW_UT_CHILDREN_H_
279