separate resolving+scanning to own interface+class and avoid use of extern
This commit is contained in:
@@ -94,11 +94,6 @@ static const char* defaultMessageFieldMap[] = { // access level not included in
|
||||
/** the m_pollOrder of the last polled message. */
|
||||
static unsigned int g_lastPollOrder = 0;
|
||||
|
||||
extern DataFieldTemplates* getTemplates(const string& filename);
|
||||
|
||||
extern result_t loadDefinitionsFromConfigPath(FileReader* reader, const string& filename, bool verbose,
|
||||
map<string, string>* defaults, string* errorDescription, bool replace = false);
|
||||
|
||||
|
||||
Message::Message(const string& filename, const string& circuit, const string& level, const string& name,
|
||||
bool isWrite, bool isPassive, const map<string, string>& attributes,
|
||||
@@ -1738,7 +1733,11 @@ void Instruction::getDestination(ostringstream* ostream) const {
|
||||
|
||||
result_t LoadInstruction::execute(MessageMap* messages, ostringstream* log) {
|
||||
string errorDescription;
|
||||
result_t result = loadDefinitionsFromConfigPath(messages, m_filename, false, &m_defaults, &errorDescription);
|
||||
Resolver* resolver = messages->getResolver();
|
||||
if (!resolver) {
|
||||
return RESULT_ERR_MISSING_ARG;
|
||||
}
|
||||
result_t result = resolver->loadDefinitionsFromConfigPath(messages, m_filename, &m_defaults, &errorDescription);
|
||||
if (log->tellp() > 0) {
|
||||
*log << ", ";
|
||||
}
|
||||
@@ -2306,7 +2305,10 @@ result_t MessageMap::addFromFile(const string& filename, unsigned int lineNo, ma
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
result = RESULT_ERR_EOF;
|
||||
DataFieldTemplates* templates = getTemplates(filename);
|
||||
if (!m_resolver) {
|
||||
return result;
|
||||
}
|
||||
DataFieldTemplates* templates = m_resolver->getTemplates(filename);
|
||||
bool hasMulti = types.find(VALUE_SEPARATOR) != string::npos;
|
||||
istringstream stream(types);
|
||||
string type;
|
||||
|
||||
+52
-1
@@ -1255,6 +1255,43 @@ class LoadedFileInfo {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Interface for resolving templates and loading additional message definitions.
|
||||
*/
|
||||
class Resolver {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
Resolver() {}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~Resolver() {}
|
||||
|
||||
/**
|
||||
* Get the @a DataFieldTemplates for the specified configuration file.
|
||||
* @param filename the full name of the configuration file, or "*" to get the non-root templates with the longest name
|
||||
* or the root templates if not available.
|
||||
* @return the @a DataFieldTemplates.
|
||||
*/
|
||||
virtual DataFieldTemplates* getTemplates(const string& filename) = 0;
|
||||
|
||||
/**
|
||||
* Load definitions from a relative file from the config path/URL.
|
||||
* @param reader the @a FileReader instance to load with the definitions.
|
||||
* @param filename the relative name of the file being read.
|
||||
* @param defaults the default values by name (potentially overwritten by file name), or nullptr to not use defaults.
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @param replace whether to replace an already existing entry.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t loadDefinitionsFromConfigPath(FileReader* reader, const string& filename,
|
||||
map<string, string>* defaults, string* errorDescription, bool replace = false) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Holds a map of all known @a Message instances.
|
||||
*/
|
||||
@@ -1267,7 +1304,7 @@ class MessageMap : public MappedFileReader {
|
||||
* @param deleteData whether to delete the scan message @a DataField during @a Message destruction.
|
||||
*/
|
||||
explicit MessageMap(bool addAll = false, const string& preferLanguage = "", bool deleteData = true)
|
||||
: MappedFileReader::MappedFileReader(true, preferLanguage),
|
||||
: MappedFileReader::MappedFileReader(true, preferLanguage), m_resolver(nullptr),
|
||||
m_addAll(addAll), m_additionalScanMessages(false), m_maxIdLength(0), m_maxBroadcastIdLength(0),
|
||||
m_messageCount(0), m_conditionalMessageCount(0), m_passiveMessageCount(0) {
|
||||
m_scanMessage = Message::createScanMessage(false, deleteData);
|
||||
@@ -1289,6 +1326,17 @@ class MessageMap : public MappedFileReader {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the @a Resolver instance.
|
||||
* @param the @a Resolver instance.
|
||||
*/
|
||||
void setResolver(Resolver* resolver) { m_resolver = resolver; }
|
||||
|
||||
/**
|
||||
* @return the @a Resolver instance.
|
||||
*/
|
||||
Resolver* getResolver() const { return m_resolver; }
|
||||
|
||||
/**
|
||||
* Add a @a Message instance to this set.
|
||||
* @param message the @a Message instance to add.
|
||||
@@ -1575,6 +1623,9 @@ class MessageMap : public MappedFileReader {
|
||||
/** empty vector for @a getLoadedFiles(). */
|
||||
static vector<string> s_noFiles;
|
||||
|
||||
/** the @a Resolver instance. */
|
||||
Resolver* m_resolver;
|
||||
|
||||
/** whether to add all messages, even if duplicate. */
|
||||
const bool m_addAll;
|
||||
|
||||
|
||||
@@ -54,27 +54,29 @@ DataFieldTemplates* templates = nullptr;
|
||||
|
||||
namespace ebusd {
|
||||
|
||||
DataFieldTemplates* getTemplates(const string& filename) {
|
||||
if (filename == "") { // avoid compiler warning
|
||||
class TestResolver : public Resolver {
|
||||
public:
|
||||
virtual DataFieldTemplates* getTemplates(const string& filename) {
|
||||
if (filename == "") { // avoid compiler warning
|
||||
return templates;
|
||||
}
|
||||
return templates;
|
||||
}
|
||||
return templates;
|
||||
}
|
||||
|
||||
result_t loadDefinitionsFromConfigPath(FileReader* reader, const string& filename, bool verbose,
|
||||
map<string, string>* defaults, string* errorDescription, bool replace = false) {
|
||||
time_t mtime = 0;
|
||||
istream* stream = FileReader::openFile(filename, errorDescription, &mtime);
|
||||
result_t result;
|
||||
if (stream) {
|
||||
result = reader->readFromStream(stream, filename, mtime, verbose, defaults, errorDescription);
|
||||
delete(stream);
|
||||
} else {
|
||||
result = RESULT_ERR_NOTFOUND;
|
||||
virtual result_t loadDefinitionsFromConfigPath(FileReader* reader, const string& filename,
|
||||
map<string, string>* defaults, string* errorDescription, bool replace = false) {
|
||||
time_t mtime = 0;
|
||||
istream* stream = FileReader::openFile(filename, errorDescription, &mtime);
|
||||
result_t result;
|
||||
if (stream) {
|
||||
result = reader->readFromStream(stream, filename, mtime, false, defaults, errorDescription);
|
||||
delete(stream);
|
||||
} else {
|
||||
result = RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace ebusd
|
||||
|
||||
@@ -208,6 +210,7 @@ int main() {
|
||||
templates->readLineFromStream(&dummystr, __FILE__, false, &lineNo, &row, &errorDescription, false, nullptr, nullptr);
|
||||
lineNo = 0;
|
||||
MessageMap* messages = new MessageMap("");
|
||||
messages->setResolver(new TestResolver());
|
||||
dummystr.clear();
|
||||
dummystr.str("#");
|
||||
messages->readLineFromStream(&dummystr, __FILE__, false, &lineNo, &row, &errorDescription, false, nullptr, nullptr);
|
||||
|
||||
Reference in New Issue
Block a user