2 * Copyright (c) 2007-2013, Czirkos Zoltan http://code.google.com/p/gdash/
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #ifndef _GD_REFLECTIVE
18 #define _GD_REFLECTIVE
23 #include "cave/cavetypes.hpp"
26 * A GetterBase class, from which Getter-s for a particular
27 * reflective class derive.
29 * A particular Getter will store a member pointer to a member
30 * of a Reflective class.
34 unsigned const count
; ///< The size of the array pointed by the prop, or 1
36 template <class KLASS
, class MEMBERTYPE
>
37 static std::auto_ptr
<GetterBase
> create_new(MEMBERTYPE
KLASS::*ptr
);
38 template <class KLASS
, class MEMBERTYPE
, unsigned COUNT
>
39 static std::auto_ptr
<GetterBase
> create_new(MEMBERTYPE (KLASS::*ptr
)[COUNT
]);
41 virtual ~GetterBase() {}
44 /** Create a GetterBase, which remembers the size or
45 * a member array, or 1. */
46 explicit GetterBase(unsigned count
) : count(count
) {}
49 // pre-declaration of reflective class for GetForType::get(Reflective&)
53 * A Getter for a given type.
55 * Has a virtual function, which will return the member
56 * of a given reflective object. This will be implemented
57 * by a real Getter, which knows the exact type of the
58 * Reflective object, too.
60 template <class MEMBERTYPE
>
61 class GetterForType
: public GetterBase
{
63 /** Return the data member pointed to by the prop.
64 * @param o The reflective object.
65 * @return The data member, the pointer for which will be stored in the derived object. */
66 virtual MEMBERTYPE
& get(Reflective
& o
) const=0;
68 /// Create a new GetterForType.
69 GetterForType(unsigned count
);
72 template <class MEMBERTYPE
>
73 GetterForType
<MEMBERTYPE
>::GetterForType(unsigned count
)
75 // Does nothing, just passes the count to the base class.
80 * A Getter for a given type of a given class.
82 * Stores a member pointer for the member of the class.
83 * Implements the virtual function of its base class,
86 * The exact type of the Reflective object is not known;
87 * it had to be dropped, as the virtual function is already
88 * declared in the base class GetterForType<MEMBERTYPE>.
89 * In the implemented get() function we downcast it to
90 * its own type, KLASS again. This must be safe; as long
91 * as the function is not given another object - some
92 * other object that is Reflective, but not exactly
93 * of type KLASS. As Getters will be associated to
94 * different KLASSes and their member description
95 * arrays, this is not likely.
97 template <class KLASS
, class MEMBERTYPE
>
98 class Getter
: public GetterForType
<MEMBERTYPE
> {
100 MEMBERTYPE
KLASS::* const ptr
; ///< The pointer to the member of the given object (class)
102 explicit Getter(MEMBERTYPE
KLASS::*ptr
, unsigned count
);
103 virtual MEMBERTYPE
& get(Reflective
& o
) const;
107 * Create a prop, and remember the pointer given.
108 * Also remember the count given - which will be the size of the array (if ptr points to a member array),
109 * or 1 for single members.
111 template <class KLASS
, class MEMBERTYPE
>
112 Getter
<KLASS
, MEMBERTYPE
>::Getter(MEMBERTYPE
KLASS::*ptr
, unsigned count
)
113 : GetterForType
<MEMBERTYPE
>(count
),
118 * The get function a returns with a given member of the reflective object o.
119 * The dynamic cast checks that a correct object is given by the caller
120 * (not another type of reflective object). It is cannot be static,
121 * as the KLASS for which this Getter is instantiated may be a base
122 * class of the object, which is not yet reflective (i.e. reflective
123 * is inherited later in the hierarchy.)
125 template <class KLASS
, class MEMBERTYPE
>
126 MEMBERTYPE
& Getter
<KLASS
, MEMBERTYPE
>::get(Reflective
& o
) const {
127 return dynamic_cast<KLASS
&>(o
).*ptr
;
131 * Create a new Getter for a class of type KLASS,
132 * and its member of type MEMBERTYPE.
133 * This function is provided for convenience to automatically guess
134 * the class type and member type.
135 * The KLASS and MEMBERTYPE are guessed from the member pointer parameter.
136 * @param ptr A pointer to a member pointer (of any type) of a class (of any Reflective type).
137 * @return A pointer to a newly allocated Getter, cast to GetterBase *.
139 template <class KLASS
, class MEMBERTYPE
>
140 std::auto_ptr
<GetterBase
> GetterBase::create_new(MEMBERTYPE
KLASS::*ptr
) {
141 return std::auto_ptr
<GetterBase
>(new Getter
<KLASS
, MEMBERTYPE
>(ptr
, 1));
145 * Create a new Getter for a class of type KLASS,
146 * and its member array of COUNT elements of type MEMBERTYPE.
147 * This function is provided for convenience to automatically guess
148 * the class type and member type.
149 * The KLASS and MEMBERTYPE, also the size of the array are guessed from the member pointer parameter.
150 * @param ptr A pointer to a member pointer (of any type) of a class (of any Reflective type).
151 * @return A pointer to a newly allocated Getter, cast to GetterBase *.
153 template <class KLASS
, class MEMBERTYPE
, unsigned COUNT
>
154 std::auto_ptr
<GetterBase
> GetterBase::create_new(MEMBERTYPE (KLASS::*ptr
)[COUNT
]) {
155 return std::auto_ptr
<GetterBase
>(new Getter
<KLASS
, MEMBERTYPE
[COUNT
]>(ptr
, COUNT
));
159 * Properties which can be used in a description of a reflective class data item.
161 enum ReflectivePropertyFlags
{
164 GD_DONT_SHOW_IN_EDITOR
=1<<2,
165 GD_SHOW_LEVEL_LABEL
=1<<3,
166 GD_COMPATIBILITY_SETTING
=1<<4,
167 GD_BDCFF_RATIO_TO_CAVE_SIZE
=1<<5,
168 GD_BD_PROBABILITY
=1<<6,
172 * A data structure which describes (usually) one data member in a reflective class.
174 struct PropertyDescription
{
176 const char *identifier
;
177 /// Type of data item
179 /// Flags used during saving and loading, and in the editor
181 /// A Getter which can give this data item
183 /// Tooltip for data item, shown in editor.
184 std::auto_ptr
<GetterBase
> prop
;
185 /// Name in the editor, shown to the user
187 /// Minimum and maximum, for integers.
192 * A base class for reflective classes.
194 * A requirement for reflective classes is to be able to
195 * provide an array of PropertyDescriptions, which describe
196 * their data members.
200 virtual PropertyDescription
const *get_description_array() const=0;
201 virtual ~Reflective() {}
202 template <class MEMBERTYPE
> MEMBERTYPE
& get(std::auto_ptr
<GetterBase
> const &prop
);
206 * Read a data member of type MEMBERTYPE from the given
207 * reflective object. The type of the member in question
208 * has to be known by the caller, by explicitly giving the
209 * template parameter.
210 * The dynamic_cast checks if the correct type is given
212 * @param prop The prop which knows the data member
214 template <class MEMBERTYPE
>
215 MEMBERTYPE
& Reflective::get(std::auto_ptr
<GetterBase
> const &prop
) {
216 return dynamic_cast<const GetterForType
<MEMBERTYPE
>&>(*prop
).get(*this);
220 #endif /* GD_REFLECTIVE_H */