aGrUM  0.16.0
DBCell.cpp
Go to the documentation of this file.
1 
28 #include <cstdio>
30 
31 
32 #ifndef DOXYGEN_SHOULD_SKIP_THIS
33 
35 # ifdef GUM_NO_INLINE
37 # endif /* GUM_NO_INLINE */
38 
39 namespace gum {
40 
41  namespace learning {
42 
43  // create the static members
44  int DBCell::__string_max_index = 0;
45 
46 
47  Bijection< std::string, int >& DBCell::__strings() {
48 # ifdef GUM_DEBUG_MODE
49  static bool first_time = true;
50  if (first_time) {
51  first_time = false;
52  __debug__::__dec_creation(
53  "Bijection", "__strings", 0, "BCell string bijection", 0);
54  __debug__::__dec_creation(
55  "BijectionImplementation", "__strings", 0, "BCell string bijection", 0);
56  __debug__::__dec_creation(
57  "HashTable", "__strings", 0, "BCell string bijection", 0);
58  __debug__::__dec_creation(
59  "HashTable", "__strings", 0, "BCell string bijection", 0);
60  }
61 # endif
62  static Bijection< std::string, int > strings;
63  return strings;
64  }
65 
66 
67  // determines whether a string corresponds to an integer
68  bool DBCell::isInteger(const std::string& str) {
69  if (str.empty()) return false;
70 
71  // trim the string
72  auto start_iter = str.begin() + str.find_first_not_of(" \t");
73  auto end_iter = str.begin() + str.find_last_not_of(" \t\r\n") + 1;
74 
75  if (start_iter == end_iter) return false;
76 
77  // if the number is negative, pass the '-' sign
78  if (*start_iter == '-') ++start_iter;
79 
80  // check wether we have a number
81  for (; start_iter != end_iter; ++start_iter) {
82  if ((*start_iter < '0') || (*start_iter > '9')) return false;
83  }
84 
85  return true;
86  }
87 
88 
89  // determines whether a string corresponds to an integer
90  bool DBCell::isReal(const std::string& str) {
91  if (str.empty()) return false;
92 
93  // trim the string
94  auto start_iter = str.begin() + str.find_first_not_of(" \t");
95  auto end_iter = str.begin() + str.find_last_not_of(" \t\r\n") + 1;
96 
97  if (start_iter == end_iter) return false;
98 
99  // check wether we have a number
100  bool has_dot = false;
101  bool has_exponent = false;
102  bool has_digit = false;
103  bool has_negation = false;
104  for (; start_iter != end_iter; ++start_iter) {
105  if (*start_iter == '-') {
106  if (has_negation) return false;
107  } else if (*start_iter == '.') {
108  if (has_dot || has_exponent) return false;
109  has_dot = true;
110  } else if ((*start_iter == 'e') || (*start_iter == 'E')) {
111  if (has_exponent || !has_digit) return false;
112  has_exponent = true;
113  has_negation = false;
114  } else if ((*start_iter < '0') || (*start_iter > '9'))
115  return false;
116  else
117  has_digit = true;
118  }
119 
120  return true;
121  }
122 
123 
124  // try to convert the content of the DBCell into another type
125  bool DBCell::convertType(const EltType new_type) {
126  if (new_type == __type) return true;
127  switch (new_type) {
128  // ===================================
129  case EltType::REAL:
130  switch (__type) {
131  case EltType::INTEGER:
132  __val_real = float(__val_integer);
133  __type = EltType::REAL;
134  return true;
135 
136  case EltType::STRING:
137  try {
138  const std::string& str = __strings().first(__val_index);
139  if (!isReal(str)) return false;
140  __val_real = std::stof(str);
141  __type = EltType::REAL;
142  return true;
143  } catch (std::invalid_argument&) { return false; }
144 
145  case EltType::MISSING: return false;
146 
147  default:
148  GUM_ERROR(NotImplementedYet,
149  "type not supported by DBCell convertType");
150  }
151 
152  // ===================================
153  case EltType::INTEGER:
154  switch (__type) {
155  case EltType::REAL: {
156  const int nb = int(__val_real);
157  if (nb == __val_real) {
158  __val_integer = nb;
159  __type = EltType::INTEGER;
160  return true;
161  } else
162  return false;
163  }
164 
165  case EltType::STRING:
166  try {
167  const std::string& str = __strings().first(__val_index);
168  if (!isInteger(str)) return false;
169  __val_integer = std::stoi(str);
170  __type = EltType::INTEGER;
171  return true;
172  } catch (std::invalid_argument&) { return false; }
173 
174  case EltType::MISSING: return false;
175 
176  default:
177  GUM_ERROR(NotImplementedYet,
178  "type not supported by DBCell convertType");
179  }
180 
181  // ===================================
182  case EltType::STRING:
183  switch (__type) {
184  case EltType::REAL: {
185  char buffer[100];
186  sprintf(buffer, "%g", __val_real);
187  const std::string str(buffer);
188  if (!__strings().existsFirst(str)) {
189  __strings().insert(str, __string_max_index);
190  __val_index = __string_max_index;
191  ++__string_max_index;
192  } else {
193  __val_index = __strings().second(str);
194  }
195  }
196  __type = EltType::STRING;
197  return true;
198 
199  case EltType::INTEGER: {
200  const std::string str = std::to_string(__val_integer);
201  if (!__strings().existsFirst(str)) {
202  __strings().insert(str, __string_max_index);
203  __val_index = __string_max_index;
204  ++__string_max_index;
205  } else {
206  __val_index = __strings().second(str);
207  }
208  }
209  __type = EltType::STRING;
210  return true;
211 
212  case EltType::MISSING: return false;
213 
214  default:
215  GUM_ERROR(NotImplementedYet,
216  "type not supported by DBCell convertType");
217  }
218 
219  // ===================================
220  case EltType::MISSING: __type = EltType::MISSING; return true;
221 
222  default:
223  GUM_ERROR(NotImplementedYet, "type not supported by DBCell convertType");
224  }
225 
226  return false;
227  }
228 
229 
230  // raises an appropriate exception when encountering a type error
231  std::string DBCell::__typeErrorMsg(const std::string& true_type) const {
232  std::stringstream str;
233  switch (__type) {
234  case EltType::REAL:
235  str << "The DBCell contains a real number instead of " << true_type;
236  break;
237 
238  case EltType::INTEGER:
239  str << "The DBCell contains an integer instead of " << true_type;
240  break;
241 
242  case EltType::STRING:
243  str << "The DBCell contains a string instead of " << true_type;
244  break;
245 
246  case EltType::MISSING:
247  str << "The DBCell contains a missing value instead of " << true_type;
248  break;
249 
250  default: GUM_ERROR(NotImplementedYet, "DBCell type not implemented yet");
251  }
252 
253  return str.str();
254  }
255 
256  } /* namespace learning */
257 
258 } /* namespace gum */
259 
260 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
bool convertType(const EltType newtype)
try to convert the content of the DBCell into another type
static bool isInteger(const std::string &str)
determines whether a string corresponds precisely to an integer
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
std::string to_string(const Formula &f)
Definition: formula_inl.h:499
static bool isReal(const std::string &str)
determine whether a string corresponds precisely to a real number
EltType
the set of types possibly taken by the last element read
Definition: DBCell.h:75
#define GUM_ERROR(type, msg)
Definition: exceptions.h:55