added FileReader

This commit is contained in:
john30
2014-11-23 20:25:48 +01:00
parent 4141f8e091
commit 922217602b
5 changed files with 120 additions and 52 deletions
+17 -2
View File
@@ -69,7 +69,6 @@ static const dataType_t dataTypes[] = {
/** the week day names. */
static const char* dayNames[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
#define FIELD_SEPARATOR ';'
#define VALUE_SEPARATOR ','
#define LENGTH_SEPARATOR ':'
#define NULL_VALUE "-"
@@ -1048,7 +1047,7 @@ result_t DataFieldTemplates::add(DataField* field, bool replace)
map<string, DataField*>::iterator it = m_fieldsByName.find(name);
if (it != m_fieldsByName.end()) {
if (replace == false)
return RESULT_ERR_INVALID_ARG; // duplicate key
return RESULT_ERR_DUPLICATE; // duplicate key
delete it->second;
it->second = field;
@@ -1061,6 +1060,21 @@ result_t DataFieldTemplates::add(DataField* field, bool replace)
return RESULT_OK;
}
result_t DataFieldTemplates::addFromFile(vector<string>& row, void* arg)
{
DataField* field = NULL;
vector<string>::iterator it = row.begin();
result_t result = DataField::create(it, row.end(), this, field);
if (result != RESULT_OK)
return result;
result = add(field);
if (result != RESULT_OK)
delete field;
return result;
}
DataField* DataFieldTemplates::get(const string name)
{
map<string, DataField*>::const_iterator ref = m_fieldsByName.find(name);
@@ -1069,3 +1083,4 @@ DataField* DataFieldTemplates::get(const string name)
return ref->second;
}
+71 -1
View File
@@ -23,11 +23,16 @@
#include "symbol.h"
#include "result.h"
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <map>
using namespace std;
#define FIELD_SEPARATOR ';'
/** the message part in which a data field is stored. */
enum PartType {
pt_any, // stored in any data (master or slave)
@@ -554,10 +559,73 @@ private:
};
/**
* @brief An abstract class that support reading definitions from a file.
*/
template<typename T>
class FileReader
{
public:
/**
* @brief Constructs a new instance.
*/
FileReader() {}
/**
* @brief Destructor.
*/
virtual ~FileReader() {}
/**
* @brief Reads the definitions from a file.
* @param filename the name (and path) of the file to read.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t readFromFile(string filename, T arg=NULL)
{
ifstream ifs;
ifs.open(filename.c_str(), ifstream::in);
if (ifs.is_open() == false)
return RESULT_ERR_FILENOTFOUND;
string line;
unsigned int lineNo = 0;
vector<string> row;
string token;
while (getline(ifs, line) != 0) {
lineNo++;
// skip empty lines and comments
if (line.length() == 0 || line.substr(0, 1) == "#" || line.substr(0, 2) == "//")
continue;
istringstream isstr(line);
row.clear();
while (getline(isstr, token, FIELD_SEPARATOR) != 0)
row.push_back(token);
result_t result = addFromFile(row, arg);
if (result != RESULT_OK) {
cerr << "error reading \"" << filename << "\" line " << static_cast<unsigned>(lineNo) << ": " << getResultCode(result) << endl;
ifs.close();
return result;
}
}
ifs.close();
return RESULT_OK;
}
/**
* @brief Adds a definition that was read from a file.
* @param row the definition row read from the file.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t addFromFile(vector<string>& row, T arg) = 0;
};
/**
* @brief A map of template @a DataField instances.
*/
class DataFieldTemplates
class DataFieldTemplates : public FileReader<void*>
{
public:
@@ -581,6 +649,8 @@ public:
* Note: the caller may not free the added instance on success.
*/
result_t add(DataField* message, bool replace=false);
// @copydoc
virtual result_t addFromFile(vector<string>& row, void* arg);
/**
* @brief Gets the template @a DataField instance with the specified name.
* @return the template @a DataField instance, or NULL.
+16 -1
View File
@@ -210,7 +210,7 @@ result_t MessageMap::add(Message* message)
unsigned long long pkey = message->getKey();
map<unsigned long long, Message*>::iterator keyIt = m_passiveMessagesByKey.find(pkey);
if (keyIt != m_passiveMessagesByKey.end())
return RESULT_ERR_INVALID_ARG; // duplicate key
return RESULT_ERR_DUPLICATE; // duplicate key
unsigned char idLength = message->getId().size() - 2;
if (idLength > m_maxIdLength)
@@ -223,6 +223,21 @@ result_t MessageMap::add(Message* message)
return RESULT_OK;
}
result_t MessageMap::addFromFile(vector<string>& row, DataFieldTemplates* arg)
{
Message* message = NULL;
vector<string>::iterator it = row.begin();
result_t result = Message::create(it, row.end(), arg, message);
if (result != RESULT_OK)
return result;
result = add(message);
if (result != RESULT_OK)
delete message;
return result;
}
Message* MessageMap::find(const string clazz, const string name, const bool isActive, const bool isSet)
{
string key = clazz;
+4 -1
View File
@@ -176,7 +176,7 @@ private:
/**
* @brief Holds a map of all known @a Message instances.
*/
class MessageMap
class MessageMap : public FileReader<DataFieldTemplates*>
{
public:
@@ -195,6 +195,8 @@ public:
* Note: the caller may not free the added instance on success.
*/
result_t add(Message* message);
// @copydoc
virtual result_t addFromFile(vector<string>& row, DataFieldTemplates* arg);
/**
* @brief Finds the @a Message instance for the specified class and name.
* @param master the master @a SymbolString for identifying the @a Message.
@@ -214,6 +216,7 @@ public:
*/
void clear();
private:
/** the maximum ID length used by any of the known @a Message instances. */
+12 -47
View File
@@ -66,51 +66,6 @@ void printErrorPos(vector<string>::iterator it, const vector<string>::iterator e
cout << setw(cnt) << " " << setw(0) << "^" << endl;
}
bool readTemplates(string filename, DataFieldTemplates* templates)
{
ifstream ifs;
ifs.open(filename.c_str(), ifstream::in);
if (ifs.is_open() == false) {
cerr << "error reading \"" << filename << endl;
return false;
}
string line;
unsigned int lineNo = 0;
vector<string> row;
string token;
while (getline(ifs, line) != 0) {
lineNo++;
istringstream isstr(line);
row.clear();
while (getline(isstr, token, ';') != 0)
row.push_back(token);
// skip empty and commented rows
if (row.empty() == true || row[0][0] == '#')
continue;
DataField* field = NULL;
vector<string>::iterator it = row.begin();
result_t result = DataField::create(it, row.end(), templates, field);
if (result != RESULT_OK) {
cerr << "error reading \"" << filename << "\" line " << static_cast<unsigned>(lineNo) << ": " << getResultCode(result) << endl;
printErrorPos(row.begin(), row.end(), it);
} else if (it != row.end())
cout << "extra data in \"" << filename << "\" line " << static_cast<unsigned>(lineNo) << endl;
else {
result = templates->add(field, true);
if (result != RESULT_OK) {
cerr << "error adding template \"" << field->getName() << "\": " << getResultCode(result) << endl;
delete field;
}
}
}
ifs.close();
return true;
}
int main()
{
// message= [type];class;name;[comment];[QQ];ZZ;PBSB;fields...
@@ -124,11 +79,21 @@ int main()
{"c;ehp;ActualEnvironmentPower;Energiebezug;;08;B50929BA00;;s;IGN:2;;;;;s;power", "8", "1008b5090329ba00", "03ba0008", "p"},
};
DataFieldTemplates* templates = new DataFieldTemplates();
readTemplates("_types.csv", templates);
result_t result = templates->readFromFile("_types.csv");
if (result == RESULT_OK)
cout << "read templates OK" << endl;
else
cout << "read templates error: " << getResultCode(result) << endl;
MessageMap* messages = new MessageMap();
result = messages->readFromFile("ehp00.csv", templates);
if (result == RESULT_OK)
cout << "read messages OK" << endl;
else
cout << "read messages error: " << getResultCode(result) << endl;
Message *message = NULL;
Message* deleteMessage = NULL;
MessageMap* messages = new MessageMap();
for (size_t i = 0; i < sizeof(checks) / sizeof(checks[0]); i++) {
string check[5] = checks[i];
istringstream isstr(check[0]);