[Positioner] Add class CSVStringReader

Code separated from CSVFileReader, which now inherits from both
TextFileReader and CSVStringReader.
This commit is contained in:
Matteo Cypriani 2013-05-16 16:59:15 -04:00
parent 559c884499
commit f55672ef01
5 changed files with 296 additions and 139 deletions

View File

@ -63,6 +63,7 @@ OBJ_LIST = \
topologyreadercsv.o \
textfilereader.o \
csvfilereader.o \
csvstringreader.o \
textfilewriter.o \
output.o \
outputterminal.o \
@ -200,7 +201,11 @@ $(OBJ_DIR)/resultlist.o: \
$(OBJ_DIR)/textfilereader.o: \
$(OBJ_DIR)/posexcept.o
$(OBJ_DIR)/csvfilereader.o: \
$(OBJ_DIR)/csvstringreader.o \
$(OBJ_DIR)/textfilereader.o
$(OBJ_DIR)/csvstringreader.o: \
$(OBJ_DIR)/point3d.o \
$(OBJ_DIR)/timestamp.o
$(OBJ_DIR)/textfilewriter.o: \
$(OBJ_DIR)/posexcept.o
$(OBJ_DIR)/inputmedium.o: \

View File

@ -49,16 +49,6 @@ using namespace boost ;
/* *** Constructors *** */
CSVFileReader::~CSVFileReader()
{
delete current_token ;
}
/* *** Operations *** */
@ -69,91 +59,11 @@ CSVFileReader::~CSVFileReader()
*/
bool CSVFileReader::next_line()
{
delete current_token ;
current_token = NULL ;
if (! read_nonblank_line(current_line))
return false ;
// Split read string into fields (semicolon-separated)
current_token = new tokenizer<escaped_list_separator<char> >(
current_line, escaped_list_separator<char>('\\', separator, '\"')) ;
set_str(current_line) ;
token_iterator = current_token->begin() ;
current_field_nb = 0 ;
return true ;
}
bool CSVFileReader::read_timestamp(Timestamp &t)
{
string timestamp_str ;
uint_fast32_t time_s, time_ns ;
if (! read_field(timestamp_str))
return false ;
tokenizer<escaped_list_separator<char> > tok(
timestamp_str, escaped_list_separator<char>('\\', '.', '\"')) ;
tokenizer<escaped_list_separator<char> >::const_iterator tok_iter =
tok.begin() ;
if (tok_iter == tok.end())
return false ;
try
{
time_s = lexical_cast<uint_fast32_t>(*tok_iter) ;
}
catch (bad_lexical_cast &e)
{
print_error_cast() ;
return false ;
}
++tok_iter ;
if (tok_iter == tok.end())
return false ;
try
{
time_ns = lexical_cast<uint_fast32_t>(*tok_iter) ;
}
catch (bad_lexical_cast &e)
{
print_error_cast() ;
return false ;
}
t = Timestamp(time_s, time_ns) ;
return true ;
}
bool CSVFileReader::read_point3d(Point3D &p)
{
float coord[3] ;
for (unsigned int i = 0 ; i < 3 ; ++i)
{
if (token_iterator == current_token->end())
return false ;
++current_field_nb ;
try
{
coord[i] = lexical_cast<float>(*token_iterator) ;
}
catch (bad_lexical_cast &e)
{
print_error_cast() ;
return false ;
}
++token_iterator ;
}
p.set_coordinates(coord) ;
return true ;
}

View File

