eff65bb54917e4137ef7a0b683386b27e2d776dd
[synfig.git] / synfig-core / src / synfig / value.h
1 /* === S Y N F I G ========================================================= */
2 /*!     \file value.h
3 **      \brief Template Header
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2007, 2008 Chris Moore
10 **
11 **      This package is free software; you can redistribute it and/or
12 **      modify it under the terms of the GNU General Public License as
13 **      published by the Free Software Foundation; either version 2 of
14 **      the License, or (at your option) any later version.
15 **
16 **      This package is distributed in the hope that it will be useful,
17 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 **      General Public License for more details.
20 **      \endlegal
21 */
22 /* ========================================================================= */
23
24 /* === S T A R T =========================================================== */
25
26 #ifndef __SYNFIG_VALUE_H
27 #define __SYNFIG_VALUE_H
28
29 /* === H E A D E R S ======================================================= */
30
31 #include "angle.h"
32 #include "segment.h"
33 #include "string.h"
34 #include <list>
35 #include <vector>
36 #include <ETL/trivial>
37 #include <ETL/handle>
38 #include "general.h"
39 #include "blinepoint.h"
40 #include "exception.h"
41
42 #ifdef USE_HALF_TYPE
43 #include <OpenEXR/half.h>
44 #endif
45
46
47 #include <ETL/ref_count>
48
49 /* === M A C R O S ========================================================= */
50
51 /* === T Y P E D E F S ===================================================== */
52
53 /* === C L A S S E S & S T R U C T S ======================================= */
54
55 namespace synfig {
56
57 class Canvas;
58 class Vector;
59 class Time;
60 class Segment;
61 class Gradient;
62 class BLinePoint;
63 class Color;
64
65 /*!     \class ValueBase
66 **      \todo writeme
67 */
68 class ValueBase
69 {
70         /*
71  --     ** -- T Y P E S -----------------------------------------------------------
72         */
73
74 public:
75
76         //! \writeme
77         enum Type
78         {
79                 TYPE_NIL=0,                     //!< Represents an empty value
80
81                 TYPE_BOOL,
82                 TYPE_INTEGER,
83                 TYPE_ANGLE,                     //!< Angle
84
85                 // All types after this point are larger than 32 bits
86
87                 TYPE_TIME,                      //!< Time
88                 TYPE_REAL,                      //!< Real
89
90                 // All types after this point are larger than 64 bits
91
92                 TYPE_VECTOR,            //!< Vector
93                 TYPE_COLOR,                     //!< Color
94                 TYPE_SEGMENT,           //!< Segment
95                 TYPE_BLINEPOINT,        //!< BLinePoint
96
97                 // All types after this point require construction/destruction
98
99                 TYPE_LIST,                      //!< List
100                 TYPE_CANVAS,            //!< Canvas
101                 TYPE_STRING,            //!< String
102                 TYPE_GRADIENT,          //!< Color Gradient
103
104                 TYPE_END                        //!< Not a valid type, used for sanity checks
105         };
106
107 private:
108
109         typedef std::vector<ValueBase> list_type;
110
111         /*
112  --     ** -- D A T A -------------------------------------------------------------
113         */
114
115 protected:
116
117         Type type;
118         void *data;
119         etl::reference_counter ref_count;
120         bool loop_;
121
122         /*
123  --     ** -- C O N S T R U C T O R S -----------------------------------
124         */
125
126 public:
127
128         //! \writeme
129         ValueBase();
130
131         //! \writeme
132         template <typename T>
133         ValueBase(const T &x, bool loop_=false):
134                 type(TYPE_NIL),data(0),ref_count(0),loop_(loop_)
135                 { set(x); }
136
137         //! \writeme
138         ValueBase(Type x);
139
140         //! \writeme
141         ~ValueBase();
142
143         /*
144  --     ** -- O P E R A T O R S ---------------------------------------------------
145         */
146
147 public:
148
149         //! \writeme
150         template <class T> ValueBase& operator=(const T& x)
151                 { set(x); return *this; }
152
153         //! \writeme
154         ValueBase& operator=(const ValueBase& x);
155
156         //! \writeme
157         bool operator==(const ValueBase& rhs)const;
158
159         //! \writeme
160         bool operator!=(const ValueBase& rhs)const { return !operator==(rhs); }
161
162         //!     Constant index operator for when value is of type TYPE_LIST
163         const ValueBase &operator[](int index)const
164                 { assert(type==TYPE_LIST); assert(index>0); return get_list()[index]; }
165
166         /*
167  --     ** -- M E M B E R   F U N C T I O N S -------------------------------------
168         */
169
170 public:
171
172         //! \writeme
173         void clear();
174
175         //! \writeme
176         bool get_loop()const { return loop_; }
177
178         //! \writeme
179         void set_loop(bool x) { loop_=x; }
180
181         //! \writeme
182         bool empty()const;
183
184         //! \writeme
185         Type get_contained_type()const;
186
187         //! Returns true if the contained value is defined and valid.
188         bool is_valid()const;
189
190         //!     Returns a string containing the name of the type
191         String type_name()const { return type_name(type); }
192
193         //! Returns the type of the contained value
194         const Type & get_type()const { return type; }
195
196         //! Checks the type of the parameter against itself. Returns true if they are of the same type.
197         template <class T> bool
198         same_type_as(const T &x)const
199         {
200                 const Type testtype(get_type(x));
201
202                 return same_type_as(type, testtype);
203         }
204
205         bool same_type_as(const Type testtype)const
206         {
207                 return same_type_as(type, testtype);
208         }
209
210         //! Compares two types.  Returns true if they are the same type.
211         static bool same_type_as(const Type type1, const Type type2)
212         {
213                 if (type1 == type2) return true;
214                 if ((type1 == TYPE_REAL || type1 == TYPE_TIME) &&
215                         (type2 == TYPE_REAL || type2 == TYPE_TIME))
216                         return true;
217                 return false;
218         }
219
220
221         // === GET MEMBERS ========================================================
222         template <typename T>
223         const T &get(const T& x __attribute__ ((unused)))const
224         {
225                 assert(is_valid() && same_type_as(x));
226                 return *static_cast<const T*>(data);
227         }
228         float get(const float &)const { return get(Real()); }
229         etl::loose_handle<Canvas> get(const etl::handle<Canvas>&)const
230                 { return get(etl::loose_handle<Canvas>()); }
231         etl::loose_handle<Canvas> get(Canvas*)const
232                 { return get(etl::loose_handle<Canvas>()); }
233         const char* get(const char*)const;
234         const list_type& get_list()const { return get(list_type()); }
235
236 #ifdef _DEBUG
237         String get_string() const;
238 #endif  // _DEBUG
239         // ========================================================================
240
241
242
243         // === PUT MEMBERS ========================================================
244         template <typename T>
245         void put(T* x)const
246         {
247                 assert(same_type_as(*x));
248                 *x=*static_cast<const T*>(data);
249         }
250         void put(float* x)const { *x=get(Real()); }
251         void put(char** x)const;
252         // ========================================================================
253
254
255
256         // === SET MEMBERS ========================================================
257         template <typename T> void set(const T& x) { _set(x); }
258         void set(const float &x) { _set(Real(x)); }
259         void set(const list_type &x);
260         void set(const char* x);
261         void set(char* x);
262         void set(Canvas*x);
263         void set(etl::loose_handle<Canvas> x);
264         void set(etl::handle<Canvas> x);
265         template <class T> void set(const std::vector<T> &x)
266                 { _set(list_type(x.begin(),x.end())); }
267         template <class T> void set(const std::list<T> &x)
268                 { _set(list_type(x.begin(),x.end())); }
269         // ========================================================================
270
271
272         /*
273  --     ** -- S T A T I C   F U N C T I O N S -------------------------------------
274         */
275
276 public:
277
278         //!     Returns a string containing the name of the given Type
279         static String type_name(Type id);
280
281         //!     Returns a string containing the translated name of the given Type
282         static String type_local_name(Type id);
283
284         //!     Returns a the corresponding Type of the described type
285         static Type ident_type(const String &str);
286
287
288         // === GET TYPE MEMBERS ===================================================
289         static Type get_type(bool) { return TYPE_BOOL; }
290         static Type get_type(int) { return TYPE_INTEGER; }
291         static Type get_type(const Time&) { return TYPE_TIME; }
292         static Type get_type(const Real&) { return TYPE_REAL; }
293         static Type get_type(const float&) { return TYPE_REAL; }
294         static Type get_type(const Vector&) { return TYPE_VECTOR; }
295         static Type get_type(const Color&) { return TYPE_COLOR; }
296         static Type get_type(const Segment&) { return TYPE_SEGMENT; }
297         static Type get_type(const BLinePoint&) { return TYPE_BLINEPOINT; }
298         static Type get_type(const String&) { return TYPE_STRING; }
299         static Type get_type(const Gradient&) { return TYPE_GRADIENT; }
300         static Type get_type(Canvas*) { return TYPE_CANVAS; }
301         static Type get_type(const etl::handle<Canvas>&)
302                 { return TYPE_CANVAS; }
303         static Type get_type(const etl::loose_handle<Canvas>&)
304                 { return TYPE_CANVAS; }
305         static Type get_type(const list_type&) { return TYPE_LIST; }
306         template <class T> static Type get_type(const std::vector<T> &/*x*/)
307                 { return TYPE_LIST; }
308         template <class T> static Type get_type(const std::list<T> &/*x*/)
309                 { return TYPE_LIST; }
310         // ========================================================================
311
312
313         /*
314  --     ** -- C A S T   O P E R A T O R S -----------------------------------------
315         */
316
317 public:
318
319         operator const list_type&()const { return get_list(); }
320         //operator const Color&()const { return get(Color()); }
321         operator const Real&()const { return get(Real()); }
322         //operator const Time&()const { return get(Time()); }
323
324         operator const Vector&()const {  return get(Vector()); }
325         operator const BLinePoint&()const {  return get(BLinePoint()); }
326         //operator const int&()const {  return get(int()); }
327         //operator const String&()const {  return get(String()); }
328         //operator const char *()const {  return get(String()).c_str(); }
329         operator const Segment&()const { return get(Segment()); }
330
331
332         /*
333  --     ** -- O T H E R -----------------------------------------------------------
334         */
335
336 public:
337
338 #ifdef USE_HALF_TYPE
339         half get(const half &)const { return get(Real()); }
340         void put(half*x)const { *x=get(Real()); }
341         void set(const half &x) { _set(Real(x)); }
342         static Type get_type(const half&) { return TYPE_REAL; }
343         operator half()const { return get(Real()); }
344 #endif
345
346         operator const Angle&()const { return get(Angle()); }
347         static Type get_type(const Angle&) { return TYPE_ANGLE; }
348
349         template <class T>
350         operator std::list<T>()const
351         {
352                 assert(type==TYPE_LIST);
353                 std::list<T> ret(get_list().begin(),get_list().end());
354                 return ret;
355         }
356         template <class T>
357         operator std::vector<T>()const
358         {
359                 assert(type==TYPE_LIST);
360                 std::vector<T> ret(get_list().begin(),get_list().end());
361                 return ret;
362         }
363
364
365 private:
366
367         template <typename T> void
368         _set(const T& x)
369         {
370                 const Type newtype(get_type(x));
371
372                 assert(newtype!=TYPE_NIL);
373
374                 if(newtype==type)
375                 {
376                         if(ref_count.unique())
377                         {
378                                 *reinterpret_cast<T*>(data)=x;
379                                 return;
380                         }
381                 }
382
383                 clear();
384
385                 type=newtype;
386                 ref_count.reset();
387                 data=new T(x);
388         }
389 }; // END of class ValueBase
390
391
392 /*!     \class Value
393 **      \todo writeme
394 */
395 template <class T>
396 class Value : public ValueBase
397 {
398 public:
399         Value(const T &x):ValueBase(x)
400         {
401         }
402
403         Value(const ValueBase &x):ValueBase(x)
404         {
405                 if(!x.same_type_as(T()))
406                         throw Exception::BadType("Value<T>(ValueBase): Type Mismatch");
407         }
408
409         Value()
410         {
411         }
412
413         T get()const { return ValueBase::get(T()); }
414
415         void put(T* x)const     { ValueBase::put(x); }
416
417         void set(const T& x) { ValueBase::operator=(x); }
418
419         Value<T>& operator=(const T& x) { set(x); return *this; }
420
421         Value<T>& operator=(const Value<T>& x) { return ValueBase::operator=(x); }
422
423         Value<T>& operator=(const ValueBase& x)
424         {
425                 if(!x.same_type_as(T()))
426                         throw Exception::BadType("Value<T>(ValueBase): Type Mismatch");
427                 return ValueBase::operator=(x);
428         }
429
430 }; // END of class Value
431
432 /*
433 template <>
434 class Value< std::list<CT> > : public ValueBase
435 {
436 public:
437         Value(const T &x):ValueBase(x)
438         {
439         }
440         Value(const ValueBase &x):ValueBase(x)
441         {
442                 if(!x.same_type_as(T()))
443                         throw Exception::BadType("Value<T>(ValueBase): Type Mismatch");
444         }
445         Value()
446         {
447         }
448
449         T get()const { return ValueBase::get(T()); }
450
451         void put(T* x)const     { ValueBase::put(x); }
452
453         void set(const T& x) { ValueBase::operator=(x); }
454
455         Value<T>& operator=(const T& x) { set(x); return *this; }
456
457         Value<T>& operator=(const Value<T>& x) { return ValueBase::operator=(x); }
458
459         Value<T>& operator=(const ValueBase& x)
460         {
461                 if(!x.same_type_as(T()))
462                         throw Exception::BadType("Value<T>(ValueBase): Type Mismatch");
463                 return ValueBase::operator=(x);
464         }
465
466 }; // END of class Value
467 */
468
469 }; // END of namespace synfig
470
471 /* === E N D =============================================================== */
472
473 #endif