aGrUM  0.14.2
DBCell.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005 by Christophe GONZALES and Pierre-Henri WUILLEMIN *
3  * {prenom.nom}_at_lip6.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
25 #include <cstdio>
27 
28 
29 #ifndef DOXYGEN_SHOULD_SKIP_THIS
30 
32 # ifdef GUM_NO_INLINE
34 # endif /* GUM_NO_INLINE */
35 
36 namespace gum {
37 
38  namespace learning {
39 
40  // create the static members
41  int DBCell::__string_max_index = 0;
42 
43 
44  Bijection< std::string, int >& DBCell::__strings() {
45 # ifdef GUM_DEBUG_MODE
46  static bool first_time = true;
47  if (first_time) {
48  first_time = false;
49  __debug__::__dec_creation(
50  "Bijection", "__strings", 0, "BCell string bijection", 0);
51  __debug__::__dec_creation(
52  "BijectionImplementation", "__strings", 0, "BCell string bijection", 0);
53  __debug__::__dec_creation(
54  "HashTable", "__strings", 0, "BCell string bijection", 0);
55  __debug__::__dec_creation(
56  "HashTable", "__strings", 0, "BCell string bijection", 0);
57  }
58 # endif
59  static Bijection< std::string, int > strings;
60  return strings;
61  }
62 
63 
64  // determines whether a string corresponds to an integer
65  bool DBCell::isInteger(const std::string& str) {
66  if (str.empty()) return false;
67 
68  // trim the string
69  auto start_iter = str.begin() + str.find_first_not_of(" \t");
70  auto end_iter = str.begin() + str.find_last_not_of(" \t\r\n") + 1;
71 
72  if (start_iter == end_iter) return false;
73 
74  // if the number is negative, pass the '-' sign
75  if (*start_iter == '-') ++start_iter;
76 
77  // check wether we have a number
78  for (; start_iter != end_iter; ++start_iter) {
79  if ((*start_iter < '0') || (*start_iter > '9')) return false;
80  }
81 
82  return true;
83  }
84 
85 
86  // determines whether a string corresponds to an integer
87  bool DBCell::isReal(const std::string& str) {
88  if (str.empty()) return false;
89 
90  // trim the string
91  auto start_iter = str.begin() + str.find_first_not_of(" \t");
92  auto end_iter = str.begin() + str.find_last_not_of(" \t\r\n") + 1;
93 
94  if (start_iter == end_iter) return false;
95 
96  // check wether we have a number
97  bool has_dot = false;
98  bool has_exponent = false;
99  bool has_digit = false;
100  bool has_negation = false;
101  for (; start_iter != end_iter; ++start_iter) {
102  if (*start_iter == '-') {
103  if (has_negation) return false;
104  } else if (*start_iter == '.') {
105  if (has_dot || has_exponent) return false;
106  has_dot = true;
107  } else if ((*start_iter == 'e') || (*start_iter == 'E')) {
108  if (has_exponent || !has_digit) return false;
109  has_exponent = true;
110  has_negation = false;
111  } else if ((*start_iter < '0') || (*start_iter > '9'))
112  return false;
113  else
114  has_digit = true;
115  }
116 
117  return true;
118  }
119 
120 
121  // try to convert the content of the DBCell into another type
122  bool DBCell::convertType(const EltType new_type) {
123  if (new_type == __type) return true;
124  switch (new_type) {
125  // ===================================
126  case EltType::REAL:
127  switch (__type) {
128  case EltType::INTEGER:
129  __val_real = float(__val_integer);
130  __type = EltType::REAL;
131  return true;
132 
133  case EltType::STRING:
134  try {
135  const std::string& str = __strings().first(__val_index);
136  if (!isReal(str)) return false;
137  __val_real = std::stof(str);
138  __type = EltType::REAL;
139  return true;
140  } catch (std::invalid_argument&) { return false; }
141 
142  case EltType::MISSING: return false;
143 
144  default:
145  GUM_ERROR(NotImplementedYet,
146  "type not supported by DBCell convertType");
147  }
148 
149  // ===================================
150  case EltType::INTEGER:
151  switch (__type) {
152  case EltType::REAL: {
153  const int nb = int(__val_real);
154  if (nb == __val_real) {
155  __val_integer = nb;
156  __type = EltType::INTEGER;
157  return true;
158  } else
159  return false;
160  }
161 
162  case EltType::STRING:
163  try {
164  const std::string& str = __strings().first(__val_index);
165  if (!isInteger(str)) return false;
166  __val_integer = std::stoi(str);
167  __type = EltType::INTEGER;
168  return true;
169  } catch (std::invalid_argument&) { return false; }
170 
171  case EltType::MISSING: return false;
172 
173  default:
174  GUM_ERROR(NotImplementedYet,
175  "type not supported by DBCell convertType");
176  }
177 
178  // ===================================
179  case EltType::STRING:
180  switch (__type) {
181  case EltType::REAL: {
182  char buffer[100];
183  sprintf(buffer, "%g", __val_real);
184  const std::string str(buffer);
185  if (!__strings().existsFirst(str)) {
186  __strings().insert(str, __string_max_index);
187  __val_index = __string_max_index;
188  ++__string_max_index;
189  } else {
190  __val_index = __strings().second(str);
191  }
192  }
193  __type = EltType::STRING;
194  return true;
195 
196  case EltType::INTEGER: {
197  const std::string str = std::to_string(__val_integer);
198  if (!__strings().existsFirst(str)) {
199  __strings().insert(str, __string_max_index);
200  __val_index = __string_max_index;
201  ++__string_max_index;
202  } else {
203  __val_index = __strings().second(str);
204  }
205  }
206  __type = EltType::STRING;
207  return true;
208 
209  case EltType::MISSING: return false;
210 
211  default:
212  GUM_ERROR(NotImplementedYet,
213  "type not supported by DBCell convertType");
214  }
215 
216  // ===================================
217  case EltType::MISSING: __type = EltType::MISSING; return true;
218 
219  default:
220  GUM_ERROR(NotImplementedYet, "type not supported by DBCell convertType");
221  }
222 
223  return false;
224  }
225 
226 
227  // raises an appropriate exception when encountering a type error
228  std::string DBCell::__typeErrorMsg(const std::string& true_type) const {
229  std::stringstream str;
230  switch (__type) {
231  case EltType::REAL:
232  str << "The DBCell contains a real number instead of " << true_type;
233  break;
234 
235  case EltType::INTEGER:
236  str << "The DBCell contains an integer instead of " << true_type;
237  break;
238 
239  case EltType::STRING:
240  str << "The DBCell contains a string instead of " << true_type;
241  break;
242 
243  case EltType::MISSING:
244  str << "The DBCell contains a missing value instead of " << true_type;
245  break;
246 
247  default: GUM_ERROR(NotImplementedYet, "DBCell type not implemented yet");
248  }
249 
250  return str.str();
251  }
252 
253  } /* namespace learning */
254 
255 } /* namespace gum */
256 
257 #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
The inlined implementation of DBCells.
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
The class representing the original values of the cells of databases.
std::string to_string(const Formula &f)
Definition: formula_inl.h:479
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:72
#define GUM_ERROR(type, msg)
Definition: exceptions.h:52