]> git.mxchange.org Git - simgear.git/blob - simgear/props/propertyObject.hxx
Fix PropertyObject bug and interface improvements.
[simgear.git] / simgear / props / propertyObject.hxx
1 // Copyright (C) 2010  James Turner - zakalawe@mac.com
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Library General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 //
17
18 #ifndef SG_PROPERTY_OBJECT
19 #define SG_PROPERTY_OBJECT
20
21 #include <simgear/props/props.hxx>
22
23 namespace simgear
24 {
25
26 class PropertyObjectBase
27 {
28 public:
29   static void setDefaultRoot(SGPropertyNode* aRoot);
30   
31   PropertyObjectBase();
32   
33   PropertyObjectBase(const PropertyObjectBase& aOther);
34     
35   PropertyObjectBase(const char* aChild);
36   
37   PropertyObjectBase(SGPropertyNode* aNode, const char* aChild = NULL);
38   
39   SGPropertyNode* node(bool aCreate) const;
40
41   /**
42    * Resolve the property node, or throw an exception if it could not
43    * be resolved.
44    */
45   SGPropertyNode* getOrThrow() const;
46 protected:
47   mutable const char* _path;
48
49   /**
50    * Important - if _path is NULL, this is the actual prop.
51    * If path is non-NULL, this is the parent which path should be resolved
52    * against (or NULL, if _path is absolute). Use node() instead of accessing
53    * this directly, and the above is handled automatically. 
54    */
55   mutable SGPropertyNode* _prop;
56 };
57
58 template <typename T>
59 class PropertyObject : PropertyObjectBase
60 {
61 public:
62   PropertyObject()
63   {}
64   
65   /**
66    * Create from path relative to the default root, and option default value
67    */
68   explicit PropertyObject(const char* aChild) :
69     PropertyObjectBase(aChild)
70   { }
71   
72   /**
73    * Create from a node, with optional relative path
74    */
75   explicit PropertyObject(SGPropertyNode* aNode, const char* aChild = NULL) :
76     PropertyObjectBase(aNode, aChild)
77   {
78   
79   }
80   
81 // copy-constructor
82   PropertyObject(const PropertyObject<T>& aOther) :
83     PropertyObjectBase(aOther)
84   {
85   }
86
87 // create() form creates the property immediately
88   static PropertyObject<T> create(const char* aPath, T aValue)
89   {
90     PropertyObject<T> p(aPath);
91     p = aValue;
92     return p;
93   }
94   
95   static PropertyObject<T> create(SGPropertyNode* aNode, T aValue)
96   {
97     PropertyObject<T> p(aNode);
98     p = aValue;
99     return p;
100   }
101
102   static PropertyObject<T> create(SGPropertyNode* aNode, const char* aChild, T aValue)
103   {
104     PropertyObject<T> p(aNode, aChild);
105     p = aValue;
106     return p;
107   }
108   
109 // conversion operators
110   operator T () const
111   {
112     return getOrThrow()->template getValue<T>();
113   }
114
115   T operator=(const T& aValue)
116   {
117     SGPropertyNode* n = PropertyObjectBase::node(true);
118     if (!n) {
119       std::cout << "no node" << std::endl;
120       return aValue;
121     }
122     
123     n->setValue<T>(aValue);
124     return aValue;
125   }
126
127 #define SG_DEF_ASSIGN_OP(op)\
128   T operator op##=(const T rhs)\
129   {\
130     SGPropertyNode* n = getOrThrow();\
131     T new_val = n->getValue<T>() op rhs;\
132     n->setValue<T>(new_val);\
133     return new_val;\
134   }
135
136   SG_DEF_ASSIGN_OP(+)
137   SG_DEF_ASSIGN_OP(-)
138   SG_DEF_ASSIGN_OP(*)
139   SG_DEF_ASSIGN_OP(/)
140   SG_DEF_ASSIGN_OP(%)
141   SG_DEF_ASSIGN_OP(>>)
142   SG_DEF_ASSIGN_OP(<<)
143   SG_DEF_ASSIGN_OP(&)
144   SG_DEF_ASSIGN_OP(^)
145   SG_DEF_ASSIGN_OP(|)
146
147 #undef SG_DEF_ASSIGN_OP
148
149   SGPropertyNode* node() const
150   {
151     return PropertyObjectBase::node(false);
152   }
153 }; // of template PropertyObject
154
155
156 // specialization for const char* / std::string
157
158 template <>
159 class PropertyObject<std::string> : PropertyObjectBase
160 {
161 public:
162   explicit PropertyObject(const char* aChild) :
163     PropertyObjectBase(aChild)
164   { }
165   
166
167   
168   explicit PropertyObject(SGPropertyNode* aNode, const char* aChild = NULL) :
169     PropertyObjectBase(aNode, aChild)
170   {
171   
172   }
173   
174 // copy-constructor
175   PropertyObject(const PropertyObject<std::string>& aOther) :
176     PropertyObjectBase(aOther)
177   {
178   }
179
180 // create form
181   static PropertyObject<std::string> create(const char* aPath, const std::string& aValue)
182   {
183     PropertyObject<std::string> p(aPath);
184     p = aValue;
185     return p;
186   }
187   
188   static PropertyObject<std::string> create(SGPropertyNode* aNode, const std::string& aValue)
189   {
190     PropertyObject<std::string> p(aNode);
191     p = aValue;
192     return p;
193   }
194
195   static PropertyObject<std::string> create(SGPropertyNode* aNode, const char* aChild, const std::string& aValue)
196   {
197     PropertyObject<std::string> p(aNode, aChild);
198     p = aValue;
199     return p;
200   }
201   
202   
203   operator std::string () const
204   {
205     return getOrThrow()->getStringValue();
206   }
207   
208   const char* operator=(const char* aValue)
209   {
210     SGPropertyNode* n = PropertyObjectBase::node(true);
211     if (!n) {
212       return aValue;
213     }
214     
215     n->setStringValue(aValue);
216     return aValue;
217   }
218   
219   std::string operator=(const std::string& aValue)
220   {
221     SGPropertyNode* n = PropertyObjectBase::node(true);
222     if (!n) {
223       return aValue;
224     }
225     
226     n->setStringValue(aValue);
227     return aValue;
228   }
229   
230   bool operator==(const char* value) const
231   {
232     std::string s(*this);
233     return (s == value);    
234   }
235
236   bool operator==(const std::string& value) const
237   {
238     std::string s(*this);
239     return (s == value);    
240   }
241
242   SGPropertyNode* node() const
243   {
244     return PropertyObjectBase::node(false);
245   }
246 private:
247 };
248
249 } // of namespace simgear
250
251 typedef simgear::PropertyObject<double> SGPropObjDouble;
252 typedef simgear::PropertyObject<bool> SGPropObjBool;
253 typedef simgear::PropertyObject<std::string> SGPropObjString;
254 typedef simgear::PropertyObject<long> SGPropObjInt;
255
256 #endif