added FileReader
This commit is contained in:
+17
-2
@@ -69,7 +69,6 @@ static const dataType_t dataTypes[] = {
|
|||||||
/** the week day names. */
|
/** the week day names. */
|
||||||
static const char* dayNames[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
|
static const char* dayNames[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
|
||||||
|
|
||||||
#define FIELD_SEPARATOR ';'
|
|
||||||
#define VALUE_SEPARATOR ','
|
#define VALUE_SEPARATOR ','
|
||||||
#define LENGTH_SEPARATOR ':'
|
#define LENGTH_SEPARATOR ':'
|
||||||
#define NULL_VALUE "-"
|
#define NULL_VALUE "-"
|
||||||
@@ -1048,7 +1047,7 @@ result_t DataFieldTemplates::add(DataField* field, bool replace)
|
|||||||
map<string, DataField*>::iterator it = m_fieldsByName.find(name);
|
map<string, DataField*>::iterator it = m_fieldsByName.find(name);
|
||||||
if (it != m_fieldsByName.end()) {
|
if (it != m_fieldsByName.end()) {
|
||||||
if (replace == false)
|
if (replace == false)
|
||||||
return RESULT_ERR_INVALID_ARG; // duplicate key
|
return RESULT_ERR_DUPLICATE; // duplicate key
|
||||||
|
|
||||||
delete it->second;
|
delete it->second;
|
||||||
it->second = field;
|
it->second = field;
|
||||||
@@ -1061,6 +1060,21 @@ result_t DataFieldTemplates::add(DataField* field, bool replace)
|
|||||||
return RESULT_OK;
|
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)
|
DataField* DataFieldTemplates::get(const string name)
|
||||||
{
|
{
|
||||||
map<string, DataField*>::const_iterator ref = m_fieldsByName.find(name);
|
map<string, DataField*>::const_iterator ref = m_fieldsByName.find(name);
|
||||||
@@ -1069,3 +1083,4 @@ DataField* DataFieldTemplates::get(const string name)
|
|||||||
|
|
||||||
return ref->second;
|
return ref->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+71
-1
@@ -23,11 +23,16 @@
|
|||||||
#include "symbol.h"
|
#include "symbol.h"
|
||||||
#include "result.h"
|
#include "result.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
#define FIELD_SEPARATOR ';'
|
||||||
|
|
||||||
/** the message part in which a data field is stored. */
|
/** the message part in which a data field is stored. */
|
||||||
enum PartType {
|
enum PartType {
|
||||||
pt_any, // stored in any data (master or slave)
|
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.
|
* @brief A map of template @a DataField instances.
|
||||||
*/
|
*/
|
||||||
class DataFieldTemplates
|
class DataFieldTemplates : public FileReader<void*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -581,6 +649,8 @@ public:
|
|||||||
* Note: the caller may not free the added instance on success.
|
* Note: the caller may not free the added instance on success.
|
||||||
*/
|
*/
|
||||||
result_t add(DataField* message, bool replace=false);
|
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.
|
* @brief Gets the template @a DataField instance with the specified name.
|
||||||
* @return the template @a DataField instance, or NULL.
|
* @return the template @a DataField instance, or NULL.
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ result_t MessageMap::add(Message* message)
|
|||||||
unsigned long long pkey = message->getKey();
|
unsigned long long pkey = message->getKey();
|
||||||
map<unsigned long long, Message*>::iterator keyIt = m_passiveMessagesByKey.find(pkey);
|
map<unsigned long long, Message*>::iterator keyIt = m_passiveMessagesByKey.find(pkey);
|
||||||
if (keyIt != m_passiveMessagesByKey.end())
|
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;
|
unsigned char idLength = message->getId().size() - 2;
|
||||||
if (idLength > m_maxIdLength)
|
if (idLength > m_maxIdLength)
|
||||||
@@ -223,6 +223,21 @@ result_t MessageMap::add(Message* message)
|
|||||||
return RESULT_OK;
|
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)
|
Message* MessageMap::find(const string clazz, const string name, const bool isActive, const bool isSet)
|
||||||
{
|
{
|
||||||
string key = clazz;
|
string key = clazz;
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* @brief Holds a map of all known @a Message instances.
|
* @brief Holds a map of all known @a Message instances.
|
||||||
*/
|
*/
|
||||||
class MessageMap
|
class MessageMap : public FileReader<DataFieldTemplates*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -195,6 +195,8 @@ public:
|
|||||||
* Note: the caller may not free the added instance on success.
|
* Note: the caller may not free the added instance on success.
|
||||||
*/
|
*/
|
||||||
result_t add(Message* message);
|
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.
|
* @brief Finds the @a Message instance for the specified class and name.
|
||||||
* @param master the master @a SymbolString for identifying the @a Message.
|
* @param master the master @a SymbolString for identifying the @a Message.
|
||||||
@@ -214,6 +216,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** the maximum ID length used by any of the known @a Message instances. */
|
/** the maximum ID length used by any of the known @a Message instances. */
|
||||||
|
|||||||
@@ -66,51 +66,6 @@ void printErrorPos(vector<string>::iterator it, const vector<string>::iterator e
|
|||||||
cout << setw(cnt) << " " << setw(0) << "^" << endl;
|
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()
|
int main()
|
||||||
{
|
{
|
||||||
// message= [type];class;name;[comment];[QQ];ZZ;PBSB;fields...
|
// 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"},
|
{"c;ehp;ActualEnvironmentPower;Energiebezug;;08;B50929BA00;;s;IGN:2;;;;;s;power", "8", "1008b5090329ba00", "03ba0008", "p"},
|
||||||
};
|
};
|
||||||
DataFieldTemplates* templates = new DataFieldTemplates();
|
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 *message = NULL;
|
||||||
Message* deleteMessage = NULL;
|
Message* deleteMessage = NULL;
|
||||||
MessageMap* messages = new MessageMap();
|
|
||||||
for (size_t i = 0; i < sizeof(checks) / sizeof(checks[0]); i++) {
|
for (size_t i = 0; i < sizeof(checks) / sizeof(checks[0]); i++) {
|
||||||
string check[5] = checks[i];
|
string check[5] = checks[i];
|
||||||
istringstream isstr(check[0]);
|
istringstream isstr(check[0]);
|
||||||
|
|||||||
Reference in New Issue
Block a user