Main MRPT website > C++ reference for MRPT 1.5.6
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-2017, 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 "base-precomp.h" // Precompiled headers
11 
13 #include <mrpt/utils/CStream.h>
14 #include <mrpt/system/os.h>
15 
16 using namespace mrpt::utils;
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 /*---------------------------------------------------------------
31  writeToStream
32  ---------------------------------------------------------------*/
33 void CSimpleDatabase::writeToStream(mrpt::utils::CStream &out, int *out_Version) const
34 {
35  if (out_Version)
36  *out_Version = 0;
37  else
38  {
39  // Save all tables in DB:
40  uint32_t n = (uint32_t)m_tables.size();
41  out << n;
42 
43  for (const_iterator i=m_tables.begin();i!=m_tables.end();++i)
44  {
45  out << i->first; //.c_str();
46  out << *i->second;
47  }
48  }
49 }
50 /*---------------------------------------------------------------
51  readFromStream
52  ---------------------------------------------------------------*/
54 {
55  switch (version)
56  {
57  case 0:
58  {
59  std::string aux;
60 
61  // Clear existing tables:
62  clear();
63 
64  // Load all tables in DB:
65  uint32_t n;
66  in >> n;
67 
68  for (uint32_t i=0;i<n;i++)
69  {
70  in >> aux;
71 
72  CSimpleDatabaseTablePtr newTb = CSimpleDatabaseTable::Create();
73  in >> (*newTb);
74 
75  m_tables[aux] = newTb;
76  }
77  }
78  break;
79  default:
81 
82  };
83 }
84 
85 /*---------------------------------------------------------------
86  writeToStream
87  ---------------------------------------------------------------*/
89 {
90  if (out_Version)
91  *out_Version = 0;
92  else
93  {
94  uint32_t row,col,nRec = (uint32_t) getRecordCount(), nFie=(uint32_t) fieldsCount();
95 
96  out << nRec << nFie;
97 
98  for (col=0;col<nFie;col++)
99  out << field_names[col]; //.c_str();
100 
101  for (row=0;row<nRec;row++)
102  for (col=0;col<nFie;col++)
103  out << data[row][col]; //.c_str();
104  }
105 }
106 /*---------------------------------------------------------------
107  readFromStream
108  ---------------------------------------------------------------*/
110 {
111  switch (version)
112  {
113  case 0:
114  {
115  uint32_t row,col,nRec,nFie;
116  //char str[10000];
117 
118  in >> nRec >> nFie;
119 
120  data.resize(nRec);
121  field_names.resize(nFie);
122 
123  for (col=0;col<nFie;col++)
124  in >> field_names[col];
125 
126  for (row=0;row<nRec;row++)
127  {
128  data[row].resize(nFie);
129 
130  for (col=0;col<nFie;col++)
131  in >> data[row][col];
132  }
133  }
134  break;
135  default:
137 
138  };
139 }
140 
141 /*---------------------------------------------------------------
142  Constructor
143  ---------------------------------------------------------------*/
145 {
146 
147 }
148 
149 /*---------------------------------------------------------------
150  Destructor
151  ---------------------------------------------------------------*/
153 {
154  clear();
155 }
156 
157 /*---------------------------------------------------------------
158  Clear the DB
159  ---------------------------------------------------------------*/
161 {
162  m_tables.clear();
163 }
164 
165 /*---------------------------------------------------------------
166  getTable
167  ---------------------------------------------------------------*/
168 CSimpleDatabaseTablePtr CSimpleDatabase::getTable(const std::string &tableName)
169 {
170  MRPT_START
171 
172  iterator it = m_tables.find(tableName);
173  if (it!=m_tables.end())
174  return it->second;
175 
176  THROW_EXCEPTION_FMT("Table '%s' was not found",tableName.c_str())
177 
178  MRPT_END
179 }
180 
181 /*---------------------------------------------------------------
182  getTable
183  ---------------------------------------------------------------*/
184 CSimpleDatabaseTablePtr CSimpleDatabase::getTable(size_t tableIndex)
185 {
186  MRPT_START
187 
188  ASSERT_(tableIndex<tablesCount() )
189 
190  iterator it = m_tables.begin();
191  std::advance(it,tableIndex);
192  return it->second;
193 
194  MRPT_END
195 }
196 
197 /*---------------------------------------------------------------
198  tablesCount
199  ---------------------------------------------------------------*/
201 {
202  return m_tables.size();
203 }
204 
205 /*---------------------------------------------------------------
206  tablesName
207  ---------------------------------------------------------------*/
208 string CSimpleDatabase::tablesName(size_t tableIndex) const
209 {
210  MRPT_START
211 
212  ASSERT_( tableIndex<tablesCount() )
213  const_iterator it = m_tables.begin();
214  std::advance(it,tableIndex);
215  return it->first;
216 
217  MRPT_END
218 }
219 
220 /*---------------------------------------------------------------
221  createTable
222  ---------------------------------------------------------------*/
223 CSimpleDatabaseTablePtr CSimpleDatabase::createTable(const string &name)
224 {
225  CSimpleDatabaseTablePtr table = CSimpleDatabaseTable::Create();
226  m_tables[name] = table;
227  return table;
228 }
229 
230 /*---------------------------------------------------------------
231  Constructor
232  ---------------------------------------------------------------*/
234 {
235 }
236 
237 /*---------------------------------------------------------------
238  Destructor
239  ---------------------------------------------------------------*/
241 {
242 }
243 
244 /*---------------------------------------------------------------
245  fieldsCount
246  ---------------------------------------------------------------*/
248 {
249  return field_names.size();
250 }
251 
252 /*---------------------------------------------------------------
253  addField
254  ---------------------------------------------------------------*/
255 void CSimpleDatabaseTable::addField(const char *fieldName)
256 {
257  field_names.push_back(string(fieldName));
258  data.clear();
259 }
260 
261 /*---------------------------------------------------------------
262  getFieldName
263  ---------------------------------------------------------------*/
264 string CSimpleDatabaseTable::getFieldName(size_t fieldIndex) const
265 {
266  MRPT_START
267 
268  ASSERT_( fieldIndex<fieldsCount() );
269  return field_names[fieldIndex];
270 
271  MRPT_END
272 }
273 
274 /*---------------------------------------------------------------
275  fieldIndex
276  ---------------------------------------------------------------*/
277 size_t CSimpleDatabaseTable::fieldIndex(const char *fieldName) const
278 {
279  MRPT_START
280 
281  size_t i,n = field_names.size();
282 
283  for (i=0;i<n;i++)
284  if (!os::_strcmpi(fieldName,field_names[i].c_str()))
285  return (int)i;
286 
287  THROW_EXCEPTION_FMT("fieldIndex: Field '%s' not found",fieldName);
288 
289  MRPT_END
290 }
291 
292 /*---------------------------------------------------------------
293  getRecordCount
294  ---------------------------------------------------------------*/
296 {
297  return data.size();
298 }
299 
300 /*---------------------------------------------------------------
301  get
302  ---------------------------------------------------------------*/
304  size_t recordIndex,
305  string field ) const
306 {
307  MRPT_START
308  ASSERT_(recordIndex<getRecordCount());
309  return data[recordIndex][fieldIndex(field.c_str())];
310  MRPT_END
311 }
312 
313 /*---------------------------------------------------------------
314  get
315  ---------------------------------------------------------------*/
317  size_t recordIndex,
318  size_t fieldIndex ) const
319 {
320  MRPT_START
321  ASSERT_(recordIndex<getRecordCount());
322  ASSERT_(fieldIndex<fieldsCount() );
323  return data[recordIndex][fieldIndex];
324  MRPT_END
325 }
326 
327 /*---------------------------------------------------------------
328  set
329  ---------------------------------------------------------------*/
331  size_t recordIndex,
332  string field,
333  string value)
334 {
335  MRPT_START
336 
337  ASSERT_(recordIndex<getRecordCount());
338  data[recordIndex][fieldIndex(field.c_str())]=value;
339 
340  MRPT_END
341 }
342 
343 /*---------------------------------------------------------------
344  set
345  ---------------------------------------------------------------*/
347  size_t recordIndex,
348  size_t fieldIndex,
349  string value)
350 {
351  MRPT_START
352 
353  ASSERT_(recordIndex<getRecordCount());
354  ASSERT_(fieldIndex<fieldsCount() );
355  data[recordIndex][fieldIndex]=value;
356 
357  MRPT_END
358 }
359 
360 /*---------------------------------------------------------------
361  query
362  ---------------------------------------------------------------*/
364  string field,
365  string value ) const
366 {
367  int fieldInd,i,n = (uint32_t) getRecordCount();
368 
369  try
370  {
371  fieldInd = (uint32_t) fieldIndex(field.c_str());
372  }
373  catch (...)
374  {
375  return -1;
376  }
377 
378  for (i=0;i<n;i++)
379  {
380  if (!os::_strcmpi(value.c_str(),data[i][fieldInd].c_str()))
381  return i;
382  }
383 
384  // Do not found:
385  return -1;
386 }
387 
388 /*---------------------------------------------------------------
389  appendRecord
390  ---------------------------------------------------------------*/
392 {
393  vector_string new_rec;
394 
395  new_rec.resize( fieldsCount() );
396  data.push_back( new_rec );
397 
398  return data.size()-1;
399 }
400 
401 /*---------------------------------------------------------------
402  deleteRecord
403  ---------------------------------------------------------------*/
404 void CSimpleDatabaseTable::deleteRecord(size_t recordIndex)
405 {
406  MRPT_START
407  ASSERT_(recordIndex<getRecordCount())
408 
410  std::advance(it,recordIndex);
411  data.erase(it);
412 
413  MRPT_END
414 }
415 
416 
417 /*---------------------------------------------------------------
418  saveAsXML
419  ---------------------------------------------------------------*/
420 bool CSimpleDatabase::saveAsXML( const string &fileName ) const
421 {
422  try
423  {
424  // Root node:
425  XMLNode rootXml = XMLNode::createXMLTopNode("CSimpleDatabase-MRPT-Object");
426 
427  // For each table:
428  for (const_iterator it=m_tables.begin();it!=m_tables.end();++it)
429  {
430  CSimpleDatabaseTablePtr t = it->second;
431  XMLNode tabNod = rootXml.addChild("table");
432  tabNod.addAttribute( "name", it->first.c_str() );
433 
434  // Add field descriptions:
435  // ------------------------
436  size_t nFields = t->fieldsCount();
437  size_t nRecs = t->getRecordCount();
438 
439  XMLNode fNod = tabNod.addChild("fields");
440  for (unsigned int i=0;i<nFields;i++)
441  fNod.addChild( t->getFieldName(i).c_str() );
442 
443  // Add record contents:
444  // ------------------------
445  for (unsigned int i=0;i<nRecs;i++)
446  {
447  XMLNode recNod = tabNod.addChild("record");
448  for (size_t j=0;j<nFields;j++)
449  {
450  XMLNode recContent = recNod.addChild( t->getFieldName(j).c_str() );
451  recContent.addText( t->get(i,j).c_str() );
452  }
453  }
454 
455  } // end for each table.
456 
457  rootXml.writeToFile( fileName.c_str() );
458 
459  return true; // Ok
460  }
461  catch (exception &e)
462  {
463  cerr << "[CSimpleDatabase::saveAsXML] Exception ignored:" << endl << e.what() << endl;
464  return false; // Errors found
465  }
466  catch (...)
467  {
468  return false; // Errors found
469  }
470 }
471 
472 
473 /*---------------------------------------------------------------
474  loadFromXML
475  ---------------------------------------------------------------*/
476 bool CSimpleDatabase::loadFromXML( const string &fileName )
477 {
478  try
479  {
480  XMLResults results;
481  XMLNode root = XMLNode::parseFile( fileName.c_str(), NULL, &results );
482 
483  if (results.error != eXMLErrorNone)
484  {
485  cerr << "[CSimpleDatabase::loadFromXML] Error loading XML file: " <<
486  XMLNode::getError( results.error ) << " at line " << results.nLine << ":" << results.nColumn << endl;
487  return false;
488  }
489 
490  root = root.getChildNode("CSimpleDatabase-MRPT-Object");
491  if (root.isEmpty())
492  {
493  cerr << "[CSimpleDatabase::loadFromXML] Loaded XML file does not have a 'CSimpleDatabase-MRPT-Object' tag";
494  return false;
495  }
496 
497  // Clear previous contents:
498  clear();
499 
500  // Get tables:
501  size_t i,j, nTables = root.nChildNode("table");
502  for (i=0;i<nTables;i++)
503  {
504  XMLNode tabNod = root.getChildNode("table",(int)i);
505  ASSERT_(!tabNod.isEmpty())
506 
507  // Create table:
508  CSimpleDatabaseTablePtr t = createTable( tabNod.getAttribute("name") );
509 
510  // Create fields:
511  XMLNode fNod = tabNod.getChildNode("fields");
512  ASSERT_(!fNod.isEmpty())
513 
514  size_t nFields = fNod.nChildNode();
515  for (j=0;j<nFields;j++)
516  {
517  t->addField( fNod.getChildNode((int)j).getName() );
518  } // end for each field
519 
520  // Add record data:
521  size_t nRecs = tabNod.nChildNode("record");
522  for (size_t k=0;k<nRecs;k++)
523  {
524  size_t recIdx = t->appendRecord();
525 
526  XMLNode recNod = tabNod.getChildNode("record",(int)k);
527  ASSERT_(!recNod.isEmpty())
528 
529  for (j=0;j<nFields;j++)
530  {
531  XMLCSTR str=recNod.getChildNode(t->getFieldName(j).c_str() ).getText();
532  t->set(recIdx,j, str!=NULL ? string(str) : string() );
533  }
534 
535  } // end for each record
536 
537  } // for each table
538 
539  return true; // Ok
540  }
541  catch (exception &e)
542  {
543  cerr << "[CSimpleDatabase::loadFromXML] Exception ignored:" << endl << e.what() << endl;
544  return false; // Errors found
545  }
546  catch (...)
547  {
548  return false; // Errors found
549  }
550 }
551 
552 /*---------------------------------------------------------------
553  dropTable
554  ---------------------------------------------------------------*/
556 {
557  MRPT_START
558 
559  iterator it = m_tables.find(tableName);
560  if (it==m_tables.end())
561  THROW_EXCEPTION_FMT("Table '%s' was not found",tableName.c_str())
562 
563  m_tables.erase(it);
564 
565 
566  MRPT_END
567 }
568 
569 /*---------------------------------------------------------------
570  renameTable
571  ---------------------------------------------------------------*/
573  const std::string &tableName,
574  const std::string &newTableName )
575 {
576  MRPT_START
577 
578  if (tableName==newTableName) return; // done
579 
580  iterator it = m_tables.find(tableName);
581  if (it==m_tables.end())
582  THROW_EXCEPTION_FMT("Table '%s' was not found",tableName.c_str())
583 
584  {
585  iterator itNew = m_tables.find(newTableName);
586  if (itNew !=m_tables.end())
587  THROW_EXCEPTION_FMT("A table with the name '%s' already exists",newTableName.c_str())
588  }
589 
590  CSimpleDatabaseTablePtr tb = it->second;
591 
592  m_tables.erase(it);
593  m_tables[newTableName] = tb;
594 
595 
596  MRPT_END
597 }
598 
599 
size_t fieldsCount() const
Get the count of fields.
void writeToStream(mrpt::utils::CStream &out, int *getVersion) const
Introduces a pure virtual method responsible for writing to a CStream.
GLenum GLsizei GLenum GLenum const GLvoid * table
Definition: glew.h:2878
GLenum GLenum GLvoid * row
Definition: glew.h:2903
void readFromStream(mrpt::utils::CStream &in, int version)
Introduces a pure virtual method responsible for loading from a CStream This can not be used directly...
void readFromStream(mrpt::utils::CStream &in, int version)
Introduces a pure virtual method responsible for loading from a CStream This can not be used directly...
size_t fieldIndex(const char *fieldName) const
Get the index for a given field name On field not found.
Main Class representing a XML node.
Definition: xmlParser.h:275
XMLNode getChildNode(int i=0) const
return ith child node
Definition: xmlParser.cpp:2535
int nColumn
Definition: xmlParser.h:245
The virtual base class which provides a unified interface for all persistent objects in MRPT...
Definition: CSerializable.h:39
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
void deleteRecord(size_t recordIndex)
Delete the record at the given index.
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
std::string getFieldName(size_t fieldIndex) const
Get the name of a field by its index On index out of bounds.
Scalar * iterator
Definition: eigen_plugins.h:23
bool loadFromXML(const std::string &fileName)
Loads the content of this database from a a XML file.
GLdouble GLdouble t
Definition: glew.h:1303
virtual ~CSimpleDatabase()
Destructor.
static XMLNode createXMLTopNode(XMLCSTR lpszName, char isDeclaration=FALSE)
Create the top node of an XMLNode structure.
Definition: xmlParser.cpp:1001
static CSimpleDatabaseTablePtr Create()
CSimpleDatabase()
Default constructor.
#define XMLCSTR
Definition: xmlParser.h:191
std::map< std::string, CSimpleDatabaseTablePtr >::const_iterator const_iterator
XMLAttribute getAttribute(int i=0) const
return ith attribute
Definition: xmlParser.cpp:2531
void clear()
Clear the contents of this container.
Definition: ts_hash_map.h:113
XMLError writeToFile(XMLCSTR filename, const char *encoding=NULL, char nFormat=1) const
Save the content of an xmlNode inside a file.
Definition: xmlParser.cpp:529
GLuint in
Definition: glew.h:7146
GLsizei const GLfloat * value
Definition: glew.h:1756
static XMLCSTR getError(XMLError error)
this gives you a user-friendly explanation of the parsing error
Definition: xmlParser.cpp:73
CSimpleDatabaseTable()
Default constructor.
void renameTable(const std::string &tableName, const std::string &newTableName)
Changes the name of a given table On table not found or new name already existed. ...
std::vector< std::string > vector_string
A type for passing a vector of strings.
Definition: types_simple.h:30
void addField(const char *fieldName)
Add a new field to the table.
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:38
This class implements the tables of databases.
std::map< std::string, CSimpleDatabaseTablePtr >::iterator iterator
GLsizei n
Definition: glew.h:5051
void dropTable(const std::string &tableName)
Deletes the given table.
#define MRPT_END
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
size_t tablesCount() const
Returns the tables count in the DB.
size_t getRecordCount() const
Get the records count in the table.
GLuint const GLchar * name
Definition: glew.h:1721
int version
Definition: mrpt_jpeglib.h:898
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
Definition: glew.h:1284
This class impements a very simple database system.
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"...
#define MRPT_START
XMLCSTR addText(XMLCSTR lpszValue, XMLElementPosition pos=-1)
Add a new text content.
Definition: xmlParser.cpp:2549
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.
GLsizei const GLcharARB ** string
Definition: glew.h:3293
std::string tablesName(size_t tableIndex) const
Returns the tables names in the DB.
int BASE_IMPEXP _strcmpi(const char *str1, const char *str2) MRPT_NO_THROWS
An OS-independent version of strcmpi.
Definition: os.cpp:320
char isEmpty() const
is this node Empty?
Definition: xmlParser.cpp:2538
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"...
CSimpleDatabaseTablePtr getTable(const std::string &tableName)
Returns the table with the indicated name On table not found.
CSimpleDatabaseTablePtr createTable(const std::string &name)
Creates a new table in the DB, initially empty.
#define ASSERT_(f)
int nChildNode(XMLCSTR name) const
return the number of child node with specific name
Definition: xmlParser.cpp:2329
bool saveAsXML(const std::string &fileName) const
Saves this database as a XML file.
enum XMLError error
Definition: xmlParser.h:244
static XMLNode parseFile(XMLCSTR filename, XMLCSTR tag=NULL, XMLResults *pResults=NULL)
Parse an XML file and return the root of a XMLNode tree representing the file.
Definition: xmlParser.cpp:1708
XMLNode addChild(XMLCSTR lpszName, char isDeclaration=FALSE, XMLElementPosition pos=-1)
Add a new child node.
Definition: xmlParser.cpp:2541
unsigned __int32 uint32_t
Definition: rptypes.h:49
void clear()
Clears the DB.
Structure used to obtain error details if the parse fails.
Definition: xmlParser.h:242
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...
XMLAttribute * addAttribute(XMLCSTR lpszName, XMLCSTR lpszValuev)
Add a new attribute.
Definition: xmlParser.cpp:2545



Page generated by Doxygen 1.8.6 for MRPT 1.5.6 Git: 4c65e84 Tue Apr 24 08:18:17 2018 +0200 at mar abr 24 08:26:17 CEST 2018