Sun, 02 Feb 2014 17:06:39 +0200
- reformatting
88 | 1 | /* |
2 | Copyright 2012-2014 Santeri Piippo | |
3 | All rights reserved. | |
4 | ||
5 | Redistribution and use in source and binary forms, with or without | |
6 | modification, are permitted provided that the following conditions | |
7 | are met: | |
8 | ||
9 | 1. Redistributions of source code must retain the above copyright | |
10 | notice, this list of conditions and the following disclaimer. | |
11 | 2. Redistributions in binary form must reproduce the above copyright | |
12 | notice, this list of conditions and the following disclaimer in the | |
13 | documentation and/or other materials provided with the distribution. | |
14 | 3. The name of the author may not be used to endorse or promote products | |
15 | derived from this software without specific prior written permission. | |
16 | ||
17 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
18 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
20 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
22 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
24 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | |
28 | ||
29 | #ifndef BOTC_PROPERTY_H | |
30 | #define BOTC_PROPERTY_H | |
31 | ||
32 | // ============================================================================= | |
33 | // | |
34 | // Identifier names | |
35 | // | |
36 | #define PROPERTY_SET_ACCESSOR(NAME) Set##NAME | |
37 | #define PROPERTY_GET_ACCESSOR(NAME) Get##NAME | |
38 | #define PROPERTY_IS_ACCESSOR(NAME) Is##NAME // for bool types | |
39 | #define PROPERTY_MEMBER_NAME(NAME) m##NAME | |
40 | ||
41 | // Names of operations | |
42 | #define PROPERTY_APPEND_OPERATION(NAME) AppendTo##NAME | |
43 | #define PROPERTY_PREPEND_OPERATION(NAME) PrependTo##NAME | |
44 | #define PROPERTY_REPLACE_OPERATION(NAME) ReplaceIn##NAME | |
45 | #define PROPERTY_INCREASE_OPERATION(NAME) Increase##NAME | |
46 | #define PROPERTY_DECREASE_OPERATION(NAME) Decrease##NAME | |
47 | #define PROPERTY_TOGGLE_OPERATION(NAME) Toggle##NAME | |
48 | #define PROPERTY_PUSH_OPERATION(NAME) PushTo##NAME | |
49 | #define PROPERTY_REMOVE_OPERATION(NAME) RemoveFrom##NAME | |
50 | #define PROPERTY_CLEAR_OPERATION(NAME) Clear##NAME | |
51 | #define PROPERTY_COUNT_OPERATION(NAME) Count##NAME | |
52 | ||
53 | // Operation definitions | |
54 | // These are the methods of the list type that are called in the operations. | |
55 | #define PROPERTY_APPEND_METHOD_NAME Append // String::Append | |
56 | #define PROPERTY_PREPEND_METHOD_NAME Prepend // String::Prepend | |
57 | #define PROPERTY_REPLACE_METHOD_NAME Replace // String::Replace | |
58 | #define PROPERTY_PUSH_METHOD_NAME Append // List<T>::Append | |
59 | #define PROPERTY_REMOVE_METHOD_NAME Remove // List<T>::Remove | |
60 | #define PROPERTY_CLEAR_METHOD_NAME Clear // List<T>::Clear | |
61 | ||
62 | // ============================================================================= | |
63 | // | |
64 | // Main PROPERTY macro | |
65 | // | |
66 | #define PROPERTY(ACCESS, TYPE, NAME, OPS, WRITETYPE) \ | |
67 | private: \ | |
68 | TYPE PROPERTY_MEMBER_NAME(NAME); \ | |
69 | \ | |
70 | public: \ | |
71 | inline TYPE const& PROPERTY_GET_READ_METHOD (NAME, OPS) const \ | |
72 | { \ | |
73 | return PROPERTY_MEMBER_NAME(NAME); \ | |
74 | } \ | |
75 | \ | |
76 | ACCESS: \ | |
77 | PROPERTY_MAKE_WRITE (TYPE, NAME, WRITETYPE) \ | |
78 | PROPERTY_DEFINE_OPERATIONS (TYPE, NAME, OPS) | |
79 | ||
80 | // ============================================================================= | |
81 | // | |
82 | // PROPERTY_GET_READ_METHOD | |
83 | // | |
84 | // This macro uses the OPS argument to construct the name of the actual | |
85 | // macro which returns the name of the get accessor. This is so that the | |
86 | // bool properties get is<NAME>() accessors while non-bools get get<NAME>() | |
87 | // | |
88 | #define PROPERTY_GET_READ_METHOD(NAME, OPS) \ | |
89 | PROPERTY_GET_READ_METHOD_##OPS (NAME) | |
90 | ||
91 | #define PROPERTY_GET_READ_METHOD_BOOL_OPS(NAME) PROPERTY_IS_ACCESSOR (NAME)() | |
92 | #define PROPERTY_GET_READ_METHOD_NO_OPS(NAME) PROPERTY_GET_ACCESSOR (NAME)() | |
93 | #define PROPERTY_GET_READ_METHOD_STR_OPS(NAME) PROPERTY_GET_ACCESSOR (NAME)() | |
94 | #define PROPERTY_GET_READ_METHOD_NUM_OPS(NAME) PROPERTY_GET_ACCESSOR (NAME)() | |
95 | #define PROPERTY_GET_READ_METHOD_LIST_OPS(NAME) PROPERTY_GET_ACCESSOR (NAME)() | |
96 | ||
97 | // ============================================================================= | |
98 | // | |
99 | // PROPERTY_MAKE_WRITE | |
100 | // | |
101 | // This macro uses the WRITETYPE argument to construct the set accessor of the | |
102 | // property. If WRITETYPE is STOCK_WRITE, an inline method is defined to just | |
103 | // set the new value of the property. If WRITETYPE is CUSTOM_WRITE, the accessor | |
104 | // is merely declared and is left for the user to define. | |
105 | // | |
106 | #define PROPERTY_MAKE_WRITE(TYPE, NAME, WRITETYPE) \ | |
107 | PROPERTY_MAKE_WRITE_##WRITETYPE (TYPE, NAME) | |
108 | ||
109 | #define PROPERTY_MAKE_WRITE_STOCK_WRITE(TYPE, NAME) \ | |
110 | inline void PROPERTY_SET_ACCESSOR(NAME) (TYPE const& a) \ | |
111 | { \ | |
112 | PROPERTY_MEMBER_NAME(NAME) = a; \ | |
113 | } | |
114 | ||
115 | #define PROPERTY_MAKE_WRITE_CUSTOM_WRITE(TYPE, NAME) \ | |
116 | void PROPERTY_SET_ACCESSOR(NAME) (TYPE const& NAME); \ | |
117 | ||
118 | // ============================================================================= | |
119 | // | |
120 | // PROPERTY_DEFINE_OPERATIONS | |
121 | // | |
122 | // This macro may expand into methods defining additional operations for the | |
123 | // method. | |
124 | ||
125 | #define PROPERTY_DEFINE_OPERATIONS(TYPE, NAME, OPS) \ | |
126 | DEFINE_PROPERTY_##OPS (TYPE, NAME) | |
127 | ||
128 | // ============================================================================= | |
129 | // | |
130 | // DEFINE_PROPERTY_NO_OPS | |
131 | // | |
132 | // Obviously NO_OPS expands into no operations. | |
133 | // | |
134 | #define DEFINE_PROPERTY_NO_OPS(TYPE, NAME) | |
135 | ||
136 | // ============================================================================= | |
137 | // | |
138 | // DEFINE_PROPERTY_STR_OPS | |
139 | // | |
140 | #define DEFINE_PROPERTY_STR_OPS(TYPE, NAME) \ | |
141 | void PROPERTY_APPEND_OPERATION(NAME) (const TYPE& a) \ | |
142 | { \ | |
143 | TYPE tmp (PROPERTY_MEMBER_NAME(NAME)); \ | |
144 | tmp.PROPERTY_APPEND_METHOD_NAME (a); \ | |
145 | PROPERTY_SET_ACCESSOR(NAME) (tmp); \ | |
146 | } \ | |
147 | \ | |
148 | void PROPERTY_PREPEND_OPERATION(NAME) (const TYPE& a) \ | |
149 | { \ | |
150 | TYPE tmp (PROPERTY_MEMBER_NAME(NAME)); \ | |
151 | tmp.PROPERTY_PREPEND_METHOD_NAME (a); \ | |
152 | PROPERTY_SET_ACCESSOR(NAME) (tmp); \ | |
153 | } \ | |
154 | \ | |
155 | void PROPERTY_REPLACE_OPERATION(NAME) (const TYPE& a, const TYPE& b) \ | |
156 | { \ | |
157 | TYPE tmp (PROPERTY_MEMBER_NAME(NAME)); \ | |
158 | tmp.PROPERTY_REPLACE_METHOD_NAME (a, b); \ | |
159 | PROPERTY_SET_ACCESSOR(NAME) (tmp); \ | |
160 | } | |
161 | ||
162 | // ============================================================================= | |
163 | // | |
164 | // DEFINE_PROPERTY_NUM_OPS | |
165 | // | |
166 | #define DEFINE_PROPERTY_NUM_OPS(TYPE, NAME) \ | |
167 | inline void PROPERTY_INCREASE_OPERATION(NAME) (TYPE a = 1) \ | |
168 | { \ | |
169 | PROPERTY_SET_ACCESSOR(NAME) (PROPERTY_MEMBER_NAME(NAME) + a); \ | |
170 | } \ | |
171 | \ | |
172 | inline void PROPERTY_DECREASE_OPERATION(NAME) (TYPE a = 1) \ | |
173 | { \ | |
174 | PROPERTY_SET_ACCESSOR(NAME) (PROPERTY_MEMBER_NAME(NAME) - a); \ | |
175 | } | |
176 | ||
177 | // ============================================================================= | |
178 | // | |
179 | // DEFINE_PROPERTY_BOOL_OPS | |
180 | // | |
181 | #define DEFINE_PROPERTY_BOOL_OPS(TYPE, NAME) \ | |
182 | inline void PROPERTY_TOGGLE_OPERATION(NAME)() \ | |
183 | { \ | |
184 | PROPERTY_SET_ACCESSOR(NAME) (!PROPERTY_MEMBER_NAME(NAME)); \ | |
185 | } | |
186 | ||
187 | // ============================================================================= | |
188 | // | |
189 | // DEFINE_PROPERTY_LIST_OPS | |
190 | // | |
191 | #define DEFINE_PROPERTY_LIST_OPS(TYPE, NAME) \ | |
192 | void PROPERTY_PUSH_OPERATION(NAME) (const TYPE::ValueType& a) \ | |
193 | { \ | |
194 | PROPERTY_MEMBER_NAME(NAME).PROPERTY_PUSH_METHOD_NAME (a); \ | |
195 | } \ | |
196 | \ | |
197 | void PROPERTY_REMOVE_OPERATION(NAME) (const TYPE::ValueType& a) \ | |
198 | { \ | |
199 | PROPERTY_MEMBER_NAME(NAME).PROPERTY_REMOVE_METHOD_NAME (a); \ | |
200 | } \ | |
201 | \ | |
202 | inline void PROPERTY_CLEAR_OPERATION(NAME)() \ | |
203 | { \ | |
204 | PROPERTY_MEMBER_NAME(NAME).PROPERTY_CLEAR_METHOD_NAME(); \ | |
205 | } \ | |
206 | \ | |
207 | public: \ | |
208 | inline int PROPERTY_COUNT_OPERATION(NAME)() const \ | |
209 | { \ | |
210 | return PROPERTY_GET_ACCESSOR (NAME)().Size(); \ | |
211 | } | |
212 | ||
213 | #endif // BOTC_PROPERTY_H |