20130313
[gdash.git] / src / cave / helper / reflective.hpp
blobcff91a8a1648c0fabf6c6b3ae6577dd7cee02b1c
1 /*
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
20 #include "config.h"
22 #include <memory>
23 #include "cave/cavetypes.hpp"
25 /**
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.
32 class GetterBase {
33 public:
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() {}
43 protected:
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&)
50 class Reflective;
52 /**
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 {
62 public:
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;
67 protected:
68 /// Create a new GetterForType.
69 GetterForType(unsigned count);
72 template <class MEMBERTYPE>
73 GetterForType<MEMBERTYPE>::GetterForType(unsigned count)
74 : GetterBase(count) {
75 // Does nothing, just passes the count to the base class.
79 /**
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,
84 * the GetterForType.
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> {
99 private:
100 MEMBERTYPE KLASS::* const ptr; ///< The pointer to the member of the given object (class)
101 public:
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),
114 ptr(ptr) {
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 {
162 GD_ALWAYS_SAVE=1<<0,
163 GD_DONT_SAVE=1<<1,
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 {
175 /// BDCFF identifier
176 const char *identifier;
177 /// Type of data item
178 GdType type;
179 /// Flags used during saving and loading, and in the editor
180 int flags;
181 /// A Getter which can give this data item
182 const char *name;
183 /// Tooltip for data item, shown in editor.
184 std::auto_ptr<GetterBase> prop;
185 /// Name in the editor, shown to the user
186 const char *tooltip;
187 /// Minimum and maximum, for integers.
188 int min, max;
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.
198 class Reflective {
199 public:
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
211 * by the caller.
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 */