Suuports clang compiler
[anna.git] / source / core / util / Variable.cpp
1 // ANNA - Anna is Not Nothingness Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // http://redmine.teslayout.com/projects/anna-suite
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //     * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //     * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 //     *  Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 #include <anna/core/functions.hpp>
38 #include <anna/core/util/Variable.hpp>
39
40 using namespace std;
41 using namespace anna;
42
43 anna_assign_enum(Variable::Type) =  {
44   "Unused0", "String", "Integer", "Unused1", "Boolean", "Integer64", "Block", "Float", "Double", "Custom", NULL
45 };
46
47 Variable::Variable(const char* name, const Type::_v type) :
48   a_name(name),
49   a_isNull(true),
50   a_type(type),
51   a_isOwner(true) {
52   anna_memset(&a_value, 0, sizeof(a_value));
53
54   switch(type) {
55   case Type::String: a_value.a_string = new std::string; break;
56   case Type::Integer: a_value.a_integer = &a_aux.integer; break;
57   case Type::Integer64: a_value.a_longInteger = &a_aux.longInteger; break;
58   case Type::Boolean: a_value.a_boolean = &a_aux.boolean; break;
59   case Type::Block: a_value.a_dataBlock = new DataBlock(true); break;
60   case Type::Float: a_value.a_float = &a_aux.theFloat; break;
61   case Type::Double: a_value.a_double = &a_aux.theDouble; break;
62   case Type::Custom: a_value.a_custom = NULL; break;
63   default: break;
64   }
65 }
66
67 Variable::~Variable() {
68   if(a_isOwner == false)
69     return;
70
71   switch(a_type) {
72   case Type::String:
73     delete a_value.a_string;
74     a_value.a_string = NULL;
75     break;
76   case Type::Block:
77     delete a_value.a_dataBlock;
78     a_value.a_dataBlock = NULL;
79     break;
80   default: break;
81   }
82 }
83
84 void Variable::setValue(const char* value)
85 throw(RuntimeException) {
86   verifyMatchType(Type::String, ANNA_FILE_LOCATION);
87   a_isNull = false;
88   *a_value.a_string = value;
89 }
90
91 void Variable::setValue(const int value)
92 throw(RuntimeException) {
93   verifyMatchType(Type::Integer, ANNA_FILE_LOCATION);
94   a_isNull = false;
95   *a_value.a_integer = value;
96 }
97
98 void Variable::setValue(const S64 value)
99 throw(RuntimeException) {
100   verifyMatchType(Type::Integer64, ANNA_FILE_LOCATION);
101   a_isNull = false;
102   *a_value.a_longInteger = value;
103 }
104
105 void Variable::setValue(const bool value)
106 throw(RuntimeException) {
107   verifyMatchType(Type::Boolean, ANNA_FILE_LOCATION);
108   a_isNull = false;
109   *a_value.a_boolean = value;
110 }
111
112 void Variable::setValue(const DataBlock& value)
113 throw(RuntimeException) {
114   verifyMatchType(Type::Block, ANNA_FILE_LOCATION);
115
116   if(a_value.a_dataBlock->deepCopy() == false) {
117     string msg("Variable: ");
118     msg += a_name;
119     msg += " | Datablock requires deep copy";
120     throw RuntimeException(msg, ANNA_FILE_LOCATION);
121   }
122
123   a_isNull = false;
124   *a_value.a_dataBlock = value;
125 }
126
127 void Variable::setValue(const float value)
128 throw(RuntimeException) {
129   verifyMatchSomeType(Type::Float, Type::Double, ANNA_FILE_LOCATION);
130
131   if(a_type == Type::Float) {
132     a_isNull = false;
133     *a_value.a_float = value;
134   } else if(a_type == Type::Double) {
135     a_isNull = false;
136     *a_value.a_double = value;
137   }
138 }
139
140 void Variable::setValue(const double value)
141 throw(RuntimeException) {
142   verifyMatchSomeType(Type::Float, Type::Double, ANNA_FILE_LOCATION);
143
144   if(a_type == Type::Float) {
145     a_isNull = false;
146     *a_value.a_float = value;
147   } else if(a_type == Type::Double) {
148     a_isNull = false;
149     *a_value.a_double = value;
150   }
151 }
152
153 const char* Variable::getStringValue() const
154 throw(RuntimeException) {
155   verifyIsNotNull(ANNA_FILE_LOCATION);
156   verifyMatchType(Type::String, ANNA_FILE_LOCATION);
157   return a_value.a_string->c_str();
158 }
159
160 int Variable::getIntegerValue() const
161 throw(RuntimeException) {
162   verifyIsNotNull(ANNA_FILE_LOCATION);
163   verifyMatchType(Type::Integer, ANNA_FILE_LOCATION);
164   return *a_value.a_integer;
165 }
166
167 S64 Variable::getInteger64Value() const
168 throw(RuntimeException) {
169   int result(0);
170   verifyIsNotNull(ANNA_FILE_LOCATION);
171   verifyMatchSomeType(Type::Integer, Type::Integer64, ANNA_FILE_LOCATION);
172
173   switch(a_type) {
174   case Type::Integer: result = *a_value.a_integer; break;
175   case Type::Integer64: result = *a_value.a_longInteger; break;
176   default: break;
177   }
178
179   return result;
180 }
181
182 bool Variable::getBooleanValue() const
183 throw(RuntimeException) {
184   verifyIsNotNull(ANNA_FILE_LOCATION);
185   verifyMatchType(Type::Boolean, ANNA_FILE_LOCATION);
186   return *a_value.a_boolean;
187 }
188
189 const DataBlock& Variable::getDataBlockValue() const
190 throw(RuntimeException) {
191   verifyIsNotNull(ANNA_FILE_LOCATION);
192   verifyMatchType(Type::Block, ANNA_FILE_LOCATION);
193   return *a_value.a_dataBlock;
194 }
195
196 float Variable::getFloatValue() const
197 throw(RuntimeException) {
198   float result(0.0);
199   verifyIsNotNull(ANNA_FILE_LOCATION);
200   verifyMatchSomeType(Type::Float, Type::Double, ANNA_FILE_LOCATION);
201
202   switch(a_type) {
203   case Type::Float: result = *a_value.a_float; break;
204   case Type::Double: result = (float) *a_value.a_double; break;
205   default: break;
206   }
207
208   return result;
209 }
210
211 double Variable::getDoubleValue() const
212 throw(RuntimeException) {
213   double result(0.0);
214   verifyIsNotNull(ANNA_FILE_LOCATION);
215   verifyMatchSomeType(Type::Float, Type::Double, ANNA_FILE_LOCATION);
216
217   switch(a_type) {
218   case Type::Float: result = (double) *a_value.a_float; break;
219   case Type::Double: result = *a_value.a_double; break;
220   default: break;
221   }
222
223   return result;
224 }
225
226 String Variable::asString() const
227 throw() {
228   String result("anna::Variable { Name: ");
229   result << a_name;
230   result << " | Type: " << Type::asNotNullCString(a_type);
231   result += " | Value: ";
232
233   if(a_isNull == true)
234     result += "<null>";
235   else {
236     switch(a_type) {
237     case Type::String: result += a_value.a_string->c_str(); break;
238     case Type::Integer: result += functions::asString(*a_value.a_integer); break;
239     case Type::Integer64: result += functions::asString(*a_value.a_longInteger); break;
240     case Type::Boolean: result += functions::asString(*a_value.a_boolean); break;
241     case Type::Block: result += functions::asString(*a_value.a_dataBlock); break;
242     case Type::Float: result += functions::asString("%f", *a_value.a_float); break;
243     case Type::Double: result += functions::asString("%g", *a_value.a_double); break;
244     case Type::Custom: result += functions::asHexString(anna_ptrnumber_cast(a_value.a_custom)); break;
245     default: break;
246     }
247   }
248
249   return result += " }";
250 }
251
252 void* Variable::buffer() const
253 throw() {
254   void* result(NULL);
255
256   switch(a_type) {
257   case Type::String: result = const_cast <char*>(a_value.a_string->data()); break;
258   case Type::Integer: result = a_value.a_integer; break;
259   case Type::Integer64: result = a_value.a_longInteger; break;
260   case Type::Boolean: result = a_value.a_boolean; break;
261   case Type::Block: result = const_cast <char*>(a_value.a_dataBlock->getData()); break;
262   case Type::Float: result = a_value.a_float; break;
263   case Type::Double: result = a_value.a_double; break;
264   case Type::Custom: result = a_value.a_custom; break;
265   default: break;
266   }
267
268   return result;
269 }
270
271 void* Variable::getReference() const
272 throw() {
273   void* result(NULL);
274
275   switch(a_type) {
276   case Type::String: result = a_value.a_string; break;
277   case Type::Integer: result = a_value.a_integer; break;
278   case Type::Integer64: result = a_value.a_longInteger; break;
279   case Type::Boolean: result = a_value.a_boolean; break;
280   case Type::Block: result = a_value.a_dataBlock; break;
281   case Type::Float: result = a_value.a_float; break;
282   case Type::Double: result = a_value.a_double; break;
283   case Type::Custom: result = a_value.a_custom; break;
284   default: break;
285   }
286
287   return result;
288 }
289
290 void Variable::verifyMatchType(const Type::_v type, const char* file, const int lineno) const
291 throw(RuntimeException) {
292   if(a_type != type) {
293     String msg("Variable: ");
294     msg << a_name << " | " << Type::asNotNullCString(type) << " mismatch data type";
295     throw RuntimeException(msg, file, lineno);
296   }
297 }
298
299 void Variable::verifyMatchSomeType(const Type::_v firstType, const Type::_v secondType, const char* file, const int lineno) const
300 throw(RuntimeException) {
301   if(a_type != firstType && a_type != secondType) {
302     String msg("Variable: ");
303     msg << a_name << " | Neihter " << Type::asNotNullCString(firstType);
304     msg << " nor " << Type::asNotNullCString(secondType) << " matches with data type";
305     throw RuntimeException(msg, file, lineno);
306   }
307 }
308
309 void Variable::verifyIsNotNull(const char* file, const int lineno) const
310 throw(RuntimeException) {
311   if(a_isNull == true) {
312     String msg("Variable: ");
313     msg << a_name << " | Variable does not have assigned value";
314     throw RuntimeException(msg, file, lineno);
315   }
316 }