[Positioning] InputCSV: handle auto EOF & closing

InputCSV:
- Add eof_close() to automatically close the file when EOF is reached.
- Add read_next_line(), that read the next non-blank line and skips
  blank characters.
- Add current_line, a string containing the current line data.
- Update unit test.

InputMedium:
- Rename InputMedium::current_line to current_line_nb.
This commit is contained in:
Matteo Cypriani 2010-02-02 19:37:37 +01:00
parent ec10ed71a1
commit 910d9a04d9
6 changed files with 92 additions and 40 deletions

View File

@ -1,2 +1,4 @@
doc
csv/*.csv
tests/*.cc
tests/tests

View File

@ -6,9 +6,6 @@
° Différencier une requête normale d'une requête de calibration, en
utilisant les champs de direction.
° Lire la direction en tant qu'entier plutôt que float ?
° Fermer le fichier lorsqu'on a atteint la fin.
° Faire en sorte que eof() soit vrai dès qu'on a lu la dernière
ligne (skip blanks, etc.).
- Affichage de debug
Garder (generaliser) ? Supprimer ?

View File

@ -33,6 +33,8 @@ InputCSV::InputCSV(const string &filename)
if (! input_file)
throw runtime_error("Error opening input file « " +
input_file_name + " »!") ;
read_next_line() ;
}
@ -40,6 +42,59 @@ InputCSV::InputCSV(const string &filename)
/* *** Operations *** */
/**
* Tests if #input_file is opened and there is something more to
* read. If the end of file is reached, the stream is closed.
* @return \em true if the end of file is reached or if the file is
* already closed.
* @return \em false if there is something more to read.
*/
bool InputCSV::eof_close()
{
if (! input_file)
return false ;
if (input_file.eof())
{
input_file.close() ;
return true ;
}
return false ;
}
/**
* Read the next non-blank line. Tabs and spaces at the begining of a
* line are skipped.
* #current_line is set to empty string in case of error.
*/
void InputCSV::read_next_line()
{
if (eof_close())
{
current_line.clear() ;
return ;
}
string::size_type first_non_blank = 0 ;
do
{
++current_line_nb ;
getline(input_file, current_line) ;
}
while (! input_file.eof() &&
(first_non_blank = current_line.find_first_not_of(" \t"))
== string::npos) ;
if (eof_close())
current_line.clear() ;
else
current_line.erase(0, first_non_blank) ;
}
/**
* This function reads the next Request in the CSV input file. Blank
* lines and lines containing only spaces are skipped.
@ -55,33 +110,16 @@ InputCSV::InputCSV(const string &filename)
*/
const Request& InputCSV::get_next_request()
{
if (! input_file)
if (eof_close())
{
current_request.clear() ;
return current_request ;
}
string line ;
// Skipping blank lines
do
{
++current_line ;
getline(input_file, line) ;
}
while (! input_file.eof()
&& line.find_first_not_of(" \t") == string::npos) ;
if (input_file.eof())
{
// End of file reached: blank current request
// End of file or error: blank current request
current_request.clear() ;
return current_request ;
}
// Split read string into fields (semicolon-separated)
tokenizer<escaped_list_separator<char> > tok(
line, escaped_list_separator<char>('\\', ';', '\"')) ;
current_line, escaped_list_separator<char>('\\', ';', '\"')) ;
tokenizer<escaped_list_separator<char> >::iterator ti(tok.begin()) ;
@ -121,7 +159,7 @@ const Request& InputCSV::get_next_request()
cerr
<< "InputCSV::get_next_request(): Bad value « "
<< *ti << " » at line "
<< current_line << ", field « Timestamp », of input file « "
<< current_line_nb << ", field « Timestamp », of input file « "
<< input_file_name << " »!" << endl ;
current_request.clear() ; // Blank current request
return current_request ;
@ -146,7 +184,7 @@ const Request& InputCSV::get_next_request()
cerr
<< "InputCSV::get_next_request(): Bad value « "
<< *ti << " » at line "
<< current_line << ", position field #" << i
<< current_line_nb << ", position field #" << i
<< ", of input file « " << input_file_name << " »!"
<< endl ;
current_request.clear() ; // Blank current request
@ -178,7 +216,7 @@ const Request& InputCSV::get_next_request()
cerr
<< "InputCSV::get_next_request(): Bad value « "
<< *ti << " » at line "
<< current_line
<< current_line_nb
<< " of input file « " << input_file_name << " »!"
<< endl ;
current_request.clear() ; // Blank current request
@ -202,5 +240,7 @@ const Request& InputCSV::get_next_request()
current_request.set_measurements(measurements) ;
read_next_line() ;
return current_request ;
}

