Commit c5eaaf1e authored by Laurent Belcour's avatar Laurent Belcour

[Refactor] The 'header' class is useless I replaced the call to this code by

calls to the arguments class, much more robust. The header class was
causing segmentation faults due to non initialized static strings.
[Debug] Correction of the non-resizing of the min and max vectors inthe
vertical segment class when doing a setDimX or setDimY.
parent 7e793f6b
...@@ -329,6 +329,33 @@ class arguments ...@@ -329,6 +329,33 @@ class arguments
} }
return res; return res;
} }
//! \brief access a pair of element of type \a T.
//! the string associated with the key \a key should have the form
//! "a b" where a, b are compatible with type \a T.
template<typename T>
std::pair<T, T> get_pair(const std::string& key) const {
std::pair<T, T> res;
//TODO: RP: it is not very efficient to call count + find
// because find is called twice !!!
// My advice: find should be called once, check if the key exist
// and if yes use the iterator returned by find
if(_map.count(key) > 0) {
std::string str = _map.find(key)->second;
std::stringstream sstream(str);
T first, second;
sstream >> first >> second;
// Update the pair
res.first = first;
res.second = second;
}
return res;
}
//! \brief get the reconstructed command line arguments (without //! \brief get the reconstructed command line arguments (without
//! the executable name //! the executable name
...@@ -398,6 +425,80 @@ class arguments ...@@ -398,6 +425,80 @@ class arguments
return out; return out;
} }
//! \brief Parse a data file header.
//
//! \detail
//! ALTA file header should appear at the beginning of each file. Each
//! line starts with '#' and describe a couple key, value. For example,
//! parametrizations are described as:
//! #PARAM_IN NAME
//!
//! Note: A header should always start and ends by:
//! #ALTA HEADER BEGIN
//! #ALTA HEADER END
//!
static arguments parse_header(std::istream &input) {
// Argument object to be returned
arguments args;
while(input.good())
{
if (input.peek() == '#')
{
// consume the hash sign
input.get();
// Get the line
std::string line;
std::getline(input, line);
std::stringstream linestream(line);
// Lines starting with '# ' are real comments and we ignore
// them. Others are key/value associations that we want to use.
if (linestream.peek() != ' ') {
linestream.flags(std::ios_base::skipws);
std::string key, data;
linestream >> key;
if (!key.empty()) {
// ALTA header starts and ends with '#ALTA'
if (key == "ALTA") {
std::string first, second;
linestream >> first >> second;
if (second == "HEADER") {
// Add the header type
if (first != "END") {
args.update("TYPE", second);
} else {
break;
}
}
// Store the line into the argument
} else {
while(!linestream.eof() && std::isspace(linestream.peek())) {
linestream.get();
}
getline(linestream, data);
args.update(key, data) ;
}
}
}
// The first non-comment line terminates the header.
} else {
break;
}
}
return args;
}
private: // data private: // data
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#endif #endif
void vertical_segment::load_data_from_text(std::istream& input, void vertical_segment::load_data_from_text(std::istream& input,
const header& header, const arguments& header,
vertical_segment& result, vertical_segment& result,
const arguments& args) const arguments& args)
{ {
...@@ -30,12 +30,19 @@ void vertical_segment::load_data_from_text(std::istream& input, ...@@ -30,12 +30,19 @@ void vertical_segment::load_data_from_text(std::istream& input,
result._nX = 0 ; result._nY = 0 ; result._nX = 0 ; result._nY = 0 ;
std::pair<int, int> dim = header["DIM"]; if(! header.is_defined("DIM")) {
result._nX = dim.first; std::cerr << "<<ERROR>> Undefined dimensions ! ";
result._nY = dim.second; std::cerr << "Please add DIM [int] [int] into the file header." << std::endl;
throw;
}
params::input in_param = params::parse_input(header.get_string("PARAM_IN", "UNKNOWN_INPUT"));
params::output out_param = params::parse_output(header.get_string("PARAM_OUT", "UNKNOWN_OUTPUT"));
result.setParametrizations(in_param, out_param);
result._min.resize(result.dimX()) ; std::pair<int, int> dim = header.get_pair<int>("DIM");
result._max.resize(result.dimX()) ; result.setDimX(dim.first);
result.setDimY(dim.second);
min = args.get_vec("min", result._nX, -std::numeric_limits<float>::max()) ; min = args.get_vec("min", result._nX, -std::numeric_limits<float>::max()) ;
max = args.get_vec("max", result._nX, std::numeric_limits<float>::max()) ; max = args.get_vec("max", result._nX, std::numeric_limits<float>::max()) ;
...@@ -55,10 +62,7 @@ void vertical_segment::load_data_from_text(std::istream& input, ...@@ -55,10 +62,7 @@ void vertical_segment::load_data_from_text(std::istream& input,
result._max[k] = -std::numeric_limits<double>::max() ; result._max[k] = -std::numeric_limits<double>::max() ;
} }
result._in_param = params::parse_input(header["PARAM_IN"]); int vs_value = header.get_int("VS");
result._out_param = params::parse_output(header["PARAM_OUT"]);
int vs_value = header["VS"];
// Now read the body. // Now read the body.
while(input.good()) while(input.good())
...@@ -254,31 +258,28 @@ void save_data_as_binary(std::ostream &out, const data& data) ...@@ -254,31 +258,28 @@ void save_data_as_binary(std::ostream &out, const data& data)
out << std::endl << "#END_STREAM" << std::endl; out << std::endl << "#END_STREAM" << std::endl;
} }
void load_data_from_binary(std::istream& in, const header& header, data& data) void load_data_from_binary(std::istream& in, const arguments& header, data& data)
{ {
// FIXME: For now we make a number of assumptions. // FIXME: For now we make a number of assumptions.
assert(header["FORMAT"].string() == "binary"); assert(header["FORMAT"] == "binary");
assert(header["VERSION"] == 0); assert(header.get_int("VERSION") == 0);
assert(header["PRECISION"].string() == "ieee754-double"); assert(header["PRECISION"] == "ieee754-double");
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
assert(header["ENDIAN"].string() == "little"); assert(header["ENDIAN"] == "little");
#else #else
assert(header["ENDIAN"].string() == "big"); assert(header["ENDIAN"] == "big");
#endif #endif
std::pair<int, int> dim = header["DIM"]; data.setParametrizations(params::parse_input(header["PARAM_IN"]),
params::parse_output(header["PARAM_OUT"]));
std::pair<int, int> dim = header.get_pair<int>("DIM");
data.setDimX(dim.first); data.setDimX(dim.first);
data.setDimY(dim.second); data.setDimY(dim.second);
data._min.resize(dim.first);
data._max.resize(dim.first);
data.setParametrizations(params::parse_input(header["PARAM_IN"]),
params::parse_output(header["PARAM_OUT"]));
in.exceptions(std::ios_base::failbit); in.exceptions(std::ios_base::failbit);
int sample_count = header["SAMPLE_COUNT"]; int sample_count = header.get_int("SAMPLE_COUNT");
// Initialize the mininum and maximum values. // Initialize the mininum and maximum values.
vec min(dim.first), max(dim.first); vec min(dim.first), max(dim.first);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <iostream> #include <iostream>
#include "data.h" #include "data.h"
#include "common.h" #include "common.h"
#include "args.h"
// Write DATA to OUT in ALTA's text format. // Write DATA to OUT in ALTA's text format.
void save_data_as_text(std::ostream& out, const data &data); void save_data_as_text(std::ostream& out, const data &data);
...@@ -21,5 +22,5 @@ void save_data_as_text(std::ostream& out, const data &data); ...@@ -21,5 +22,5 @@ void save_data_as_text(std::ostream& out, const data &data);
void save_data_as_binary(std::ostream& out, const data& data); void save_data_as_binary(std::ostream& out, const data& data);
// Initialize DATA from the binary-formatted stream IN. // Initialize DATA from the binary-formatted stream IN.
void load_data_from_binary(std::istream& in, const header& header, void load_data_from_binary(std::istream& in, const arguments& header,
data &data); data &data);
...@@ -490,9 +490,21 @@ class parametrized ...@@ -490,9 +490,21 @@ class parametrized
virtual int dimY() const { return _nY ; } virtual int dimY() const { return _nY ; }
//! Set the dimension of the input space of the function //! Set the dimension of the input space of the function
virtual void setDimX(int nX) { _nX = nX ; } virtual void setDimX(int nX) {
if(_nX != nX) {
_nX = nX;
_min.resize(nX);
_max.resize(nX);
}
}
//! Set the dimension of the output space of the function //! Set the dimension of the output space of the function
virtual void setDimY(int nY) { _nY = nY ; } virtual void setDimY(int nY) {
if(_nY != nY) {
_nY = nY;
_min.resize(nY);
_max.resize(nY);
}
}
/* DEFINITION DOMAIN OF THE FUNCTION */ /* DEFINITION DOMAIN OF THE FUNCTION */
......
...@@ -192,14 +192,14 @@ function* plugins_manager::load_function(const std::string& filename) ...@@ -192,14 +192,14 @@ function* plugins_manager::load_function(const std::string& filename)
// Parse the header for the function command line and the dimension // Parse the header for the function command line and the dimension
// of the function // of the function
header header(file); arguments header = arguments::parse_header(file);
std::pair<int, int> dim = header["DIM"]; std::pair<int, int> dim = header.get_pair<int>("DIM");
nX = dim.first; nX = dim.first;
nY = dim.second; nY = dim.second;
param_in = params::parse_input(header["PARAM_IN"]); param_in = params::parse_input(header.get_string("PARAM_IN", "UNKNOWN_INPUT"));
param_out = params::parse_output(header["PARAM_OUT"]); param_out = params::parse_output(header.get_string("PARAM_OUT", "UNKNOWN_OUTPUT"));
args = arguments::create_arguments(header["CMD"]); args = arguments::create_arguments(header["CMD"]);
// Create the function from the command line // Create the function from the command line
...@@ -256,12 +256,11 @@ function* plugins_manager::get_function(const arguments& args) ...@@ -256,12 +256,11 @@ function* plugins_manager::get_function(const arguments& args)
return NULL; return NULL;
} }
//! create a <em>compound</em> class to store multiple //! create a *compound* class to store multiple ! functions in it.
//! functions in it.
compound_function* compound = new compound_function(); compound_function* compound = new compound_function();
//! For each args_vec element, create a function object and add //! For each args_vec element, create a function object and add ! it to the
//! it to the compound one. //compound one.
for(unsigned int i=0; i<args_vec.size(); ++i) for(unsigned int i=0; i<args_vec.size(); ++i)
{ {
std::string n("--func "); std::string n("--func ");
......
...@@ -68,13 +68,19 @@ void vertical_segment::load(const std::string& filename, const arguments& args) ...@@ -68,13 +68,19 @@ void vertical_segment::load(const std::string& filename, const arguments& args)
file.open(filename.c_str()); file.open(filename.c_str());
file.exceptions (std::ios::goodbit); file.exceptions (std::ios::goodbit);
header header(file); arguments header = arguments::parse_header(file);
if (header["FORMAT"].string() == "binary") // Default behaviour: parsing a file as TEXT file. Send a message error in case
load_data_from_binary(file, header, *this); // the user did not set it.
else if (header["FORMAT"].string() == "text") if(! header.is_defined("FORMAT")) {
load_data_from_text(file, header, *this, args); std::cerr << "<<DEBUG>> The file format is undefined, assuming TEXT" << std::endl;
else throw; // FIXME: Throw a usable exception. }
if (header["FORMAT"] == "binary") {
load_data_from_binary(file, header, *this);
} else {
load_data_from_text(file, header, *this, args);
}
file.close(); file.close();
} }
......
...@@ -133,7 +133,7 @@ class vertical_segment : public data ...@@ -133,7 +133,7 @@ class vertical_segment : public data
void initializeToZero( unsigned int number_of_data_elements ); void initializeToZero( unsigned int number_of_data_elements );
static void load_data_from_text(std::istream& input, static void load_data_from_text(std::istream& input,
const header& header, const arguments& header,
vertical_segment& result, vertical_segment& result,
const arguments& args); const arguments& args);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment