Main MRPT website > C++ reference for MRPT 1.9.9
CSimpleDatabase.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "db-precomp.h" // Precompiled headers
11 
14 #include <mrpt/system/os.h>
15 
16 using namespace mrpt::db;
17 using namespace mrpt::system;
18 using namespace std;
19 
20 #undef _UNICODE // JLBC
21 
22 #include "xmlparser/xmlParser.h"
23 
24 #include <iostream>
25 
26 // This must be added to any CSerializable class implementation file.
29 
30 uint8_t CSimpleDatabase::serializeGetVersion() const { return 0; }
32 {
33  // Save all tables in DB:
34  uint32_t n = (uint32_t)m_tables.size();
35  out << n;
36 
37  for (const_iterator i = m_tables.begin(); i != m_tables.end(); ++i)
38  {
39  out << i->first; //.c_str();
40  out << *i->second;
41  }
42 }
45 {
46  switch (version)
47  {
48  case 0:
49  {
50  std::string aux;
51 
52  // Clear existing tables:
53  clear();
54 
55  // Load all tables in DB:
56  uint32_t n;
57  in >> n;
58 
59  for (uint32_t i = 0; i < n; i++)
60  {
61  in >> aux;
62 
64  mrpt::make_aligned_shared<CSimpleDatabaseTable>();
65  in >> (*newTb);
66 
67  m_tables[aux] = newTb;
68  }
69  }
70  break;
71  default:
73  };
74 }
75 
78 {
79  uint32_t row, col, nRec = (uint32_t)getRecordCount(),
80  nFie = (uint32_t)fieldsCount();
81 
82  out << nRec << nFie;
83 
84  for (col = 0; col < nFie; col++) out << field_names[col]; //.c_str();
85 
86  for (row = 0; row < nRec; row++)
87  for (col = 0; col < nFie; col++) out << data[row][col]; //.c_str();
88 }
91 {
92  switch (version)
93  {
94  case 0:
95  {
96  uint32_t row, col, nRec, nFie;
97  // char str[10000];
98 
99  in >> nRec >> nFie;
100 
101  data.resize(nRec);
102  field_names.resize(nFie);
103 
104  for (col = 0; col < nFie; col++) in >> field_names[col];
105 
106  for (row = 0; row < nRec; row++)
107  {
108  data[row].resize(nFie);
109 
110  for (col = 0; col < nFie; col++) in >> data[row][col];
111  }
112  }
113  break;
114  default:
116  };
117 }
118 
119 /*---------------------------------------------------------------
120  Constructor
121  ---------------------------------------------------------------*/
123 /*---------------------------------------------------------------
124  Destructor
125  ---------------------------------------------------------------*/
127 /*---------------------------------------------------------------
128  Clear the DB
129  ---------------------------------------------------------------*/
130 void CSimpleDatabase::clear() { m_tables.clear(); }
131 /*---------------------------------------------------------------
132  getTable
133  ---------------------------------------------------------------*/
135  const std::string& tableName)
136 {
137  MRPT_START
138 
139  iterator it = m_tables.find(tableName);
140  if (it != m_tables.end()) return it->second;
141 
142  THROW_EXCEPTION_FMT("Table '%s' was not found", tableName.c_str())
143 
144  MRPT_END
145 }
146 
147 /*---------------------------------------------------------------
148  getTable
149  ---------------------------------------------------------------*/
151 {
152  MRPT_START
153 
154  ASSERT_(tableIndex < tablesCount());
155  iterator it = m_tables.begin();
156  std::advance(it, tableIndex);
157  return it->second;
158 
159  MRPT_END
160 }
161 
162 /*---------------------------------------------------------------
163  tablesCount
164  ---------------------------------------------------------------*/
165 size_t CSimpleDatabase::tablesCount() const { return m_tables.size(); }
166 /*---------------------------------------------------------------
167  tablesName
168  ---------------------------------------------------------------*/
169 string CSimpleDatabase::tablesName(size_t tableIndex) const
170 {
171  MRPT_START
172 
173  ASSERT_(tableIndex < tablesCount());
174  const_iterator it = m_tables.begin();
175  std::advance(it, tableIndex);
176  return it->first;
177 
178  MRPT_END
179 }
180 
181 /*---------------------------------------------------------------
182  createTable
183  ---------------------------------------------------------------*/
185 {
187  mrpt::make_aligned_shared<CSimpleDatabaseTable>();
188  m_tables[name] = table;
189  return table;
190 }
191 
192 /*---------------------------------------------------------------
193  Constructor
194  ---------------------------------------------------------------*/
196 /*---------------------------------------------------------------
197  Destructor
198  ---------------------------------------------------------------*/
200 /*---------------------------------------------------------------
201  fieldsCount
202  ---------------------------------------------------------------*/
203 size_t CSimpleDatabaseTable::fieldsCount() const { return field_names.size(); }
204 /*---------------------------------------------------------------
205  addField
206  ---------------------------------------------------------------*/
207 void CSimpleDatabaseTable::addField(const char* fieldName)
208 {
209  field_names.push_back(string(fieldName));
210  data.clear();
211 }
212 
213 /*---------------------------------------------------------------
214  getFieldName
215  ---------------------------------------------------------------*/
216 string CSimpleDatabaseTable::getFieldName(size_t fieldIndex) const
217 {
218  MRPT_START
219 
220  ASSERT_(fieldIndex < fieldsCount());
221  return field_names[fieldIndex];
222 
223  MRPT_END
224 }
225 
226 /*---------------------------------------------------------------
227  fieldIndex
228  ---------------------------------------------------------------*/
229 size_t CSimpleDatabaseTable::fieldIndex(const char* fieldName) const
230 {
231  MRPT_START
232 
233  size_t i, n = field_names.size();
234 
235  for (i = 0; i < n; i++)
236  if (!os::_strcmpi(fieldName, field_names[i].c_str())) return (int)i;
237 
238  THROW_EXCEPTION_FMT("fieldIndex: Field '%s' not found", fieldName);
239 
240  MRPT_END
241 }
242 
243 /*---------------------------------------------------------------
244  getRecordCount
245  ---------------------------------------------------------------*/
246 size_t CSimpleDatabaseTable::getRecordCount() const { return data.size(); }
247 /*---------------------------------------------------------------
248  get
249  ---------------------------------------------------------------*/
250 string CSimpleDatabaseTable::get(size_t recordIndex, string field) const
251 {
252  MRPT_START
253  ASSERT_(recordIndex < getRecordCount());
254  return data[recordIndex][fieldIndex(field.c_str())];
255  MRPT_END
256 }
257 
258 /*---------------------------------------------------------------
259  get
260  ---------------------------------------------------------------*/
261 string CSimpleDatabaseTable::get(size_t recordIndex, size_t fieldIndex) const
262 {
263  MRPT_START
264  ASSERT_(recordIndex < getRecordCount());
265  ASSERT_(fieldIndex < fieldsCount());
266  return data[recordIndex][fieldIndex];
267  MRPT_END
268 }
269 
270 /*---------------------------------------------------------------
271  set
272  ---------------------------------------------------------------*/
273 void CSimpleDatabaseTable::set(size_t recordIndex, string field, string value)
274 {
275  MRPT_START
276 
277  ASSERT_(recordIndex < getRecordCount());
278  data[recordIndex][fieldIndex(field.c_str())] = value;
279 
280  MRPT_END
281 }
282 
283 /*---------------------------------------------------------------
284  set
285  ---------------------------------------------------------------*/
287  size_t recordIndex, size_t fieldIndex, string value)
288 {
289  MRPT_START
290 
291  ASSERT_(recordIndex < getRecordCount());
292  ASSERT_(fieldIndex < fieldsCount());
293  data[recordIndex][fieldIndex] = value;
294 
295  MRPT_END
296 }
297 
298 /*---------------------------------------------------------------
299  query
300  ---------------------------------------------------------------*/
301 int CSimpleDatabaseTable::query(string field, string value) const
302 {
303  int fieldInd, i, n = (uint32_t)getRecordCount();
304 
305  try
306  {
307  fieldInd = (uint32_t)fieldIndex(field.c_str());
308  }
309  catch (...)
310  {
311  return -1;
312  }
313 
314  for (i = 0; i < n; i++)
315  {
316  if (!os::_strcmpi(value.c_str(), data[i][fieldInd].c_str())) return i;
317  }
318 
319  // Do not found:
320  return -1;
321 }
322 
323 /*---------------------------------------------------------------
324  appendRecord
325  ---------------------------------------------------------------*/
327 {
328  std::vector<std::string> new_rec;
329 
330  new_rec.resize(fieldsCount());
331  data.push_back(new_rec);
332 
333  return data.size() - 1;
334 }
335 
336 /*---------------------------------------------------------------
337  deleteRecord
338  ---------------------------------------------------------------*/
339 void CSimpleDatabaseTable::deleteRecord(size_t recordIndex)
340 {
341  MRPT_START
342  ASSERT_(recordIndex < getRecordCount());
343  std::vector<std::vector<std::string>>::iterator it = data.begin();
344  std::advance(it, recordIndex);
345  data.erase(it);
346 
347  MRPT_END
348 }
349 
350 /*---------------------------------------------------------------
351  saveAsXML
352  ---------------------------------------------------------------*/
353 bool CSimpleDatabase::saveAsXML(const string& fileName) const
354 {
355  try
356  {
357  // Root node:
358  XMLNode rootXml =
359  XMLNode::createXMLTopNode("CSimpleDatabase-MRPT-Object");
360 
361  // For each table:
362  for (const_iterator it = m_tables.begin(); it != m_tables.end(); ++it)
363  {
364  CSimpleDatabaseTable::Ptr t = it->second;
365  XMLNode tabNod = rootXml.addChild("table");
366  tabNod.addAttribute("name", it->first.c_str());
367 
368  // Add field descriptions:
369  // ------------------------
370  size_t nFields = t->fieldsCount();
371  size_t nRecs = t->getRecordCount();
372 
373  XMLNode fNod = tabNod.addChild("fields");
374  for (unsigned int i = 0; i < nFields; i++)
375  fNod.addChild(t->getFieldName(i).c_str());
376 
377  // Add record contents:
378  // ------------------------
379  for (unsigned int i = 0; i < nRecs; i++)
380  {
381  XMLNode recNod = tabNod.addChild("record");
382  for (size_t j = 0; j < nFields; j++)
383  {
384  XMLNode recContent =
385  recNod.addChild(t->getFieldName(j).c_str());
386  recContent.addText(t->get(i, j).c_str());
387  }
388  }
389 
390  } // end for each table.
391 
392  rootXml.writeToFile(fileName.c_str());
393 
394  return true; // Ok
395  }
396  catch (exception& e)
397  {
398  cerr << "[CSimpleDatabase::saveAsXML] Exception ignored:" << endl
399  << e.what() << endl;
400  return false; // Errors found
401  }
402  catch (...)
403  {
404  return false; // Errors found
405  }
406 }
407 
408 /*---------------------------------------------------------------
409  loadFromXML
410  ---------------------------------------------------------------*/
411 bool CSimpleDatabase::loadFromXML(const string& fileName)
412 {
413  try
414  {
416  XMLNode root = XMLNode::parseFile(fileName.c_str(), nullptr, &results);
417 
418  if (results.error != eXMLErrorNone)
419  {
420  cerr << "[CSimpleDatabase::loadFromXML] Error loading XML file: "
421  << XMLNode::getError(results.error) << " at line "
422  << results.nLine << ":" << results.nColumn << endl;
423  return false;
424  }
425 
426  root = root.getChildNode("CSimpleDatabase-MRPT-Object");
427  if (root.isEmpty())
428  {
429  cerr << "[CSimpleDatabase::loadFromXML] Loaded XML file does not "
430  "have a 'CSimpleDatabase-MRPT-Object' tag";
431  return false;
432  }
433 
434  // Clear previous contents:
435  clear();
436 
437  // Get tables:
438  size_t i, j, nTables = root.nChildNode("table");
439  for (i = 0; i < nTables; i++)
440  {
441  XMLNode tabNod = root.getChildNode("table", (int)i);
442  ASSERT_(!tabNod.isEmpty());
443  // Create table:
445  createTable(tabNod.getAttribute("name"));
446 
447  // Create fields:
448  XMLNode fNod = tabNod.getChildNode("fields");
449  ASSERT_(!fNod.isEmpty());
450  size_t nFields = fNod.nChildNode();
451  for (j = 0; j < nFields; j++)
452  {
453  t->addField(fNod.getChildNode((int)j).getName());
454  } // end for each field
455 
456  // Add record data:
457  size_t nRecs = tabNod.nChildNode("record");
458  for (size_t k = 0; k < nRecs; k++)
459  {
460  size_t recIdx = t->appendRecord();
461 
462  XMLNode recNod = tabNod.getChildNode("record", (int)k);
463  ASSERT_(!recNod.isEmpty());
464  for (j = 0; j < nFields; j++)
465  {
466  XMLCSTR str =
467  recNod.getChildNode(t->getFieldName(j).c_str())
468  .getText();
469  t->set(recIdx, j, str != nullptr ? string(str) : string());
470  }
471 
472  } // end for each record
473 
474  } // for each table
475 
476  return true; // Ok
477  }
478  catch (exception& e)
479  {
480  cerr << "[CSimpleDatabase::loadFromXML] Exception ignored:" << endl
481  << e.what() << endl;
482  return false; // Errors found
483  }
484  catch (...)
485  {
486  return false; // Errors found
487  }
488 }
489 
490 /*---------------------------------------------------------------
491  dropTable
492  ---------------------------------------------------------------*/
494 {
495  MRPT_START
496 
497  iterator it = m_tables.find(tableName);
498  if (it == m_tables.end())
499  THROW_EXCEPTION_FMT("Table '%s' was not found", tableName.c_str())
500 
501  m_tables.erase(it);
502 
503  MRPT_END
504 }
505 
506 /*---------------------------------------------------------------
507  renameTable
508  ---------------------------------------------------------------*/
510  const std::string& tableName, const std::string& newTableName)
511 {
512  MRPT_START
513 
514  if (tableName == newTableName) return; // done
515 
516  iterator it = m_tables.find(tableName);
517  if (it == m_tables.end())
518  THROW_EXCEPTION_FMT("Table '%s' was not found", tableName.c_str())
519 
520  {
521  iterator itNew = m_tables.find(newTableName);
522  if (itNew != m_tables.end())
524  "A table with the name '%s' already exists",
525  newTableName.c_str())
526  }
527 
528  CSimpleDatabaseTable::Ptr tb = it->second;
529 
530  m_tables.erase(it);
531  m_tables[newTableName] = tb;
532 
533  MRPT_END
534 }
Scalar * iterator
Definition: eigen_plugins.h:26
CSimpleDatabaseTable()
Default constructor.
#define MRPT_START
Definition: exceptions.h:262
GLdouble GLdouble t
Definition: glext.h:3689
std::map< std::string, CSimpleDatabaseTable::Ptr >::const_iterator const_iterator
virtual ~CSimpleDatabase()
Destructor.
bool saveAsXML(const std::string &fileName) const
Saves this database as a XML file.
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
Definition: math_frwds.h:25
Main Class representing a XML node.
Definition: xmlParser.h:313
void serializeTo(mrpt::serialization::CArchive &out) const override
Pure virtual method for writing (serializing) to an abstract archive.
int query(std::string field, std::string value) const
Executes a query in the table, returning the record index which a given field has a given value...
size_t fieldsCount() const
Get the count of fields.
XMLError writeToFile(XMLCSTR filename, const char *encoding=nullptr, char nFormat=1) const
Save the content of an xmlNode inside a file.
Definition: xmlParser.cpp:806
This class impements a very simple database system.
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
GLenum GLsizei n
Definition: glext.h:5074
size_t tablesCount() const
Returns the tables count in the DB.
char isEmpty() const
is this node Empty?
Definition: xmlParser.cpp:3417
std::string getFieldName(size_t fieldIndex) const
Get the name of a field by its index.
GLenum GLsizei GLenum GLenum const GLvoid * table
Definition: glext.h:3531
static XMLNode createXMLTopNode(XMLCSTR lpszName, char isDeclaration=FALSE)
Create the top node of an XMLNode structure.
Definition: xmlParser.cpp:1414
STL namespace.
CSimpleDatabaseTable::Ptr createTable(const std::string &name)
Creates a new table in the DB, initially empty.
#define XMLCSTR
Definition: xmlParser.h:226
size_t fieldIndex(const char *fieldName) const
Get the index for a given field name.
void serializeFrom(mrpt::serialization::CArchive &in, uint8_t serial_version) override
Pure virtual method for reading (deserializing) from an abstract archive.
std::string tablesName(size_t tableIndex) const
Returns the tables names in the DB.
void addField(const char *fieldName)
Add a new field to the table.
unsigned char uint8_t
Definition: rptypes.h:41
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
Definition: exceptions.h:90
static XMLCSTR getError(XMLError error)
this gives you a
Definition: xmlParser.cpp:83
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:113
XMLAttribute getAttribute(int i=0) const
return ith attribute
Definition: xmlParser.cpp:3382
map< string, CVectorDouble > results
std::map< std::string, CSimpleDatabaseTable::Ptr >::iterator iterator
void dropTable(const std::string &tableName)
Deletes the given table.
CSimpleDatabase()
Default constructor.
void clear()
Clears the DB.
size_t appendRecord()
Append a new and empty record at the end of the table, and return the index of the newly added record...
virtual ~CSimpleDatabaseTable()
Destructor.
void deleteRecord(size_t recordIndex)
Delete the record at the given index.
GLsizei const GLchar ** string
Definition: glext.h:4101
CSimpleDatabaseTable::Ptr getTable(const std::string &tableName)
Returns the table with the indicated name.
static XMLNode parseFile(XMLCSTR filename, XMLCSTR tag=nullptr, XMLResults *pResults=nullptr)
Parse an XML file and return the root of a XMLNode tree representing the file.
Definition: xmlParser.cpp:2283
XMLCSTR addText(XMLCSTR lpszValue, XMLElementPosition pos=-1)
Add a new text content.
Definition: xmlParser.cpp:3437
Virtual base class for "archives": classes abstracting I/O streams.
Definition: CArchive.h:48
std::string get(size_t recordIndex, std::string field) const
Returns the cell content of the record indicates by its index, and the field indicated in "field"...
GLenum GLenum GLvoid * row
Definition: glext.h:3576
#define MRPT_END
Definition: exceptions.h:266
void set(size_t recordIndex, std::string field, std::string value)
Sets the cell content of the record indicates by its index, and the field indicated in "field"...
GLuint in
Definition: glext.h:7274
GLuint const GLchar * name
Definition: glext.h:4054
XMLNode addChild(XMLCSTR lpszName, char isDeclaration=FALSE, XMLElementPosition pos=-1)
Add a new child node.
Definition: xmlParser.cpp:3419
This class implements the tables of databases.
GLsizei const GLfloat * value
Definition: glext.h:4117
uint8_t serializeGetVersion() const override
Must return the current versioning number of the object.
void renameTable(const std::string &tableName, const std::string &newTableName)
Changes the name of a given table.
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
Definition: exceptions.h:43
unsigned __int32 uint32_t
Definition: rptypes.h:47
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3546
void clear()
Clear the contents of this container.
Definition: ts_hash_map.h:188
void serializeFrom(mrpt::serialization::CArchive &in, uint8_t serial_version) override
Pure virtual method for reading (deserializing) from an abstract archive.
size_t getRecordCount() const
Get the records count in the table.
bool loadFromXML(const std::string &fileName)
Loads the content of this database from a a XML file.
int nChildNode(XMLCSTR name) const
return the number of child node with specific name
Definition: xmlParser.cpp:3097
void serializeTo(mrpt::serialization::CArchive &out) const override
Pure virtual method for writing (serializing) to an abstract archive.
Structure used to obtain error details if the parse fails.
Definition: xmlParser.h:274
XMLNode getChildNode(int i=0) const
return ith child node
Definition: xmlParser.cpp:3402
XMLAttribute * addAttribute(XMLCSTR lpszName, XMLCSTR lpszValuev)
it will be detached from it&#39;s parents before being attached to the current XMLNode ...
Definition: xmlParser.cpp:3429
int _strcmpi(const char *str1, const char *str2) noexcept
An OS-independent version of strcmpi.
Definition: os.cpp:320



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at lun oct 28 00:14:14 CET 2019