View File

@ -14,6 +14,16 @@ protected:
std::string input_file_name ;
/// Stream corresponding to the input CSV file
std::ifstream input_file ;
/// Current line contents
std::string current_line ;
/** @name Operations */
//@{
/// Checks if the file is readable and closes it if not
bool eof_close(void) ;
/// Reads the next line
void read_next_line(void) ;
//@}
public:
/// Constructs an InputCSV from a CSV input file name
@ -49,7 +59,7 @@ public:
*/
inline bool InputCSV::eof() const
{
return input_file.eof() ;
return ! input_file && input_file.eof() ;
}

View File

@ -14,7 +14,7 @@ protected:
/// The Request just read
Request current_request ;
/// Number of the current line proceeded
unsigned long current_line ;
unsigned long current_line_nb ;
public:
/// Default constructor
@ -28,8 +28,8 @@ public:
/// #current_request read accessor
const Request& get_current_request(void) const ;
/// #current_line read accessor
unsigned int get_current_line(void) const ;
/// #current_line_nb read accessor
unsigned int get_current_line_nb(void) const ;
/// Checks if the last request has been reached
/**
@ -45,7 +45,7 @@ public:
/// Reads the next request
/**
* Reads a Request, increments current_line, updates #current_request
* Reads a Request, increments current_line_nb, updates #current_request
* and returns it.
* @return The Request read, or an empty Request in case of error or
* EOF (note that when casted in bool, an empty Request is false, see
@ -63,7 +63,7 @@ public:
inline InputMedium::InputMedium()
{
current_line = 0 ;
current_line_nb = 0 ;
}
@ -77,9 +77,9 @@ inline const Request& InputMedium::get_current_request() const
}
inline unsigned int InputMedium::get_current_line() const
inline unsigned int InputMedium::get_current_line_nb() const
{
return current_line ;
return current_line_nb ;
}

View File

@ -32,7 +32,8 @@ public:
// Filling name and contents of the CSV test file
csv_file_name = "/tmp/InputCSV_test_csv_file.csv" ;
csv_lines.push_back("\
aa:bb:cc:dd:ee:ff;1265120910725;0.00;0.00;0.00;0\
\n \n\
aa:bb:cc:dd:ee:ff;1265120910725;0.00;0.00;0.00;0\
;" + aps[0].get_mac_addr() + ";-58\
;" + aps[2].get_mac_addr() + ";-50\
;" + aps[1].get_mac_addr() + ";-42\
@ -46,15 +47,18 @@ aa:bb:cc:dd:ee:77;1265120911234;0.00;0.00;0.00;0\
;" + aps[1].get_mac_addr() + ";-70\
;" + aps[1].get_mac_addr() + ";-21\
;" + aps[0].get_mac_addr() + ";-19\
\n \n\
\n\t\n\
\n \t \n\
\n") ;
csv_lines.push_back("\
aa:bb:cc:dd:ee:ff;1265120912345;0.00;0.00;0.00;0\
\taa:bb:cc:dd:ee:ff;1265120912345;0.00;0.00;0.00;0\
;" + aps[2].get_mac_addr() + ";-56\
;" + aps[1].get_mac_addr() + ";-45\
;" + aps[0].get_mac_addr() + ";-54\
;" + aps[1].get_mac_addr() + ";-23\
;" + aps[0].get_mac_addr() + ";-32\
\n") ;
\n\n\t\n") ;
// Opening the file
std::ofstream csv_file ;
@ -192,9 +196,8 @@ aa:bb:cc:dd:ee:ff;1265120912345;0.00;0.00;0.00;0\
// End of file
TS_WARN("TODO: eof() should be true even before we try to read another request.") ;
TS_ASSERT(inputcsv1) ;
TS_ASSERT(! inputcsv1.eof()) ;
TS_ASSERT(! inputcsv1) ;
TS_ASSERT(inputcsv1.eof()) ;
request1 = inputcsv1.get_next_request() ;
TS_ASSERT(! request1) ;