1 //------------------------------------------------------------------------------
2 // emAnything.h
3 //
4 // Copyright (C) 2015-2016 Oliver Hamann.
5 //
6 // Homepage: http://eaglemode.sourceforge.net/
7 //
8 // This program is free software: you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License version 3 as published by the
10 // Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
15 // more details.
16 //
17 // You should have received a copy of the GNU General Public License version 3
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //------------------------------------------------------------------------------
20 
21 #ifndef emAnything_h
22 #define emAnything_h
23 
24 #ifndef emStd1_h
25 #include <emCore/emStd1.h>
26 #endif
27 
28 
29 //==============================================================================
30 //================================= emAnything =================================
31 //==============================================================================
32 
33 class emAnything {
34 
35 public:
36 
37 	// Class for holding any type of value. Copies are implicitly shared.
38 	// The derived template class emCastAnything is used to cast to and from
39 	// emAnything. Examples:
40 	//
41 	//   // Convert an integer to emAnything:
42 	//   emAnything a = emCastAnything<int>(100);
43 	//
44 	//   // Get back that integer:
45 	//   const int * pi = emCastAnything<int>(a);
46 	//   if (pi) {
47 	//     int i = *pi;
48 	//     printf("a = %d\n", i);
49 	//   }
50 	//   else {
51 	//     printf("Error: a is not an int.\n");
52 	//   }
53 	//
54 	//   // Convert an emString to emAnything:
55 	//   emAnything a2 = emCastAnything<emString>(emString("Hello"));
56 	//
57 	//   // Get back that string:
58 	//   const emString * ps = emCastAnything<emString>(a2);
59 	//   if (ps) {
60 	//     printf("a2 = %s\n", ps->Get());
61 	//   }
62 	//   else {
63 	//     printf("Error: a2 is not an emString.\n");
64 	//   }
65 
66 	emAnything();
67 		// Construct invalid.
68 
69 	emAnything(const emAnything & anything);
70 		// Construct a copy.
71 
72 	~emAnything();
73 		// Destruct.
74 
75 	emAnything & operator = (const emAnything & anything);
76 		// Copy.
77 
78 protected:
79 
80 	struct AbstractSharedData {
81 		AbstractSharedData();
82 		virtual ~AbstractSharedData();
83 		unsigned int RefCount;
84 	};
85 
86 	emAnything(AbstractSharedData * data);
87 
88 	AbstractSharedData * Data;
89 };
90 
91 
92 //==============================================================================
93 //=============================== emCastAnything ===============================
94 //==============================================================================
95 
96 template <class VALUE> class emCastAnything : public emAnything {
97 
98 public:
99 
100 	// Helper class for casting emAnything to and from any type.
101 	// Please see the examples in the description of emAnything.
102 
103 	emCastAnything(const VALUE & value);
104 	emCastAnything(const emAnything & anything);
105 
106 	operator const VALUE * () const;
107 
108 private:
109 
110 	struct SharedData : AbstractSharedData {
111 		SharedData(const VALUE & value);
112 		virtual ~SharedData();
113 		VALUE Value;
114 	};
115 };
116 
117 
118 //==============================================================================
119 //============================== Implementations ===============================
120 //==============================================================================
121 
emAnything()122 inline emAnything::emAnything()
123 	: Data(NULL)
124 {
125 }
126 
AbstractSharedData()127 inline emAnything::AbstractSharedData::AbstractSharedData()
128 	: RefCount(1)
129 {
130 }
131 
emAnything(AbstractSharedData * data)132 inline emAnything::emAnything(AbstractSharedData * data)
133 	: Data(data)
134 {
135 }
136 
emCastAnything(const VALUE & value)137 template <class VALUE> inline emCastAnything<VALUE>::emCastAnything(
138 	const VALUE & value
139 ) : emAnything(new SharedData(value))
140 {
141 }
142 
emCastAnything(const emAnything & anything)143 template <class VALUE> inline emCastAnything<VALUE>::emCastAnything(
144 	const emAnything & anything
145 ) : emAnything(anything)
146 {
147 }
148 
SharedData(const VALUE & value)149 template <class VALUE> inline emCastAnything<VALUE>::SharedData::SharedData(
150 	const VALUE & value
151 ) : Value(value)
152 {
153 }
154 
155 template <class VALUE> emCastAnything<VALUE>::operator const VALUE * () const
156 {
157 	if (Data) {
158 		const SharedData * d=
159 			dynamic_cast<const typename emCastAnything<VALUE>::SharedData*>(Data)
160 		;
161 		if (d) return &d->Value;
162 	}
163 	return NULL;
164 }
165 
~SharedData()166 template <class VALUE> emCastAnything<VALUE>::SharedData::~SharedData()
167 {
168 }
169 
170 
171 #endif
172