[Positioning] Add class TextFileReader

TextFileReader read lines from a text file. It is aimed to be used by
all classes that read from a text file, as TextFileWriter is used by
those which write to a text file.

Code of TextFileReader is taken from class InputCSV.

Minor fixes on the TextFileWriter unit test.
This commit is contained in:
Matteo Cypriani 2010-03-23 11:32:05 +01:00
parent 866013248f
commit 58ed434d6b
9 changed files with 215 additions and 74 deletions

View File

@ -57,6 +57,7 @@ OBJ_LIST = \
realposition.o \
configuration.o \
userinterface.o \
textfilereader.o \
textfilewriter.o \
output.o \
outputterminal.o \
@ -133,10 +134,13 @@ calibrationrequest.o: \
$(OBJ_DIR)/request.o \
$(OBJ_DIR)/referencepoint.o \
$(OBJ_DIR)/direction.o
textfilereader.o: \
$(OBJ_DIR)/posexcept.o
textfilewriter.o: \
$(OBJ_DIR)/posexcept.o
inputcsv.o: \
$(OBJ_DIR)/inputmedium.o \
$(OBJ_DIR)/textfilereader.o \
$(OBJ_DIR)/request.o \
$(OBJ_DIR)/calibrationrequest.o \
$(OBJ_DIR)/stock.o

View File

@ -25,50 +25,17 @@ using namespace boost ;
* @param filename The name of the file to open.
* @throw error_opening_input_file if the file cannot be opened.
*/
InputCSV::InputCSV(const string &filename)
InputCSV::InputCSV(const string &filename):
file(filename)
{
input_file_name = filename ;
input_file.open(input_file_name.c_str()) ;
if (! input_file)
throw error_opening_input_file(input_file_name) ;
read_next_line() ;
}
InputCSV::~InputCSV()
{
input_file.close() ;
}
/* *** 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.
@ -76,27 +43,21 @@ bool InputCSV::eof_close()
*/
void InputCSV::read_next_line()
{
if (eof_close())
{
current_line.clear() ;
return ;
}
string::size_type first_non_blank = 0 ;
do
{
if (! file.read_line(current_line))
{
current_line.clear() ;
return ;
}
++current_line_nb ;
getline(input_file, current_line) ;
}
while (! input_file.eof() &&
(first_non_blank = current_line.find_first_not_of(" \t"))
while ((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) ;
current_line.erase(0, first_non_blank) ;
}
@ -117,7 +78,7 @@ const Request& InputCSV::get_next_request()
{
clear_current_request() ;
if (eof_close()) // End of file or error
if (current_line.empty()) // End of file or error
return *current_request ;
// Split read string into fields (semicolon-separated)
@ -159,7 +120,7 @@ const Request& InputCSV::get_next_request()
<< "InputCSV::get_next_request(): Bad value « "
<< *ti << " » at line "
<< current_line_nb << ", field « Timestamp », of input file « "
<< input_file_name << " »!" << endl ;
<< file.get_name() << " »!" << endl ;
current_request->clear() ;
return *current_request ;
}
@ -187,7 +148,7 @@ const Request& InputCSV::get_next_request()
<< "InputCSV::get_next_request(): Bad value « "
<< *ti << " » at line "
<< current_line_nb << ", position field #" << i
<< ", of input file « " << input_file_name << " »!"
<< ", of input file « " << file.get_name() << " »!"
<< endl ;
current_request->clear() ;
return *current_request ;
@ -217,7 +178,7 @@ const Request& InputCSV::get_next_request()
<< "InputCSV::get_next_request(): Bad value « "
<< *ti << " » at line "
<< current_line_nb << ", field « Direction », of input file « "
<< input_file_name << " »!" << endl ;
<< file.get_name() << " »!" << endl ;
current_request->clear() ;
return *current_request ;
}
@ -247,7 +208,7 @@ const Request& InputCSV::get_next_request()
<< "InputCSV::get_next_request(): Bad value « "
<< *ti << " » at line "
<< current_line_nb
<< " of input file « " << input_file_name << " »!"
<< " of input file « " << file.get_name() << " »!"
<< endl ;
current_request->clear() ; // Blank current request
return *current_request ;
@ -270,8 +231,6 @@ const Request& InputCSV::get_next_request()
current_request->set_measurements(measurements) ;
read_next_line() ;
if (is_calibration_request)
{
current_request_to_calibration_request() ;
@ -284,5 +243,7 @@ const Request& InputCSV::get_next_request()
request->set_reference_point(&reference_point) ;
}
read_next_line() ;
return *current_request ;
}

View File

@ -2,9 +2,9 @@
#define _OWLPS_POSITIONING_INPUTCSV_HH_
#include "inputmedium.hh"
#include "textfilereader.hh"
#include <string>
#include <fstream>
/// Reads \link Request requests \endlink from a CSV file
/**
@ -14,19 +14,16 @@
class InputCSV: public InputMedium
{
protected:
std::string input_file_name ;
std::ifstream input_file ;
TextFileReader file ;
/// Current line contents
std::string current_line ;
/// Checks if the file is readable and closes it if not
bool eof_close(void) ;
void read_next_line(void) ;
public:
InputCSV(const std::string &filename) ;
~InputCSV(void) ;
~InputCSV(void) {}
/** @name Read accessors */
//@{
@ -51,13 +48,9 @@ public:
/* *** Read accessors *** */
/**
* @return \em true if the end of file is reached.
* @return \em false if there is something more to read.
*/
inline bool InputCSV::eof() const
{
return ! input_file && input_file.eof() ;
return file.eof() ;
}
@ -65,13 +58,9 @@ inline bool InputCSV::eof() const
/* *** Operators *** */
/**
* @return The bool value of #input_file.
* @sa std::ifstream
*/
inline InputCSV::operator bool() const
{
return input_file ;
return ! eof() ;
}

