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: 28041 $
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     //!
202     //! @return          追加できたら true が返ります。
203     //!
Attach(TChild * child)204     bool Attach(TChild* child)
205     {
206         if (child->GetParent() != 0)
207         {
208             return false;
209         }
210 
211         bool pushed = m_Children.push_back(child);
212         if (pushed)
213         {
214             child->SetParent(m_Parent);
215         }
216 
217         return pushed;
218     }
219 
220     //! @brief        子を取り外します。
221     //!
222     //! @param[in] child 外す子です。
223     //!
224     //! @return          子を外せたら true が返ります。
225     //!
Detach(TChild * child)226     bool Detach(TChild* child)
227     {
228         bool result = m_Children.erase_find(child);
229         if (result)
230         {
231             child->SetParent(NULL);
232         }
233 
234         return result;
235     }
236 
237     //! @brief        親を設定します。
238     //!
239     //! 親が設定できるのは一度きりです。
240     //! すでに設定されている場合は、 ASSERT となります。
241     //!
242     //! @param[in]    parent 親です。
243     //!
SetParent(TParent * parent)244     void SetParent(TParent* parent)
245     {
246         NW_NULL_ASSERT(parent);
247         //NW_ASSERT(m_Children);
248         NW_ASSERT(m_Parent == NULL);
249         m_Parent = parent;
250     }
251 
252     //! @brief デリータを取得します。
GetDeleter()253     deleter_reference GetDeleter() { return m_Deleter; }
254 
255     //! @brief デリータを取得します。
GetDeleter()256     deleter_const_reference GetDeleter() const { return m_Deleter; }
257 
258 private:
259 
260     TParent* m_Parent;
261     TChildList m_Children;
262     deleter_type m_Deleter;
263 };
264 
265 #define NW_CHILD_DECLARE_PARENT(MParent) \
266 public:\
267     const MParent* GetParent() const { return m_Parent; }\
268     MParent* GetParent() { return m_Parent; }\
269     void SetParent(MParent* parent) { m_Parent = parent; }\
270 private:\
271     MParent* m_Parent
272 
273 } // namespace ut
274 } // namespace nw
275 
276 #endif // NW_UT_CHILDREN_H_
277