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
}
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
//! the executable name
......@@ -398,6 +425,80 @@ class arguments
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
......
......@@ -21,7 +21,7 @@
#endif
void vertical_segment::load_data_from_text(std::istream& input,
const header& header,
const arguments& header,
vertical_segment& result,
const arguments& args)
{
......@@ -30,12 +30,19 @@ void vertical_segment::load_data_from_text(std::istream& input,
result._nX = 0 ; result._nY = 0 ;
std::pair<int, int> dim = header["DIM"];
result._nX = dim.first;
result._nY = dim.second;
if(! header.is_defined("DIM")) {
std::cerr << "<<ERROR>> Undefined dimensions ! ";
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()) ;
result._max.resize(result.dimX()) ;
std::pair<int, int> dim = header.get_pair<int>("DIM");
result.setDimX(dim.first);
result.setDimY(dim.second);
min = args.get_vec("min", 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,
result._max[k] = -std::numeric_limits<double>::max() ;
}
result._in_param = params::parse_input(header["PARAM_IN"]);
result._out_param = params::parse_output(header["PARAM_OUT"]);
int vs_value = header["VS"];
int vs_value = header.get_int("VS");
// Now read the body.
while(input.good())
......@@ -254,31 +258,28 @@ void save_data_as_binary(std::ostream &out, const data& data)
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.
assert(header["FORMAT"].string() == "binary");
assert(header["VERSION"] == 0);
assert(header["PRECISION"].string() == "ieee754-double");
assert(header["FORMAT"] == "binary");
assert(header.get_int("VERSION") == 0);
assert(header["PRECISION"] == "ieee754-double");
#if __BYTE_ORDER == __LITTLE_ENDIAN
assert(header["ENDIAN"].string() == "little");
assert(header["ENDIAN"] == "little");
#else
assert(header["ENDIAN"].string() == "big");
assert(header["ENDIAN"] == "big");
#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.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);
int sample_count = header["SAMPLE_COUNT"];
int sample_count = header.get_int("SAMPLE_COUNT");
// Initialize the mininum and maximum values.
vec min(dim.first), max(dim.first);
......
......@@ -13,6 +13,7 @@
#include <iostream>
#include "data.h"
#include "common.h"
#include "args.h"
// Write DATA to OUT in ALTA's text format.
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);
// 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);
......@@ -490,9 +490,21 @@ class parametrized
virtual int dimY() const { return _nY ; }
//! 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
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 */
......
......@@ -192,14 +192,14 @@ function* plugins_manager::load_function(const std::string& filename)
// Parse the header for the function command line and the dimension
// 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;
nY = dim.second;
param_in = params::parse_input(header["PARAM_IN"]);
param_out = params::parse_output(header["PARAM_OUT"]);
param_in = params::parse_input(header.get_string("PARAM_IN", "UNKNOWN_INPUT"));
param_out = params::parse_output(header.get_string("PARAM_OUT", "UNKNOWN_OUTPUT"));
args = arguments::create_arguments(header["CMD"]);
// Create the function from the command line
......@@ -256,12 +256,11 @@ function* plugins_manager::get_function(const arguments& args)
return NULL;
}
//! create a <em>compound</em> class to store multiple
//! functions in it.
//! create a *compound* class to store multiple ! functions in it.
compound_function* compound = new compound_function();
//! For each args_vec element, create a function object and add
//! it to the compound one.
//! For each args_vec element, create a function object and add ! it to the
//compound one.
for(unsigned int i=0; i<args_vec.size(); ++i)
{
std::string n("--func ");
......
......@@ -68,13 +68,19 @@ void vertical_segment::load(const std::string& filename, const arguments& args)
file.open(filename.c_str());
file.exceptions (std::ios::goodbit);
header header(file);
arguments header = arguments::parse_header(file);
if (header["FORMAT"].string() == "binary")
load_data_from_binary(file, header, *this);
else if (header["FORMAT"].string() == "text")
load_data_from_text(file, header, *this, args);
else throw; // FIXME: Throw a usable exception.
// Default behaviour: parsing a file as TEXT file. Send a message error in case
// the user did not set it.
if(! header.is_defined("FORMAT")) {
std::cerr << "<<DEBUG>> The file format is undefined, assuming TEXT" << std::endl;
}
if (header["FORMAT"] == "binary") {
load_data_from_binary(file, header, *this);
} else {
load_data_from_text(file, header, *this, args);
}
file.close();
}
......
......@@ -133,7 +133,7 @@ class vertical_segment : public data
void initializeToZero( unsigned int number_of_data_elements );
static void load_data_from_text(std::istream& input,
const header& header,
const arguments& header,
vertical_segment& result,
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