]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/lib/iter.qh
Merge branch 'master' into Mario/hagar_notfixed
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / iter.qh
1 #pragma once
2
3 #if 1
4 #define ITER_CONST const
5 #else
6 #define ITER_CONST
7 #endif
8
9 #define FOREACH_ARRAY(arr, start, end, cond, body) \
10         MACRO_BEGIN \
11         { \
12                 for (int _i = start; _i < end; ++_i) \
13                 { \
14                         const noref int i = _i; \
15                         ITER_CONST noref entity it = arr[i]; \
16                         if (cond) { LAMBDA(body) } \
17                 } \
18         } MACRO_END
19
20 #define FOREACH(list, cond, body) FOREACH_LIST(list, enemy, cond, body)
21
22 #define FOREACH_LIST(list, next, cond, body) \
23         MACRO_BEGIN \
24         { \
25                 int _i = 0; \
26                 for (entity _it = list##_first; _it; (_it = _it.next, ++_i)) \
27                 { \
28                         const noref int i = _i; \
29                         ITER_CONST noref entity it = _it; \
30                         if (cond) { LAMBDA(body) } \
31                 } \
32         } MACRO_END
33
34 #define FOREACH_WORD(words, cond, body) \
35         MACRO_BEGIN \
36         { \
37                 string _words = words; \
38                 int _i = 0; \
39                 for (string _it; (_it = car(_words)); (_words = cdr(_words), ++_i)) \
40                 { \
41                         const noref int i = _i; \
42                         const noref string it = _it; \
43                         if (cond) { LAMBDA(body) } \
44                 } \
45         } MACRO_END
46
47 #define STRING_ITERATOR(this, s, i) \
48         string this##_s = s; \
49         int this##_i = i
50
51 #define STRING_ITERATOR_SET(this, s, i) \
52         MACRO_BEGIN { \
53                 this##_s = s; \
54                 this##_i = i; \
55         } MACRO_END
56
57 #define STRING_ITERATOR_GET(this) str2chr(this##_s, this##_i++)
58
59 #define FOREACH_CHAR(s, cond, body) \
60         MACRO_BEGIN \
61         { \
62                 STRING_ITERATOR(iter, s, 0); \
63                 int _it; \
64                 while ((_it = STRING_ITERATOR_GET(iter)) > 0) \
65                 { \
66                         const noref int it = _it; \
67                         if (cond) { LAMBDA(body) } \
68                 } \
69         } MACRO_END
70
71 #if defined(CSQC)
72         entity(.string fld, string match, .entity tofield) _findchainstring_tofield = #402;
73         entity(.entity fld, entity match, .entity tofield) _findchainentity_tofield = #403;
74         entity(.float fld, float match, .entity tofield) _findchainfloat_tofield = #403;
75         entity(.float fld, float match, .entity tofield) _findchainflags_tofield = #450;
76 #elif defined(SVQC)
77         entity(.string fld, string match, .entity tofield) _findchainstring_tofield = #402;
78         entity(.entity fld, entity match, .entity tofield) _findchainentity_tofield = #403;
79         entity(.float fld, float match, .entity tofield) _findchainfloat_tofield = #403;
80         entity(.float fld, float match, .entity tofield) _findchainflags_tofield = #450;
81 #elif defined(MENUQC)
82         entity(.string fld, string match, .entity tofield) _findchainstring_tofield = #26;
83         entity(.entity fld, entity match, .entity tofield) _findchainentity_tofield = #27;
84         entity(.float fld, float match, .entity tofield) _findchainfloat_tofield = #27;
85         entity(.float fld, float match, .entity tofield) _findchainflags_tofield = #88;
86 #endif
87
88 #define ORDERED(F) F##_UNORDERED
89
90 #define FOREACH_ENTITY(cond, body) ORDERED(FOREACH_ENTITY)(cond, body)
91 #define FOREACH_ENTITY_ORDERED(cond, body) \
92         MACRO_BEGIN { \
93                 int _i = 0; \
94                 for (entity _it = NULL; (_it = nextent(_it)); ++_i) \
95                 { \
96                         const noref int i = _i; \
97                         ITER_CONST noref entity it = _it; \
98                         if (cond) { LAMBDA(body) } \
99                 } \
100         } MACRO_END
101 /** marker field, always NULL */
102 .entity _FOREACH_ENTITY_fld;
103
104 .entity _FOREACH_ENTITY_next;
105 noref string _FOREACH_ENTITY_mutex;
106 #define FOREACH_ENTITY_UNORDERED(cond, body) \
107         MACRO_BEGIN { \
108                 if (_FOREACH_ENTITY_mutex) LOG_SEVEREF("Loop mutex held by %s", _FOREACH_ENTITY_mutex); \
109                 _FOREACH_ENTITY_mutex = __FUNC__; \
110                 entity _foundchain_first = _findchainentity_tofield(_FOREACH_ENTITY_fld, NULL, _FOREACH_ENTITY_next); \
111                 FOREACH_LIST(_foundchain, _FOREACH_ENTITY_next, cond, body); \
112                 _FOREACH_ENTITY_mutex = string_null; \
113         } MACRO_END
114
115
116 #ifndef MENUQC
117 entity(vector org, float rad, .entity tofield) _findradius_tofield = #22;
118 #define FOREACH_ENTITY_RADIUS(org, dist, cond, body) FOREACH_ENTITY_RADIUS_UNORDERED(org, dist, cond, body)
119 .entity _FOREACH_ENTITY_RADIUS_next;
120 noref string _FOREACH_ENTITY_RADIUS_mutex;
121 #define FOREACH_ENTITY_RADIUS_UNORDERED(org, dist, cond, body) \
122         MACRO_BEGIN { \
123                 if (_FOREACH_ENTITY_RADIUS_mutex) LOG_SEVEREF("Loop mutex held by %s", _FOREACH_ENTITY_RADIUS_mutex); \
124                 _FOREACH_ENTITY_RADIUS_mutex = __FUNC__; \
125                 entity _foundchain_first = _findradius_tofield(org, dist, _FOREACH_ENTITY_RADIUS_next); \
126                 FOREACH_LIST(_foundchain, _FOREACH_ENTITY_RADIUS_next, cond, body); \
127                 _FOREACH_ENTITY_RADIUS_mutex = string_null; \
128         } MACRO_END
129 #endif
130
131
132 #define FOREACH_ENTITY_CLASS(class, cond, body) ORDERED(FOREACH_ENTITY_CLASS)(class, cond, body)
133 #define FOREACH_ENTITY_CLASS_ORDERED(class, cond, body) FOREACH_ENTITY_ORDERED(it.classname == class && (cond), body)
134 .entity _FOREACH_ENTITY_CLASS_next;
135 noref string _FOREACH_ENTITY_CLASS_mutex;
136 #define FOREACH_ENTITY_CLASS_UNORDERED(class, cond, body) \
137         MACRO_BEGIN { \
138                 if (_FOREACH_ENTITY_CLASS_mutex) LOG_SEVEREF("Loop mutex held by %s", _FOREACH_ENTITY_CLASS_mutex); \
139                 _FOREACH_ENTITY_CLASS_mutex = __FUNC__; \
140                 entity _foundchain_first = _findchainstring_tofield(classname, class, _FOREACH_ENTITY_CLASS_next); \
141                 FOREACH_LIST(_foundchain, _FOREACH_ENTITY_CLASS_next, cond, body); \
142                 _FOREACH_ENTITY_CLASS_mutex = string_null; \
143         } MACRO_END
144
145
146
147 #define FOREACH_ENTITY_FLOAT(fld, match, body) ORDERED(FOREACH_ENTITY_FLOAT)(fld, match, body)
148 #define FOREACH_ENTITY_FLOAT_ORDERED(fld, match, body) FOREACH_ENTITY_ORDERED(it.fld == match, body)
149 .entity _FOREACH_ENTITY_FLOAT_next;
150 noref string _FOREACH_ENTITY_FLOAT_mutex;
151 #define FOREACH_ENTITY_FLOAT_UNORDERED(fld, match, body) \
152         MACRO_BEGIN { \
153                 if (_FOREACH_ENTITY_FLOAT_mutex) LOG_SEVEREF("Loop mutex held by %s", _FOREACH_ENTITY_FLOAT_mutex); \
154                 _FOREACH_ENTITY_FLOAT_mutex = __FUNC__; \
155                 entity _foundchain_first = _findchainfloat_tofield(fld, match, _FOREACH_ENTITY_FLOAT_next); \
156                 FOREACH_LIST(_foundchain, _FOREACH_ENTITY_FLOAT_next, true, body); \
157                 _FOREACH_ENTITY_FLOAT_mutex = string_null; \
158         } MACRO_END
159
160
161
162 #define FOREACH_ENTITY_FLAGS(fld, match, body) ORDERED(FOREACH_ENTITY_FLAGS)(fld, match, body)
163 #define FOREACH_ENTITY_FLAGS_ORDERED(fld, match, body) FOREACH_ENTITY_ORDERED(it.fld & match, body)
164 .entity _FOREACH_ENTITY_FLAGS_next;
165 noref string _FOREACH_ENTITY_FLAGS_mutex;
166 #define FOREACH_ENTITY_FLAGS_UNORDERED(fld, match, body) \
167         MACRO_BEGIN { \
168                 if (_FOREACH_ENTITY_FLAGS_mutex) LOG_SEVEREF("Loop mutex held by %s", _FOREACH_ENTITY_FLAGS_mutex); \
169                 _FOREACH_ENTITY_FLAGS_mutex = __FUNC__; \
170                 entity _foundchain_first = _findchainflags_tofield(fld, match, _FOREACH_ENTITY_FLAGS_next); \
171                 FOREACH_LIST(_foundchain, _FOREACH_ENTITY_FLAGS_next, true, body); \
172                 _FOREACH_ENTITY_FLAGS_mutex = string_null; \
173         } MACRO_END
174
175
176
177 #define FOREACH_ENTITY_ENT(fld, match, body) ORDERED(FOREACH_ENTITY_ENT)(fld, match, body)
178 #define FOREACH_ENTITY_ENT_ORDERED(fld, match, body) FOREACH_ENTITY_ORDERED(it.fld == match, body)
179 .entity _FOREACH_ENTITY_ENT_next;
180 noref string _FOREACH_ENTITY_ENT_mutex;
181 #define FOREACH_ENTITY_ENT_UNORDERED(fld, match, body) \
182         MACRO_BEGIN { \
183                 if (_FOREACH_ENTITY_ENT_mutex) LOG_SEVEREF("Loop mutex held by %s", _FOREACH_ENTITY_ENT_mutex); \
184                 _FOREACH_ENTITY_ENT_mutex = __FUNC__; \
185                 entity _foundchain_first = _findchainentity_tofield(fld, match, _FOREACH_ENTITY_ENT_next); \
186                 FOREACH_LIST(_foundchain, _FOREACH_ENTITY_ENT_next, true, body); \
187                 _FOREACH_ENTITY_ENT_mutex = string_null; \
188         } MACRO_END
189
190
191
192 #define FOREACH_ENTITY_STRING(fld, match, body) ORDERED(FOREACH_ENTITY_STRING)(fld, match, body)
193 #define FOREACH_ENTITY_STRING_ORDERED(fld, match, body) FOREACH_ENTITY_ORDERED(it.fld == match, body)
194 .entity _FOREACH_ENTITY_STRING_next;
195 noref string _FOREACH_ENTITY_STRING_mutex;
196 #define FOREACH_ENTITY_STRING_UNORDERED(fld, match, body) \
197         MACRO_BEGIN { \
198                 if (_FOREACH_ENTITY_STRING_mutex) LOG_SEVEREF("Loop mutex held by %s", _FOREACH_ENTITY_STRING_mutex); \
199                 _FOREACH_ENTITY_STRING_mutex = __FUNC__; \
200                 entity _foundchain_first = _findchainstring_tofield(fld, match, _FOREACH_ENTITY_STRING_next); \
201                 FOREACH_LIST(_foundchain, _FOREACH_ENTITY_STRING_next, true, body); \
202                 _FOREACH_ENTITY_STRING_mutex = string_null; \
203         } MACRO_END