Main MRPT website > C++ reference for MRPT 1.5.7
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 tablesCount() const
Returns the tables count in the DB.
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
Definition: zip.h:16
GLdouble GLdouble t
Definition: glext.h:3610
std::string getFieldName(size_t fieldIndex) const
Get the name of a field by its index.
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...
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
Definition: math_frwds.h:29
Main Class representing a XML node.
Definition: xmlParser.h:275
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
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 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,...)
GLenum GLsizei n
Definition: glext.h:4618
Scalar * iterator
Definition: eigen_plugins.h:23
bool loadFromXML(const std::string &fileName)
Loads the content of this database from a a XML file.
virtual ~CSimpleDatabase()
Destructor.
char isEmpty() const
is this node Empty?
Definition: xmlParser.cpp:2538
GLenum GLsizei GLenum GLenum const GLvoid * table
Definition: glext.h:3513
size_t fieldsCount() const
Get the count of fields.
static XMLNode createXMLTopNode(XMLCSTR lpszName, char isDeclaration=FALSE)
Create the top node of an XMLNode structure.
Definition: xmlParser.cpp:1001
static CSimpleDatabaseTablePtr Create()
STL namespace.
CSimpleDatabase()
Default constructor.
#define XMLCSTR
Definition: xmlParser.h:191
std::map< std::string, CSimpleDatabaseTablePtr >::const_iterator const_iterator
bool saveAsXML(const std::string &fileName) const
Saves this database as a XML file.
void clear()
Clear the contents of this container.
Definition: ts_hash_map.h:113
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.
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
XMLAttribute getAttribute(int i=0) const
return ith attribute
Definition: xmlParser.cpp:2531
void writeToStream(mrpt::utils::CStream &out, int *getVersion) const
Introduces a pure virtual method responsible for writing to a CStream.
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.
std::string tablesName(size_t tableIndex) const
Returns the tables names in the DB.
int version
Definition: mrpt_jpeglib.h:898
GLsizei const GLchar ** string
Definition: glext.h:3919
size_t getRecordCount() const
Get the records count in the table.
This class impements a very simple database system.
#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...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
virtual ~CSimpleDatabaseTable()
Destructor.
int BASE_IMPEXP _strcmpi(const char *str1, const char *str2) MRPT_NO_THROWS
An OS-independent version of strcmpi.
Definition: os.cpp:320
GLenum GLenum GLvoid * row
Definition: glext.h:3533
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.
GLuint in
Definition: glext.h:6301
CSimpleDatabaseTablePtr createTable(const std::string &name)
Creates a new table in the DB, initially empty.
GLuint const GLchar * name
Definition: glext.h:3891
#define ASSERT_(f)
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
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...
enum XMLError error
Definition: xmlParser.h:244
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
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
GLsizei const GLfloat * value
Definition: glext.h:3929
unsigned __int32 uint32_t
Definition: rptypes.h:49
void clear()
Clears the DB.
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3520
size_t fieldIndex(const char *fieldName) const
Get the index for a given field name.
int nChildNode(XMLCSTR name) const
return the number of child node with specific name
Definition: xmlParser.cpp:2329
Structure used to obtain error details if the parse fails.
Definition: xmlParser.h:242
XMLNode getChildNode(int i=0) const
return ith child node
Definition: xmlParser.cpp:2535
XMLAttribute * addAttribute(XMLCSTR lpszName, XMLCSTR lpszValuev)
Add a new attribute.
Definition: xmlParser.cpp:2545



Page generated by Doxygen 1.8.14 for MRPT 1.5.7 Git: 5902e14cc Wed Apr 24 15:04:01 2019 +0200 at lun oct 28 01:39:17 CET 2019