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