Diana Software
QVdt.cc
Go to the documentation of this file.
1 #include "QVdt.hh"
2 
3 #include <sstream>
4 #include <iterator>
5 #include <ctype.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include "QError.hh"
9 
10 QVdt::QVdt_type QVdt::SearchType (const std::string& str)
11 {
12  // empty string
13  if (!str.size ()) return String_QVdt;
14 
15  // vector first since are simple
16  if (str[0] == '{' && str[str.size () - 1] == '}') return Vector_QVdt;
17 
18  // check for bool
19  if(str == "false" || str == "true" ||
20  str == "FALSE" || str == "TRUE"||
21  str == "f" || str == "t") return Int_QVdt;
22 
23  // then check for number (int or float)
24  char *error_ptr1 = 0,*error_ptr2 = 0;
25  ::strtod (str.c_str (), &error_ptr1);
26  if (error_ptr1 && *error_ptr1) return String_QVdt; // not a number then is a string
27 
28  // then check for float
29  *error_ptr1 = 0;
30  ::strtol (str.c_str (), &error_ptr1, 10);
31  ::strtol (str.c_str (), &error_ptr2, 16);
32  if (error_ptr1 && *error_ptr1 && error_ptr2 && *error_ptr2) return Double_QVdt; // not integer then is a float
33 
34  // last is integer
35  return Int_QVdt;
36 }
37 
38 void QVdt::AssignValue (const std::string& str)
39 {
40  // bx_message msg(bx_message::critic, "QVdt: ");
41  // if (name_s.size ()) msg << "\"" << name_s << "\" ";
42 
43  char *error_ptr = NULL;
44  value_s = str;
45  QError err;
46  switch (type_internal) {
47  case QVdt::String_QVdt:
48  value_s = str;
49  break;
50  case QVdt::Double_QVdt:
51  value_f = ::strtod (str.c_str (), &error_ptr);
52  {
53  std::string msg = std::string("float conversion failed for ") + str;
54  if (value_f == 0 && error_ptr && *error_ptr) {
56  err.SetDescription(msg);
57  {DianaThrow(err)};
58  }
59  }
60  break;
61  case QVdt::Int_QVdt:
62  if(str == "true" || str == "TRUE" || str == "t") value_i = 1;
63  else if(str == "false" || str == "FALSE" || str == "f") value_i = 0;
64  else if(strncmp("0x", &(str.c_str()[str.find_first_not_of(" \t")]), 2) == 0)
65  value_i = ::strtol (str.c_str (), &error_ptr, 16); // 16 means force base 16
66  else value_i = ::strtol (str.c_str (), &error_ptr, 10); // 10 force base 10, 0 means autodetect the base, which is fine for 0x starting hex
67  if (value_i == 0 && error_ptr && *error_ptr) {
68  std::string msg = std::string("integer conversion failed for ") + str;
70  err.SetDescription(msg);
71  {DianaThrow(err)};
72  }
73  break;
74  case QVdt::Vector_QVdt:
75  do {
76  // Fill the vector
77  std::string sub_str;
78  if(str.size() > 1 && str[1] == '{')
79  sub_str = str.substr (2, str.size () - 4); // copy to local (modificable) discarding '{{' and '}}'
80  else
81  sub_str = str.substr (1, str.size () - 2); // copy to local (modificable) discarding '{' and '}'
82  std::string::size_type colon = 0;
83  while (sub_str.size ()) {
84  colon = sub_str.find (',', 0); // Find first ',' (since string is erased from previous fields)
85 
86  if (colon == std::string::npos) colon = sub_str.size (); // If no more ',' are present sub_str is the last field
87 
88  std::string::size_type start_field = 0; // look for spaces around the element like " 12 ,"
89  for (; start_field < colon; start_field++) if (!isspace (sub_str[start_field])) break;
90  std::string::size_type end_field = colon - 1;
91  for (; end_field > start_field; end_field--) if (!isspace (sub_str[end_field])) break;
92 
93  std::string value = sub_str.substr (start_field, end_field - start_field + 1); // Copy the value
94 
95  if (!value.size ()) break; // Stop on last void element
96 
97  value_v.push_back (QVdt (value, name_s)); // Fill the vector
98 
99  sub_str.erase (0, colon + 1); // Move forward
100  }
101  } while (0); // This do while is present to allow the declaration of variables
102  break;
103  default:
104  err.Set(QERR_UNKNOWN_ERR, __FILE__, __LINE__,
105  "internal QVdt error: cannot call AssignValue with an "
106  "undefined type value: \"" + str + "\"");
107  {DianaThrow(err)};
108  }
109 }
110 
111 std::string QVdt::ToString() const
112 {
113  std::stringstream s;
114  switch(type_internal)
115  {
116  case Int_QVdt:
117  s<<value_i;
118  break;
119  case Double_QVdt:
120  s<<value_f;
121  break;
122  case String_QVdt:
123  s<<value_s;
124  break;
125  case Vector_QVdt:
126  {
127  s<<"{";
128  QVdt_vector::const_iterator viter = value_v.begin();
129  while(viter != value_v.end()) {
130  s<<viter->GetString()<<",";
131  viter++;
132  }
133  s<<"}";
134  }
135  break;
136  case Unassigned_QVdt:
137  default:
138  {
139  QError err;
141  err.SetDescription("internal QVdt error: cannot convert to string with an undefined type value");
142  {DianaThrow(err)};
143  }
144  break;
145  }
146  return s.str();
147 }
148 
149 QVdt::QVdt (const std::string& value, const std::string& name, QVdt_type type): name_s(name)
150 {
151  QVdt_type tmp_type = SearchType (value);
152  type_internal = tmp_type;
153  if( type != Unassigned_QVdt) {
154  CheckType(type);
155  type_internal = type;
156  }
157  AssignValue (value);
158  fBuiltFromString = true;
159 }
160 
161 const QVdt& QVdt::operator= (const std::string& value)
162 {
163  QVdt_type tmp_type = SearchType (value);
164 
165  if (type_internal != Unassigned_QVdt) CheckType (tmp_type);
166 
167  type_internal = tmp_type;
168  AssignValue (value);
169 
170  fBuiltFromString = true;
171  return *this;
172 }
173 
174 const QVdt& QVdt::operator= (long int value)
175 {
177 
179  value_i = value;
180 
181  fBuiltFromString = false;
182  return *this;
183 }
184 
185 const QVdt& QVdt::operator= (double value)
186 {
188 
190  value_f = value;
191 
192  fBuiltFromString = false;
193  return *this;
194 }
195 
196 const QVdt& QVdt::operator=(const QVdt& other)
197 {
198  // if this is a string
200  CheckType (other.GetType());
201  }
203  value_i = other.value_i;
204  value_f = other.value_f;
205  value_v = other.value_v;
206  value_s = other.GetString();
208  if(name_s == "") name_s = other.name_s;
209  return *this;
210 }
211 
212 
213 long int QVdt::GetInt () const
214 {
216  return value_i;
217 }
218 
219 double QVdt::GetDouble () const
220 {
222  return (type_internal == Double_QVdt) ? value_f : value_i; // int->float cast always allowed
223 }
224 
225 const std::string& QVdt::GetString () const
226 {
227  // always allow reading a parameter as string
229  value_s = ToString();
230  return value_s;
231 }
232 
234 {
236  return value_v;
237 }
238 
239 void QVdt::CheckType (QVdt_type new_type) const
240 {
241  if (type_internal == new_type) return;
242 
243  if (new_type == Double_QVdt && type_internal == Int_QVdt) return; // int->float cast always allowed
245  std::stringstream msg;
246  if (name_s.size ()) msg << "\"" << name_s << "\" ";
247  msg << "requested " << char(new_type) << " while current type is " << char(type_internal) << " (" << *this << "); cast not allowed";
248  err.SetDescription(msg.str());
249  {DianaThrow(err)};
250 }
251 
252 
253 std::ostream& operator<< (std::ostream& out, const QVdt& v) {
254  switch (v.GetType ()) {
255  case QVdt::Int_QVdt:
256  out << v.GetInt ();
257  break;
258  case QVdt::Double_QVdt:
259  out << v.GetDouble ();
260  break;
261  case QVdt::String_QVdt:
262  out << v.GetString ();
263  break;
264  case QVdt::Vector_QVdt:
265  out << "{ ";
266  if (v.GetVector ().size ()) {
267  std::copy (v.GetVector ().begin (), v.GetVector ().end () - 1, std::ostream_iterator<QVdt>(out, ", "));
268  out << *(v.GetVector ().end () - 1) << " ";
269  }
270  out << "}";
271  break;
272  default:
273  out << "unknown type (" << v.GetName() << ")";
274  }
275  return out;
276 }
277 
278 template <> int QVdt::Get<int>() const
279 {
280  return GetInt();
281 }
282 
283 template <> double QVdt::Get<double>() const
284 {
285  return GetDouble();
286 }
287 
288 template <> bool QVdt::Get<bool>() const
289 {
290  return GetBool();
291 }
292 
293 template <> std::string QVdt::Get<std::string>() const
294 {
295  return GetString();
296 }
err
Definition: CheckOF.C:114
#define DianaThrow(obj)
Definition: QDianaDebug.hh:26
@ QERR_TYPE_CONVERSION
Definition: QError.hh:36
@ QERR_UNKNOWN_ERR
Definition: QError.hh:108
std::ostream & operator<<(std::ostream &out, const QVdt &v)
Definition: QVdt.cc:253
error class with error type and description
Definition: QError.hh:115
Variable Data Type.
Definition: QVdt.hh:26
void CheckType(QVdt_type new_type) const
Definition: QVdt.cc:239
QVdt_type
Definition: QVdt.hh:30
@ Vector_QVdt
Definition: QVdt.hh:34
@ String_QVdt
Definition: QVdt.hh:33
@ Double_QVdt
Definition: QVdt.hh:32
@ Int_QVdt
Definition: QVdt.hh:31
@ Unassigned_QVdt
Definition: QVdt.hh:35
bool GetBool() const
Definition: QVdt.hh:102
double GetDouble() const
Definition: QVdt.cc:219
QVdt_vector value_v
Definition: QVdt.hh:118
bool fBuiltFromString
Definition: QVdt.hh:121
double value_f
Definition: QVdt.hh:116
std::string value_s
Definition: QVdt.hh:117
void AssignValue(const std::string &str)
Definition: QVdt.cc:38
QVdt()
Definition: QVdt.hh:40
const QVdt & operator=(const std::string &value)
Definition: QVdt.cc:161
long int value_i
Definition: QVdt.hh:115
std::string ToString() const
Definition: QVdt.cc:111
std::vector< QVdt > QVdt_vector
Definition: QVdt.hh:38
std::string name_s
Definition: QVdt.hh:120
const std::string & GetString() const
Definition: QVdt.cc:225
std::string GetName() const
Definition: QVdt.hh:68
const QVdt_vector & GetVector() const
Definition: QVdt.cc:233
QVdt_type GetType() const
Definition: QVdt.hh:96
long int GetInt() const
Definition: QVdt.cc:213
QVdt_type type_internal
Definition: QVdt.hh:113
QVdt_type SearchType(const std::string &str)
Definition: QVdt.cc:10