Updated license
[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 // https://bitbucket.org/testillano/anna
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 Google Inc. 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   }
64 }
65
66 Variable::~Variable() {
67   if(a_isOwner == false)
68     return;
69
70   switch(a_type) {
71   case Type::String:
72     delete a_value.a_string;
73     a_value.a_string = NULL;
74     break;
75   case Type::Block:
76     delete a_value.a_dataBlock;
77     a_value.a_dataBlock = NULL;
78     break;
79   }
80 }
81
82 void Variable::setValue(const char* value)
83 throw(RuntimeException) {
84   verifyMatchType(Type::String, ANNA_FILE_LOCATION);
85   a_isNull = false;
86   *a_value.a_string = value;
87 }
88
89 void Variable::setValue(const int value)
90 throw(RuntimeException) {
91   verifyMatchType(Type::Integer, ANNA_FILE_LOCATION);
92   a_isNull = false;
93   *a_value.a_integer = value;
94 }
95
96 void Variable::setValue(const S64 value)
97 throw(RuntimeException) {
98   verifyMatchType(Type::Integer64, ANNA_FILE_LOCATION);
99   a_isNull = false;
100   *a_value.a_longInteger = value;
101 }
102
103 void Variable::setValue(const bool value)
104 throw(RuntimeException) {
105   verifyMatchType(Type::Boolean, ANNA_FILE_LOCATION);
106   a_isNull = false;
107   *a_value.a_boolean = value;
108 }
109
110 void Variable::setValue(const DataBlock& value)
111 throw(RuntimeException) {
112   verifyMatchType(Type::Block, ANNA_FILE_LOCATION);
113
114   if(a_value.a_dataBlock->deepCopy() == false) {
115     string msg("Variable: ");
116     msg += a_name;
117     msg += " | Datablock requires deep copy";
118     throw RuntimeException(msg, ANNA_FILE_LOCATION);
119   }
120
121   a_isNull = false;
122   *a_value.a_dataBlock = value;
123 }
124
125 void Variable::setValue(const float value)
126 throw(RuntimeException) {
127   verifyMatchSomeType(Type::Float, Type::Double, ANNA_FILE_LOCATION);
128
129   if(a_type == Type::Float) {
130     a_isNull = false;
131     *a_value.a_float = value;
132   } else if(a_type == Type::Double) {
133     a_isNull = false;
134     *a_value.a_double = value;
135   }
136 }
137
138 void Variable::setValue(const double value)
139 throw(RuntimeException) {
140   verifyMatchSomeType(Type::Float, Type::Double, ANNA_FILE_LOCATION);
141
142   if(a_type == Type::Float) {
143     a_isNull = false;
144     *a_value.a_float = value;
145   } else if(a_type == Type::Double) {
146     a_isNull = false;
147     *a_value.a_double = value;
148   }
149 }
150
151 const char* Variable::getStringValue() const
152 throw(RuntimeException) {
153   verifyIsNotNull(ANNA_FILE_LOCATION);
154   verifyMatchType(Type::String, ANNA_FILE_LOCATION);
155   return a_value.a_string->c_str();
156 }
157
158 int Variable::getIntegerValue() const
159 throw(RuntimeException) {
160   verifyIsNotNull(ANNA_FILE_LOCATION);
161   verifyMatchType(Type::Integer, ANNA_FILE_LOCATION);
162   return *a_value.a_integer;
163 }
164
165 S64 Variable::getInteger64Value() const
166 throw(RuntimeException) {
167   int result(0);
168   verifyIsNotNull(ANNA_FILE_LOCATION);
169   verifyMatchSomeType(Type::Integer, Type::Integer64, ANNA_FILE_LOCATION);
170
171   switch(a_type) {
172   case Type::Integer: result = *a_value.a_integer; break;
173   case Type::Integer64: result = *a_value.a_longInteger; break;
174   }
175
176   return result;
177 }
178
179 bool Variable::getBooleanValue() const
180 throw(RuntimeException) {
181   verifyIsNotNull(ANNA_FILE_LOCATION);
182   verifyMatchType(Type::Boolean, ANNA_FILE_LOCATION);
183   return *a_value.a_boolean;
184 }
185
186 const DataBlock& Variable::getDataBlockValue() const
187 throw(RuntimeException) {
188   verifyIsNotNull(ANNA_FILE_LOCATION);
189   verifyMatchType(Type::Block, ANNA_FILE_LOCATION);
190   return *a_value.a_dataBlock;
191 }
192
193 float Variable::getFloatValue() const
194 throw(RuntimeException) {
195   float result(0.0);
196   verifyIsNotNull(ANNA_FILE_LOCATION);
197   verifyMatchSomeType(Type::Float, Type::Double, ANNA_FILE_LOCATION);
198
199   switch(a_type) {
200   case Type::Float: result = *a_value.a_float; break;
201   case Type::Double: result = (float) *a_value.a_double; break;
202   }
203
204   return result;
205 }
206
207 double Variable::getDoubleValue() const
208 throw(RuntimeException) {
209   double result(0.0);
210   verifyIsNotNull(ANNA_FILE_LOCATION);
211   verifyMatchSomeType(Type::Float, Type::Double, ANNA_FILE_LOCATION);
212
213   switch(a_type) {
214   case Type::Float: result = (double) *a_value.a_float; break;
215   case Type::Double: result = *a_value.a_double; break;
216   }
217
218   return result;
219 }
220
221 String Variable::asString() const
222 throw() {
223   String result("anna::Variable { Name: ");
224   result << a_name;
225   result << " | Type: " << Type::asNotNullCString(a_type);
226   result += " | Value: ";
227
228   if(a_isNull == true)
229     result += "<null>";
230   else {
231     switch(a_type) {
232     case Type::String: result += a_value.a_string->c_str(); break;
233     case Type::Integer: result += functions::asString(*a_value.a_integer); break;
234     case Type::Integer64: result += functions::asString(*a_value.a_longInteger); break;
235     case Type::Boolean: result += functions::asString(*a_value.a_boolean); break;
236     case Type::Block: result += functions::asString(*a_value.a_dataBlock); break;
237     case Type::Float: result += functions::asString("%f", *a_value.a_float); break;
238     case Type::Double: result += functions::asString("%g", *a_value.a_double); break;
239     case Type::Custom: result += functions::asHexString(anna_ptrnumber_cast(a_value.a_custom)); break;
240     }
241   }
242
243   return result += " }";
244 }
245
246 void* Variable::buffer() const
247 throw() {
248   void* result(NULL);
249
250   switch(a_type) {
251   case Type::String: result = const_cast <char*>(a_value.a_string->data()); break;
252   case Type::Integer: result = a_value.a_integer; break;
253   case Type::Integer64: result = a_value.a_longInteger; break;
254   case Type::Boolean: result = a_value.a_boolean; break;
255   case Type::Block: result = const_cast <char*>(a_value.a_dataBlock->getData()); break;
256   case Type::Float: result = a_value.a_float; break;
257   case Type::Double: result = a_value.a_double; break;
258   case Type::Custom: result = a_value.a_custom; break;
259   }
260
261   return result;
262 }
263
264 void* Variable::getReference() const
265 throw() {
266   void* result(NULL);
267
268   switch(a_type) {
269   case Type::String: result = a_value.a_string; break;
270   case Type::Integer: result = a_value.a_integer; break;
271   case Type::Integer64: result = a_value.a_longInteger; break;
272   case Type::Boolean: result = a_value.a_boolean; break;
273   case Type::Block: result = a_value.a_dataBlock; break;
274   case Type::Float: result = a_value.a_float; break;
275   case Type::Double: result = a_value.a_double; break;
276   case Type::Custom: result = a_value.a_custom; break;
277   }
278
279   return result;
280 }
281
282 void Variable::verifyMatchType(const Type::_v type, const char* file, const int lineno) const
283 throw(RuntimeException) {
284   if(a_type != type) {
285     String msg("Variable: ");
286     msg << a_name << " | " << Type::asNotNullCString(type) << " mismatch data type";
287     throw RuntimeException(msg, file, lineno);
288   }
289 }
290
291 void Variable::verifyMatchSomeType(const Type::_v firstType, const Type::_v secondType, const char* file, const int lineno) const
292 throw(RuntimeException) {
293   if(a_type != firstType && a_type != secondType) {
294     String msg("Variable: ");
295     msg << a_name << " | Neihter " << Type::asNotNullCString(firstType);
296     msg << " nor " << Type::asNotNullCString(secondType) << " matches with data type";
297     throw RuntimeException(msg, file, lineno);
298   }
299 }
300
301 void Variable::verifyIsNotNull(const char* file, const int lineno) const
302 throw(RuntimeException) {
303   if(a_isNull == true) {
304     String msg("Variable: ");
305     msg << a_name << " | Variable does not have assigned value";
306     throw RuntimeException(msg, file, lineno);
307   }
308 }