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