View File

@ -0,0 +1,66 @@
#include "textfilereader.hh"
#include "posexcept.hh"
using namespace std ;
/* *** Constructors *** */
/**
* @param _file_name The name of the file to open.
* @throw error_opening_input_file if the file cannot be opened.
*/
TextFileReader::TextFileReader(const string &_file_name):
file_name(_file_name)
{
file.open(file_name.c_str()) ;
if (! file)
throw error_opening_input_file(file_name) ;
}
TextFileReader::~TextFileReader()
{
file.close() ;
}
/* *** Operations *** */
/**
* @return The string read, or an empty string in case of error.
*/
bool TextFileReader::read_line(string &text)
{
if (eof_close())
return false ;
getline(file, text) ;
return true ;
}
/**
* Tests if #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 TextFileReader::eof_close()
{
if (file)
return false ;
if (file.eof())
{
file.close() ;
return true ;
}
return false ;
}

View File

@ -0,0 +1,59 @@
#ifndef _OWLPS_POSITIONING_TEXTFILEREADER_HH_
#define _OWLPS_POSITIONING_TEXTFILEREADER_HH_
#include <string>
#include <fstream>
/// Read text from a file
class TextFileReader
{
private:
std::string file_name ;
std::ifstream file ;
/// Checks if the file is readable and closes it if not
bool eof_close(void) ;
public:
TextFileReader(const std::string &_file_name) ;
virtual ~TextFileReader(void) ;
/** @name Operations */
//@{
bool read_line(std::string &text) ;
bool eof(void) const ;
//@}
/** @name Accessors */
//@{
const std::string& get_name(void) const ;
//@}
} ;
/* *** Operations *** */
/**
* @return \em true if the end of file is reached.
* @return \em false if there is something more to read.
*/
inline bool TextFileReader::eof() const
{
return ! file && file.eof() ;
}
/* *** Accessors *** */
inline const std::string& TextFileReader::get_name() const
{
return file_name ;
}
#endif // _OWLPS_POSITIONING_TEXTFILEREADER_HH_

View File

@ -65,6 +65,8 @@ public:
// First Request //
request1 = inputcsv1.get_next_request() ;
TS_ASSERT(request1) ;
assert(request1.get_mobile()) ;
TS_ASSERT_EQUALS(request1.get_mobile()->get_mac_addr(),
TestUtil::mobiles[0].get_mac_addr()) ;
TS_ASSERT_EQUALS(request1.get_time_sent(),
@ -88,6 +90,8 @@ public:
// Second Request //
request1 = inputcsv1.get_next_request() ;
TS_ASSERT(request1) ;
assert(request1.get_mobile()) ;
TS_ASSERT_EQUALS(request1.get_mobile()->get_mac_addr(),
TestUtil::mobiles[1].get_mac_addr()) ;
TS_ASSERT_EQUALS(request1.get_time_sent(),
@ -108,6 +112,8 @@ public:
// Third Request //
TS_ASSERT(inputcsv1) ;
TS_ASSERT(request1) ;
assert(request1.get_mobile()) ;
TS_ASSERT(! inputcsv1.eof()) ;
request1 = inputcsv1.get_next_request() ;

View File

@ -1,6 +1,7 @@
#include <cxxtest/TestSuite.h>
#include "inputlogcsv.hh"
#include "inputcsv.hh"
#include <vector>

View File

@ -0,0 +1,55 @@
#include <cxxtest/TestSuite.h>
#include "textfilereader.hh"
class TextFileReader_test: public CxxTest::TestSuite
{
private:
std::string test_file_name ;
public:
TextFileReader_test(void)
{
test_file_name = "/tmp/TextFileReader_test_file.csv" ;
}
~TextFileReader_test(void)
{
TestUtil::remove_file(test_file_name) ;
}
static TextFileReader_test* createSuite(void)
{
return new TextFileReader_test() ;
}
static void destroySuite(TextFileReader_test *suite)
{
delete suite ;
}
void test_textfilereader(void)
{
std::ofstream output_file(test_file_name.c_str()) ;
assert(output_file) ;
output_file << "Hello\nWorld\n" ;
output_file.close() ;
std::string line ;
TextFileReader *textfilereader ;
TS_ASSERT_THROWS_NOTHING(
textfilereader = new TextFileReader(test_file_name)) ;
TS_ASSERT(textfilereader->read_line(line)) ;
TS_ASSERT_EQUALS(line, "Hello") ;
TS_ASSERT(textfilereader->read_line(line)) ;
TS_ASSERT_EQUALS(line, "World") ;
delete textfilereader ;
}
} ;

View File

@ -11,7 +11,6 @@ public:
TextFileWriter_test(void)
{
Stock::clear() ;
test_file_name = "/tmp/TextFileWriter_test_file.csv" ;
}
@ -36,8 +35,9 @@ public:
void test_textfilewriter(void)
{
TextFileWriter *textfilewriter =
new TextFileWriter(test_file_name) ;
TextFileWriter *textfilewriter ;
TS_ASSERT_THROWS_NOTHING(
textfilewriter = new TextFileWriter(test_file_name)) ;
TS_ASSERT(textfilewriter->write_text("Hello\nWorld\n")) ;
delete textfilewriter ;