1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     ut_Foreach.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_FOREACH_H_
19 #define NW_UT_FOREACH_H_
20 
21 namespace nw
22 {
23 namespace ut
24 {
25 namespace internal
26 {
27 
28 struct static_any_base
29 {
30     operator bool() const
31     {
32         return false;
33     }
34 };
35 
36 template <typename Type>
37 struct static_any : public static_any_base
38 {
static_anystatic_any39     static_any(const Type& item) : m_Item(item) {}
40     mutable Type m_Item;
41 };
42 
43 typedef const static_any_base& static_any_t;
44 
45 
46 template <typename Type>
static_any_cast(static_any_t value)47 NW_INLINE Type& static_any_cast(static_any_t value)
48 {
49     return static_cast<const static_any<Type>&>(value).m_Item;
50 }
51 
52 //----------------------------------------
53 // typeof
54 //----------------------------------------
55 template <typename Type>
56 struct contain_type
57 {
58     typedef Type type;
59 };
60 
61 template <typename Type>
encode_type(Type &)62 NW_INLINE contain_type<Type>* encode_type(Type&)
63 {
64     return 0;
65 }
66 
67 template <typename Type>
encode_type(const Type &)68 NW_INLINE contain_type<const Type>* encode_type(const Type&)
69 {
70     return 0;
71 }
72 
73 #define NW_FOREACH_TYPEOF(COL) \
74     (true ? 0 : nw::ut::internal::encode_type(COL))
75 
76 
77 //----------------------------------------
78 // contain
79 //----------------------------------------
80 template <typename Type>
contain(const Type & col)81 NW_INLINE static_any<Type> contain(const Type& col)
82 {
83     return col;
84 }
85 
86 template <typename Type>
contain(Type & col)87 NW_INLINE static_any<Type*> contain(Type& col)
88 {
89     return &col;
90 }
91 
92 template <typename Type, int Size>
contain(Type (& col)[Size])93 NW_INLINE static_any<Type*> contain(Type (&col)[Size])
94 {
95     return col;
96 }
97 
98 //----------------------------------------
99 // Array
100 //----------------------------------------
101 template <typename Type, int Size>
begin(static_any_t cur,contain_type<Type[Size]> *)102 NW_INLINE static_any<Type*> begin(static_any_t cur, contain_type<Type[Size]>*)
103 {
104     return static_any_cast<Type*>(cur);
105 }
106 
107 template <typename Type, int Size>
end(static_any_t cur,contain_type<Type[Size]> *)108 NW_INLINE static_any<Type*> end(static_any_t cur, contain_type<Type[Size]>*)
109 {
110     return static_any_cast<Type*>(cur) + Size;
111 }
112 
113 template <typename Type, int Size>
next(static_any_t cur,contain_type<Type[Size]> *)114 NW_INLINE void next(static_any_t cur, contain_type<Type[Size]>*)
115 {
116     ++static_any_cast<Type*>(cur);
117 }
118 
119 template <typename Type, int Size>
extract(static_any_t cur,contain_type<Type[Size]> *)120 NW_INLINE Type& extract(static_any_t cur, contain_type<Type[Size]>*)
121 {
122     return *static_any_cast<Type*>(cur);
123 }
124 
125 
126 template <typename Type, int Size>
done(static_any_t cur,static_any_t end,contain_type<Type[Size]> *)127 NW_INLINE bool done(static_any_t cur, static_any_t end, contain_type<Type[Size]>*)
128 {
129     return static_any_cast<Type*>(cur) == static_any_cast<Type*>(end);
130 }
131 
132 //----------------------------------------
133 // Container
134 //----------------------------------------
135 template <typename Type>
begin(static_any_t cur,contain_type<Type> *)136 NW_INLINE static_any<typename Type::iterator> begin(static_any_t cur, contain_type<Type>*)
137 {
138     return static_any_cast<Type*>(cur)->begin();
139 }
140 
141 template <typename Type>
begin(static_any_t cur,contain_type<const Type> *)142 NW_INLINE static_any<typename Type::const_iterator> begin(static_any_t cur, contain_type<const Type>*)
143 {
144     return static_any_cast<Type>(cur).begin();
145 }
146 
147 template <typename Type>
end(static_any_t cur,contain_type<Type> *)148 NW_INLINE static_any<typename Type::iterator> end(static_any_t cur, contain_type<Type>*)
149 {
150     return static_any_cast<Type*>(cur)->end();
151 }
152 
153 template <typename Type>
end(static_any_t cur,contain_type<const Type> *)154 NW_INLINE static_any<typename Type::const_iterator> end(static_any_t cur, contain_type<const Type>*)
155 {
156     return static_any_cast<Type>(cur).end();
157 }
158 
159 template <typename Type>
next(static_any_t cur,contain_type<Type> *)160 NW_INLINE void next(static_any_t cur, contain_type<Type>*)
161 {
162     ++static_any_cast<typename Type::iterator>(cur);
163 }
164 
165 template <typename Type>
extract(static_any_t cur,contain_type<Type> *)166 NW_INLINE typename Type::reference extract(static_any_t cur, contain_type<Type>*)
167 {
168     return *static_any_cast<typename Type::iterator>(cur);
169 }
170 
171 template <typename Type>
done(static_any_t cur,static_any_t end,contain_type<Type> *)172 NW_INLINE bool done(static_any_t cur, static_any_t end, contain_type<Type>*)
173 {
174     typedef typename Type::iterator Iter;
175     return static_any_cast<Iter>(cur) == static_any_cast<Iter>(end);
176 }
177 
178 //----------------------------------------
179 // pair
180 //----------------------------------------
181 template <typename Type>
begin(static_any_t cur,contain_type<std::pair<Type,Type>> *)182 NW_INLINE static_any<Type> begin(static_any_t cur, contain_type<std::pair<Type, Type> >*)
183 {
184     return static_any_cast<std::pair<Type, Type> >(cur).first;
185 }
186 
187 template <typename Type>
end(static_any_t cur,contain_type<std::pair<Type,Type>> *)188 NW_INLINE static_any<Type> end(static_any_t cur, contain_type<std::pair<Type, Type> >*)
189 {
190     return static_any_cast<std::pair<Type, Type> >(cur).second;
191 }
192 
193 template <typename Type>
next(static_any_t cur,contain_type<std::pair<Type,Type>> *)194 NW_INLINE void next(static_any_t cur, contain_type<std::pair<Type, Type> >*)
195 {
196     ++static_any_cast<Type>(cur);
197 }
198 
199 template <typename Type>
extract(static_any_t cur,contain_type<std::pair<Type,Type>> *)200 NW_INLINE typename Type::reference extract(static_any_t cur, contain_type<std::pair<Type, Type> >*)
201 {
202     return *static_any_cast<Type>(cur);
203 }
204 
205 template <typename Type>
done(static_any_t cur,static_any_t end,contain_type<std::pair<Type,Type>> *)206 NW_INLINE bool done(static_any_t cur, static_any_t end, contain_type<std::pair<Type, Type> >*)
207 {
208     return static_any_cast<Type>(cur) == static_any_cast<Type>(end);
209 }
210 
211 //----------------------------------------
212 // pair
213 //----------------------------------------
214 template <typename Type>
begin(static_any_t cur,contain_type<std::pair<Type *,Type * >> *)215 NW_INLINE static_any<Type*> begin(static_any_t cur, contain_type<std::pair<Type*, Type*> >*)
216 {
217     return static_any_cast<std::pair<Type*, Type*> >(cur).first;
218 }
219 
220 template <typename Type>
end(static_any_t cur,contain_type<std::pair<Type *,Type * >> *)221 NW_INLINE static_any<Type*> end(static_any_t cur, contain_type<std::pair<Type*, Type*> >*)
222 {
223     return static_any_cast<std::pair<Type*, Type*> >(cur).second;
224 }
225 
226 template <typename Type>
next(static_any_t cur,contain_type<std::pair<Type *,Type * >> *)227 NW_INLINE void next(static_any_t cur, contain_type<std::pair<Type*, Type*> >*)
228 {
229     ++static_any_cast<Type*>(cur);
230 }
231 
232 template <typename Type>
extract(static_any_t cur,contain_type<std::pair<Type *,Type * >> *)233 NW_INLINE Type& extract(static_any_t cur, contain_type<std::pair<Type*, Type*> >*)
234 {
235     return *static_any_cast<Type*>(cur);
236 }
237 
238 template <typename Type>
done(static_any_t cur,static_any_t end,contain_type<std::pair<Type *,Type * >> *)239 NW_INLINE bool done(static_any_t cur, static_any_t end, contain_type<std::pair<Type*, Type*> >*)
240 {
241     return static_any_cast<Type*>(cur) == static_any_cast<Type*>(end);
242 }
243 
244 } // namespace internal
245 } // namespace ut
246 } // namespace nw
247 
248 #define NW_FOREACH_CONTAIN(COL) \
249     nw::ut::internal::contain(COL)
250 
251 #define NW_FOREACH_BEGIN(COL) \
252     nw::ut::internal::begin(_contain, NW_FOREACH_TYPEOF(COL))
253 
254 #define NW_FOREACH_END(COL) \
255     nw::ut::internal::end(_contain, NW_FOREACH_TYPEOF(COL))
256 
257 #define NW_FOREACH_DONE(COL) \
258     nw::ut::internal::done(_cur, _end, NW_FOREACH_TYPEOF(COL))
259 
260 #define NW_FOREACH_NEXT(COL) \
261     nw::ut::internal::next(_cur, NW_FOREACH_TYPEOF(COL))
262 
263 #define NW_FOREACH_EXTRACT(COL) \
264     nw::ut::internal::extract(_cur, NW_FOREACH_TYPEOF(COL))
265 
266 //! foreach のマクロです。
267 #define NW_FOREACH(VAR, COL) \
268     if       (nw::ut::internal::static_any_t _contain = NW_FOREACH_CONTAIN(COL)) {} \
269     else if  (nw::ut::internal::static_any_t _cur     = NW_FOREACH_BEGIN(COL))   {} \
270     else if  (nw::ut::internal::static_any_t _end     = NW_FOREACH_END(COL))     {} \
271     else for (bool _continue = true;                                                \
272               _continue && !NW_FOREACH_DONE(COL);                                   \
273               _continue ? NW_FOREACH_NEXT(COL) : (void)0)                           \
274              if      ((_continue = false) == true) {}                               \
275              else for (VAR = NW_FOREACH_EXTRACT(COL); !_continue; _continue = true)
276 
277 #endif // NW_UT_FOREACH_H_
278