@ -42,75 +42,30 @@
#ifndef _OWLPS_POSITIONING_CSVFILEREADER_HH_
#define _OWLPS_POSITIONING_CSVFILEREADER_HH_
class Point3D ;
#include "textfilereader.hh"
#include "timestamp.hh"
#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>
#include "csvstringreader.hh"
/// Reads a CSV file, line by line, field by field
class CSVFileReader: public TextFileReader
class CSVFileReader: public TextFileReader, public CSVStringReader
{
protected:
const char separator ;
std::string current_line ;
boost::tokenizer<boost::escaped_list_separator<char> > *current_token ;
boost::tokenizer<boost::escaped_list_separator<char> >::const_iterator
token_iterator ;
unsigned int current_field_nb ;
void print_error_cast(void) const ;
public:
CSVFileReader(const std::string &filename,
const char _separator = ';'):
TextFileReader(filename), separator(_separator),
current_token(NULL), current_field_nb(0) {}
TextFileReader(filename), CSVStringReader(_separator) {}
virtual ~CSVFileReader(void) ;
/** @name Operations */
//@{
/// Loads the first next non-blank line
bool next_line(void) ;
/// Reads the next field of the current line
template<class T> bool read_field(T &field) ;
/// Reads the next field that should be a Timestamp
bool read_timestamp(Timestamp &t) ;
/// Reads the next 3 fields that should form a Point3D
bool read_point3d(Point3D &p) ;
//@}
} ;
/* *** Operations *** */
template<class T>
inline bool CSVFileReader::read_field(T &field)
{
if (token_iterator == current_token->end())
return false ;
++current_field_nb ;
try
{
field = boost::lexical_cast<T>(*token_iterator) ;
}
catch (boost::bad_lexical_cast &e)
{
print_error_cast() ;
return false ;
}
++token_iterator ;
return true ;
}
#endif // _OWLPS_POSITIONING_CSVFILEREADER_HH_

View File

@ -0,0 +1,169 @@
/*
* This file is part of the Owl Positioning System (OwlPS).
* OwlPS is a project of the University of Franche-Comte
* (Université de Franche-Comté), France.
*
* Copyright © Université de Franche-Comté 2007-2012.
*
* Corresponding author: Matteo Cypriani <mcy@lm7.fr>
*
***********************************************************************
*
* This software is governed by the CeCILL license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/or redistribute the software under the terms of the CeCILL
* license as circulated by CEA, CNRS and INRIA at the following URL:
* http://www.cecill.info
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided
* only with a limited warranty and the software's authors, the holder
* of the economic rights, and the successive licensors have only
* limited liability.
*
* In this respect, the user's attention is drawn to the risks
* associated with loading, using, modifying and/or developing or
* reproducing the software by the user in light of its specific status
* of free software, that may mean that it is complicated to manipulate,
* and that also therefore means that it is reserved for developers and
* experienced professionals having in-depth computer knowledge. Users
* are therefore encouraged to load and test the software's suitability
* as regards their requirements in conditions enabling the security of
* their systems and/or data to be ensured and, more generally, to use
* and operate it in the same conditions as regards security.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL license and that you accept its terms.
*
***********************************************************************
*/
#include "csvstringreader.hh"
#include "point3d.hh"
#include <iostream>
using namespace std ;
using namespace boost ;
/* *** Constructors *** */
CSVStringReader::~CSVStringReader()
{
delete current_token ;
}
/* *** Accessors *** */
/**
* Note that this function is not called by the constructor, so you
* must manually call it to set a string to process prior to use
* read_field().
* @return \em false in case of error (EOF, etc.), \em true else.
*/
void CSVStringReader::set_str(const string &_str)
{
str = _str ;
delete current_token ;
current_token = NULL ;
// Split read string into fields (semicolon-separated)
current_token = new tokenizer<escaped_list_separator<char> >(
str, escaped_list_separator<char>('\\', separator, '\"')) ;
token_iterator = current_token->begin() ;
current_field_nb = 0 ;
}
/* *** Operations *** */
bool CSVStringReader::read_timestamp(Timestamp &t)
{
string timestamp_str ;
uint_fast32_t time_s, time_ns ;
if (! read_field(timestamp_str))
return false ;
tokenizer<escaped_list_separator<char> > tok(
timestamp_str, escaped_list_separator<char>('\\', '.', '\"')) ;
tokenizer<escaped_list_separator<char> >::const_iterator tok_iter =
tok.begin() ;
if (tok_iter == tok.end())
return false ;
try
{
time_s = lexical_cast<uint_fast32_t>(*tok_iter) ;
}
catch (bad_lexical_cast &e)
{
print_error_cast() ;
return false ;
}
++tok_iter ;
if (tok_iter == tok.end())
return false ;
try
{
time_ns = lexical_cast<uint_fast32_t>(*tok_iter) ;
}
catch (bad_lexical_cast &e)
{
print_error_cast() ;
return false ;
}
t = Timestamp(time_s, time_ns) ;
return true ;
}
bool CSVStringReader::read_point3d(Point3D &p)
{
float coord[3] ;
for (unsigned int i = 0 ; i < 3 ; ++i)
{
if (token_iterator == current_token->end())
return false ;
++current_field_nb ;
try
{
coord[i] = lexical_cast<float>(*token_iterator) ;
}
catch (bad_lexical_cast &e)
{
print_error_cast() ;
return false ;
}
++token_iterator ;
}
p.set_coordinates(coord) ;
return true ;
}
void CSVStringReader::print_error_cast() const
{
cerr
<< "Bad value \"" << *token_iterator
<< "\" at field #" << current_field_nb
<< ", of CSV string \"" << str << "\"!" << endl ;
}

