Photon microGUI widgets library 0.6.0
tag_property.hpp
1#ifndef TAG_PROPERTY_H
2#define TAG_PROPERTY_H
3
4#include <cstddef>
5#include <map>
6#include <set>
7
8namespace PhWidgets
9{
10 namespace
11 {
12 namespace type_traits
13 {
14 template<bool>
15 struct void_enable_if { typedef void type; };
16
17 template<>
18 struct void_enable_if<false> { };
19
20 template<class T>
21 struct remove_cv { typedef T type; };
22
23 template<class T>
24 struct remove_cv<const T> { typedef typename remove_cv<T>::type type; };
25
26 template<class T>
27 struct remove_cv<volatile T> { typedef typename remove_cv<T>::type type; };
28
29 template<class, class>
30 struct is_same
31 { static const bool value = false; };
32
33 template<class T>
34 struct is_same<T, T>
35 { static const bool value = true; };
36
37 typedef char yes_type;
38 struct no_type {char dummy[8];};
39
40 template<class ObjectT, int>
41 struct sfinae {};
42
43 template<class ObjectT>
44 yes_type has_getter_tester(sfinae<ObjectT, sizeof(&ObjectT::get)>*);
45 template<class ObjectT>
46 no_type has_getter_tester(...);
47
48 template<class T>
49 struct has_getter
50 {
51 typedef typename remove_cv<T>::type type;
52 static const bool value = sizeof(has_getter_tester<type>(0)) == sizeof(yes_type);
53 };
54 }
55 }
56
57 template<
58 class ObjectT,
59 const void*(ObjectT::*Getter)()const,
60 void(ObjectT::*Setter)(const void*, std::size_t)
61 >
62 class tag_property
63 {
64 template<unsigned N, bool = true> struct priority_tag : priority_tag < N - 1 > {};
65 template<bool dummy> struct priority_tag<0, dummy> {};
66
67 public:
68 typedef const void* value_type;
69
70 tag_property(ObjectT *obj) :
71 _obj(obj)
72 { }
73
74 inline
75 void set(value_type value, std::size_t size)
76 {
77 if(value)
78 set_ptr(value, size);
79 else
80 set_ptr(value, 0);
81 }
82
83 template<class T, std::size_t count>
84 inline
85 void set(const T(&value)[count])
86 {
87 set_ptr(value, count * sizeof(T));
88 }
89
90 template<class T>
91 inline
92 void set(T &value)
93 {
94 set_value(value, priority_tag<2>());
95 }
96
97 inline
98 value_type get() const
99 {
100 return get_ptr( value_type() );
101 }
102
103 template<class T>
104 inline
105 const T* get() const
106 {
107 typedef const T* type;
108 return get_ptr( type() );
109 }
110
111 template<class T>
112 inline
113 operator const T*() const { return get<T>(); }
114
115 template<class T, std::size_t count>
116 inline
117 tag_property &operator=(const T(&value)[count]) { set(value); return *this; }
118
119 template<class T>
120 inline
121 tag_property &operator=(const T &value) { set(value); return *this; }
122
123 inline
124 value_type operator()(void) const { return get(); }
125
126 inline
127 void operator()(value_type value, std::size_t size) { set(value, size); }
128
129 template<class T, std::size_t count>
130 inline
131 void operator()(const T(&value)[count]) { set(value); }
132
133 template<class T>
134 inline
135 void operator()(const T &value) { set(value); }
136
137 template<
138 class OtherObjectT,
139 const void*(OtherObjectT::*OtherGetter)()const,
140 void(OtherObjectT::*OtherSetter)(const void*, std::size_t)
141 >
142 inline
143 bool operator==(const tag_property<OtherObjectT, OtherGetter, OtherSetter> &other)
144 {
145 value_type tmp = other.get();
146 return (get() == tmp);
147 }
148
149 template<
150 class OtherObjectT,
151 const void*(OtherObjectT::*OtherGetter)()const,
152 void(OtherObjectT::*OtherSetter)(const void*, std::size_t)
153 >
154 inline
155 bool operator!=(const tag_property<OtherObjectT, OtherGetter, OtherSetter> &other)
156 {
157 value_type tmp = other.get();
158 return (get() != tmp);
159 }
160
161 private:
162 ObjectT *_obj;
163
164 tag_property(const tag_property &);
165
166 template<
167 class OtherObjectT,
168 class OtherValueT,
169 OtherValueT (OtherObjectT::*OtherGetter)() const,
170 template <
171 class,
172 class,
173 OtherValueT (OtherObjectT::*)() const
174 > class T
175 > // ro cpp property
176 inline
177 void set_value(const T<OtherObjectT, OtherValueT, OtherGetter> &value, priority_tag<3>)
178 {
179 const OtherValueT tmp = value;
180 set_ptr(&tmp, sizeof(OtherValueT), priority_tag<3>());
181 }
182
183 template<
184 class OtherObjectT,
185 class OtherValueT,
186 OtherValueT (OtherObjectT::*OtherGetter)() const,
187 void (OtherObjectT::*OtherSetter)(OtherValueT),
188 template <
189 class,
190 class,
191 OtherValueT (OtherObjectT::*)() const,
192 void (OtherObjectT::*)(OtherValueT)
193 > class T
194 > // rw cpp property
195 inline
196 void set_value(const T<OtherObjectT, OtherValueT, OtherGetter, OtherSetter> &value, priority_tag<2>)
197 {
198 const OtherValueT tmp = value;
199 set_ptr(&tmp, sizeof(OtherValueT), priority_tag<3>());
200 }
201
202 template<class T>
203 inline
204 void set_value_from_get(T value)
205 {
206 set_ptr(&value, sizeof(T), priority_tag<3>());
207 }
208
209 template<class T>
210 inline
211 typename type_traits::void_enable_if<
212 type_traits::has_getter<T>::value
213 >::type set_value(T &value, priority_tag<1>)
214 {
215 set_value_from_get(value.get());
216 }
217
218 template<class T>
219 inline
220 void set_value(T value, priority_tag<0>)
221 {
222 set_ptr(&value, sizeof(T), priority_tag<3>());
223 }
224
225
226 inline
227 void set_ptr(value_type value, std::size_t size, priority_tag<0>)
228 {
229 (_obj->*Setter)(value, size);
230 }
231
232 inline
233 value_type get_ptr(value_type) const
234 {
235 return (_obj->*Getter)();
236 }
237
238 // 'remember' types passed:
239 #if !defined(NDEBUG) || defined(_DEBUG) || defined(DEBUG)
240 #define PH_WIDGETS_DEBUG_BUILD
241 #endif
242
243 #ifdef PH_WIDGETS_DEBUG_BUILD
244 template<class>
245 static void type_id_func() {}
246
247 typedef std::map<value_type, std::set<void (*)()> > map_type;
248
249 static map_type &tag_pointers()
250 {
251 static map_type ptr_map_;
252 return ptr_map_;
253 }
254 #endif
255
256 template<class T>
257 inline
258 const
259 typename type_traits::remove_cv<T>
260 ::type get_ptr(T) const
261 {
262 typedef const typename type_traits::remove_cv<T>::type type;
263
264 value_type value = (_obj->*Getter)();
265 type result = dynamic_cast<type>(value);
266
267 #ifdef PH_WIDGETS_DEBUG_BUILD
268 {
269 static map_type &ptr_map = tag_pointers();
270
271 map_type::iterator it = ptr_map.find(value);
272 if(ptr_map.end() != it)
273 {
274 if(!value)
275 ptr_map.erase(it);
276 else
277 {
278 if( it->second.find(&type_id_func<type>) == it->second.end() )
279 {
280 #ifdef NULL
281 return NULL;
282 #else
283 return 0;
284 #endif
285 }
286 }
287 }
288 }
289 #endif
290
291 return result;
292 }
293
294 template<class T>
295 inline
296 typename type_traits::void_enable_if<
297 false == type_traits::is_same<const T*, const void*>::value
298 >::type set_ptr(const T *value, std::size_t size, priority_tag<1>)
299 {
300 typedef const typename type_traits::remove_cv<T>::type type;
301
302 (_obj->*Setter)(value, size);
303
304 #ifdef PH_WIDGETS_DEBUG_BUILD
305 {
306 value = get_ptr(value);
307
308 static map_type &ptr_map = tag_pointers();
309
310 map_type::iterator it = ptr_map.find(value);
311
312 if(ptr_map.end() != it)
313 {
314 if(!value)
315 ptr_map.erase(it);
316 else
317 it->second.insert(&type_id_func<type>);
318 }
319 else
320 {
321 if(value)
322 {
323 map_type::mapped_type second;
324 second.insert(&type_id_func<type>);
325 ptr_map.insert(std::make_pair(value, second));
326 }
327 }
328 }
329 #endif
330 }
331 };
332
333 template<
334 class ObjectT,
335 const void*(ObjectT::*Getter)()const,
336 void(ObjectT::*Setter)(const void*, std::size_t),
337 class T
338 >
339 inline
340 bool operator==(const tag_property<ObjectT, Getter, Setter> &lhs, const T &rhs) { const T *tmp = lhs; return (&rhs == tmp); }
341
342 template<
343 class ObjectT,
344 const void*(ObjectT::*Getter)()const,
345 void(ObjectT::*Setter)(const void*, std::size_t),
346 class T
347 >
348 inline
349 bool operator==(const T &lhs, const tag_property<ObjectT, Getter, Setter> &rhs) { const T *tmp = rhs; return (&lhs == tmp); }
350
351
352 template<
353 class ObjectT,
354 const void*(ObjectT::*Getter)()const,
355 void(ObjectT::*Setter)(const void*, std::size_t),
356 class T
357 >
358 inline
359 bool operator!=(const tag_property<ObjectT, Getter, Setter> &lhs, const T &rhs) { const T *tmp = lhs; return (&rhs != tmp); }
360
361 template<
362 class ObjectT,
363 const void*(ObjectT::*Getter)()const,
364 void(ObjectT::*Setter)(const void*, std::size_t),
365 class T
366 >
367 inline
368 bool operator!=(const T &lhs, const tag_property<ObjectT, Getter, Setter> &rhs) { const T *tmp = rhs; return (&lhs != tmp); }
369}
370
371#ifdef PH_WIDGETS_DEBUG_BUILD
372#undef PH_WIDGETS_DEBUG_BUILD
373#endif
374
375
376#endif // TAG_PROPERTY_H
The main namespace for all widgets.
Definition: Basic.h:11