varconf  1.0.3
Configuration library for the Worldforge system.
variable.cpp
1 /*
2  * variable.cpp - implementation of the typeless value container.
3  * Copyright (C) 2001, Stefanus Du Toit, Joseph Zupko
4  * (C) 2003-2006 Alistair Riddoch
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  *
20  * Contact: Joseph Zupko
21  * jaz147@psu.edu
22  *
23  * 189 Reese St.
24  * Old Forge, PA 18518
25  */
26 
27 #include "variable.h"
28 
29 #include <string>
30 #include <cstdio>
31 #include <cstdlib>
32 #include <utility>
33 
34 #ifdef _WIN32
35 #define snprintf _snprintf
36 #endif
37 
38 namespace varconf {
39 
40 VarBase::VarBase()
41  : m_have_bool(false), m_have_int(false), m_have_double(false),
42  m_have_string(false), m_val_bool(false), m_val_int(0), m_val_double(0.0),
43  m_val(""), m_scope(GLOBAL)
44 {
45 }
46 
47 VarBase::VarBase(const VarBase& c)
48  : sigc::trackable(c), m_have_bool(c.m_have_bool), m_have_int(c.m_have_int),
49  m_have_double(c.m_have_double), m_have_string(c.m_have_string),
50  m_val_bool(c.m_val_bool), m_val_int(c.m_val_int),
51  m_val_double(c.m_val_double), m_val(c.m_val), m_scope(GLOBAL)
52 {
53 }
54 
55 VarBase::VarBase(bool b)
56  : m_have_bool(true), m_have_int(false), m_have_double(false),
57  m_have_string(true), m_val_bool(b), m_val_int(0), m_val_double(0.0),
58  m_scope(GLOBAL)
59 {
60  m_val = (b ? "true" : "false");
61 }
62 
63 VarBase::VarBase(int i)
64  : m_have_bool(false), m_have_int(true), m_have_double(false),
65  m_have_string(true), m_val_bool(false), m_val_int(i), m_val_double(0.0),
66  m_scope(GLOBAL)
67 {
68  char buf[1024];
69  snprintf(buf, 1024, "%d", i);
70  m_val = buf;
71 }
72 
73 VarBase::VarBase(double d)
74  : m_have_bool(false), m_have_int(false), m_have_double(true),
75  m_have_string(true), m_val_bool(false), m_val_int(0), m_val_double(d),
76  m_scope(GLOBAL)
77 {
78  char buf[1024];
79  snprintf(buf, 1024, "%lf", d);
80  m_val = buf;
81 }
82 
83 VarBase::VarBase(std::string s)
84  : m_have_bool(false), m_have_int(false), m_have_double(false),
85  m_have_string(true), m_val_bool(false), m_val_int(0), m_val_double(0.0),
86  m_val(std::move(s)), m_scope(GLOBAL)
87 {
88 }
89 
90 VarBase::VarBase(const char* s)
91  : m_have_bool(false), m_have_int(false), m_have_double(false),
92  m_have_string(true), m_val_bool(false), m_val_int(0), m_val_double(0.0),
93  m_val(s), m_scope(GLOBAL)
94 {
95 }
96 
97 VarBase::~VarBase() = default;
98 
99 std::ostream& operator<<( std::ostream& out, const VarBase& v)
100 {
101  for (char i : v.m_val) {
102  if (i == '"') out << '\\';
103  else if (i == '\\') out << '\\';
104  out << i;
105  }
106  return out;
107 }
108 
109 bool operator ==( const VarBase& one, const VarBase& two)
110 {
111  return one.m_val == two.m_val;
112  // scope is explicitly excluded as its nothing to do with value comparisons
113 
114 }
115 
116 bool operator !=(const VarBase& one, const VarBase& two)
117 {
118  return !(one == two);
119 }
120 
121 VarBase& VarBase::operator=(const VarBase& c)
122 {
123  if (&c == this) return (*this);
124  m_have_bool = c.m_have_bool; m_have_int = c.m_have_int;
125  m_have_double = c.m_have_double; m_have_string = c.m_have_string;
126  m_val_bool = c.m_val_bool; m_val_int = c.m_val_int;
127  m_val_double = c.m_val_double; m_val = c.m_val;
128  m_scope = c.m_scope;
129  return (*this);
130 }
131 
132 VarBase& VarBase::operator=(bool b)
133 {
134  m_have_bool = true; m_have_int = false;
135  m_have_double = false; m_have_string = true;
136  m_val_bool = b; m_val_int = 0;
137  m_val_double = 0.0; m_val = (b ? "true" : "false");
138  m_scope = INSTANCE;
139  return (*this);
140 }
141 
142 VarBase& VarBase::operator=(int i)
143 {
144  m_have_bool = false; m_have_int = true;
145  m_have_double = false; m_have_string = true;
146  m_val_bool = false; m_val_int = i;
147  m_val_double = 0.0;
148  char buf[1024]; snprintf(buf, 1024, "%d", i);
149  m_val = buf;
150  m_scope = INSTANCE;
151  return (*this);
152 }
153 
154 VarBase& VarBase::operator=(double d)
155 {
156  m_have_bool = false; m_have_int = false;
157  m_have_double = true; m_have_string = true;
158  m_val_bool = false; m_val_int = 0;
159  m_val_double = d;
160  char buf[1024]; snprintf(buf, 1024, "%lf", d);
161  m_val = buf;
162  m_scope = INSTANCE;
163  return (*this);
164 }
165 
166 VarBase& VarBase::operator=(const std::string& s)
167 {
168  m_have_bool = false; m_have_int = false;
169  m_have_double = false; m_have_string = true;
170  m_val_bool = false; m_val_int = 0;
171  m_val_double = 0.0; m_val = s;
172  m_scope = INSTANCE;
173  return (*this);
174 }
175 
176 VarBase& VarBase::operator=(const char* s)
177 {
178  m_have_bool = false; m_have_int = false;
179  m_have_double = false; m_have_string = true;
180  m_val_bool = false; m_val_int = 0;
181  m_val_double = 0.0; m_val = s;
182  m_scope = INSTANCE;
183  return (*this);
184 }
185 
186 VarBase::operator bool() const
187 {
188  if (!m_have_bool) {
189  m_val_bool = (m_val == "on") ||
190  (m_val == "1") ||
191  (m_val == "true") ||
192  (m_val =="yes") ||
193  (m_val == "y");
194  m_have_bool = true;
195  }
196  return m_val_bool;
197 }
198 
199 VarBase::operator int() const
200 {
201  if (!m_have_int) {
202  m_val_int = atoi(m_val.c_str());
203  m_have_int = true;
204  }
205  return m_val_int;
206 }
207 
208 VarBase::operator double() const
209 {
210  if (!m_have_double) {
211  m_val_double = atof(m_val.c_str());
212  m_have_double = true;
213  }
214  return m_val_double;
215 }
216 
217 VarBase::operator std::string() const
218 {
219  return m_val;
220 }
221 
222 bool VarBase::is_bool()
223 {
224  if (!is_string()) return false;
225  return (m_val == "on") || (m_val == "off")
226  || (m_val == "1") || (m_val == "0")
227  || (m_val == "true") || (m_val == "false")
228  || (m_val == "yes") || (m_val == "no")
229  || (m_val == "y") || (m_val == "n");
230 }
231 
232 bool VarBase::is_int()
233 {
234  if (!is_string()) return false;
235  for (char i : m_val) if (!isdigit(i))
236  return false;
237  return true;
238 }
239 
240 bool VarBase::is_double()
241 {
242  if (!is_string()) return false;
243 
244  char* p;
245 
246  // strtod() points p to the first character
247  // in the string that doesn't look like
248  // part of a double
249  strtod(m_val.c_str(), &p); //-V530
250 
251  return p == m_val.c_str() + m_val.size();
252 }
253 
254 bool VarBase::is_string()
255 {
256  return m_have_string;
257 }
258 
259 Variable::Variable (const Variable& c) : VarPtr(c.is_array()
260  ? VarPtr(new VarArray(*(c.array()))) : static_cast<const VarPtr&>(c))
261 {
262 
263 }
264 
265 Variable::Variable( const int n, const Variable& v)
266  : VarPtr(new VarArray(n, v))
267 {
268 
269 }
270 
271 Variable::Variable( const VarList& v) : VarPtr(new VarArray(v))
272 {
273 
274 }
275 
276 Variable::~Variable() = default;
277 
278 Variable& Variable::operator=( const Variable& c)
279 {
280  VarList *array_val = c.array();
281 
282  if(array_val) // Equivalent to c.is_array()
283  VarPtr::operator=(new VarArray(*array_val));
284  else
285  VarPtr::operator=(c);
286  return *this;
287 }
288 
289 Variable& Variable::operator=( VarBase* vb)
290 {
291  VarPtr::operator=(vb);
292  return *this;
293 }
294 
295 Variable& Variable::operator=( const bool b)
296 {
297  VarPtr::operator=(new VarBase(b));
298  return *this;
299 }
300 
301 Variable& Variable::operator=( const int i)
302 {
303  VarPtr::operator=(new VarBase(i));
304  return *this;
305 }
306 
307 Variable& Variable::operator=( const double d)
308 {
309  VarPtr::operator=(new VarBase(d));
310  return *this;
311 }
312 
313 Variable& Variable::operator=( const std::string& s)
314 {
315  VarPtr::operator=(new VarBase(s));
316  return *this;
317 }
318 
319 Variable& Variable::operator=( const char* s)
320 {
321  VarPtr::operator=(new VarBase(s));
322  return *this;
323 }
324 
325 Variable& Variable::operator=( const VarList& v)
326 {
327  VarPtr::operator=(new VarArray(v));
328  return *this;
329 }
330 
331 Variable& Variable::operator[](const int i)
332 {
333  std::vector<Variable> *the_array = array();
334 
335  if(!the_array) {
336  auto *new_array = new VarArray(i + 1);
337  (*new_array)[0] = *this;
338  VarPtr::operator=(new_array);
339  the_array = new_array;
340  }
341  else if ((int)the_array->size() < i + 1)
342  the_array->resize(i + 1);
343 
344  return (*the_array)[i];
345 }
346 
347 
348 VarArray::~VarArray() = default;
349 
350 std::ostream& operator<<( std::ostream& out, const VarArray& v)
351 {
352  out << "(";
353 
354  auto i = v.begin();
355  while(true) {
356  out << *i;
357  if(++i == v.end())
358  break;
359  out << ",";
360  }
361 
362  out << ")";
363  return out;
364 }
365 
366 bool operator ==( const VarArray& one, const VarArray& two)
367 {
368  if(one.size() != two.size())
369  return false;
370 
371  VarArray::const_iterator i1, i2;
372 
373  for(i1 = one.begin(), i2 = two.begin(); i1 != one.end(); ++i1, ++i2)
374  if(i1->elem() != i2->elem())
375  return false;
376 
377  return true;
378 }
379 
380 VarArray::operator bool() const
381 {
382  return false;
383 }
384 
385 VarArray::operator int() const
386 {
387  return 0;
388 }
389 
390 VarArray::operator double() const
391 {
392  return 0;
393 }
394 
395 VarArray::operator std::string() const
396 {
397  return "";
398 }
399 
400 
401 bool VarArray::is_bool()
402 {
403  return false;
404 }
405 
406 bool VarArray::is_int()
407 {
408  return false;
409 }
410 
411 bool VarArray::is_double()
412 {
413  return false;
414 }
415 
416 bool VarArray::is_string()
417 {
418  return false;
419 }
420 
421 } // namespace varconf