View File

@ -0,0 +1,118 @@
/*
* This file is part of the Owl Positioning System (OwlPS).
* OwlPS is a project of the University of Franche-Comte
* (Université de Franche-Comté), France.
*
* Copyright © Université de Franche-Comté 2007-2012.
*
* Corresponding author: Matteo Cypriani <mcy@lm7.fr>
*
***********************************************************************
*
* This software is governed by the CeCILL license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/or redistribute the software under the terms of the CeCILL
* license as circulated by CEA, CNRS and INRIA at the following URL:
* http://www.cecill.info
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided
* only with a limited warranty and the software's authors, the holder
* of the economic rights, and the successive licensors have only
* limited liability.
*
* In this respect, the user's attention is drawn to the risks
* associated with loading, using, modifying and/or developing or
* reproducing the software by the user in light of its specific status
* of free software, that may mean that it is complicated to manipulate,
* and that also therefore means that it is reserved for developers and
* experienced professionals having in-depth computer knowledge. Users
* are therefore encouraged to load and test the software's suitability
* as regards their requirements in conditions enabling the security of
* their systems and/or data to be ensured and, more generally, to use
* and operate it in the same conditions as regards security.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL license and that you accept its terms.
*
***********************************************************************
*/
#ifndef _OWLPS_POSITIONING_CSVREADER_HH_
#define _OWLPS_POSITIONING_CSVREADER_HH_
class Point3D ;
#include "timestamp.hh"
#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>
/// Processes CSV strings, allowing to read them field by field
class CSVStringReader
{
protected:
const char separator ;
std::string str ;
boost::tokenizer<boost::escaped_list_separator<char> > *current_token ;
boost::tokenizer<boost::escaped_list_separator<char> >::const_iterator
token_iterator ;
unsigned int current_field_nb ;
void print_error_cast(void) const ;
public:
CSVStringReader(const char _separator = ';'):
separator(_separator), current_token(NULL), current_field_nb(0) {}
virtual ~CSVStringReader(void) ;
/** @name Accessors */
//@{
/// Set a new string to process
void set_str(const std::string &_str) ;
//@}
/** @name Operations */
//@{
/// Reads the next field of the current line
template<class T> bool read_field(T &field) ;
/// Reads the next field that should be a Timestamp
bool read_timestamp(Timestamp &t) ;
/// Reads the next 3 fields that should form a Point3D
bool read_point3d(Point3D &p) ;
//@}
} ;
/* *** Operations *** */
template<class T>
inline bool CSVStringReader::read_field(T &field)
{
if (token_iterator == current_token->end())
return false ;
++current_field_nb ;
try
{
field = boost::lexical_cast<T>(*token_iterator) ;
}
catch (boost::bad_lexical_cast &e)
{
print_error_cast() ;
return false ;
}
++token_iterator ;
return true ;
}
#endif // _OWLPS_POSITIONING_CSVREADER_HH_