code style
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "contrib.h"
|
||||
#include "tem.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_CONTRIB_H_
|
||||
#define LIBEBUS_CONTRIB_H_
|
||||
#ifndef LIB_EBUS_CONTRIB_H_
|
||||
#define LIB_EBUS_CONTRIB_H_
|
||||
|
||||
/** @file contrib.h
|
||||
* Contributed sources that may be excluded from regular builds.
|
||||
@@ -32,4 +32,4 @@ using namespace std;
|
||||
*/
|
||||
bool libebus_contrib_register();
|
||||
|
||||
#endif // LIBEBUS_CONTRIB_H_
|
||||
#endif // LIB_EBUS_CONTRIB_H_
|
||||
|
||||
@@ -20,14 +20,14 @@
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "datatype.h"
|
||||
#include "tem.h"
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <math.h>
|
||||
#include "datatype.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -35,8 +35,7 @@ void contrib_tem_register() {
|
||||
DataTypeList::getInstance()->add(new TemParamDataType("TEM_P"));
|
||||
}
|
||||
|
||||
result_t TemParamDataType::derive(int divisor, unsigned char bitCount, NumberDataType* &derived)
|
||||
{
|
||||
result_t TemParamDataType::derive(int divisor, unsigned char bitCount, NumberDataType* &derived) {
|
||||
if (divisor == 0) {
|
||||
divisor = 1;
|
||||
}
|
||||
@@ -52,8 +51,7 @@ result_t TemParamDataType::derive(int divisor, unsigned char bitCount, NumberDat
|
||||
|
||||
result_t TemParamDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
const unsigned char offset, const unsigned char length,
|
||||
ostringstream& output, OutputFormat outputFormat)
|
||||
{
|
||||
ostringstream& output, OutputFormat outputFormat) {
|
||||
unsigned int value = 0;
|
||||
|
||||
result_t result = readRawValue(input, offset, length, value);
|
||||
@@ -90,8 +88,7 @@ result_t TemParamDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
|
||||
result_t TemParamDataType::writeSymbols(istringstream& input,
|
||||
const unsigned char offset, const unsigned char length,
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength)
|
||||
{
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength) {
|
||||
unsigned int value;
|
||||
int grp, num;
|
||||
string token;
|
||||
|
||||
@@ -16,12 +16,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_CONTRIB_TEM_H_
|
||||
#define LIBEBUS_CONTRIB_TEM_H_
|
||||
#ifndef LIB_EBUS_CONTRIB_TEM_H_
|
||||
#define LIB_EBUS_CONTRIB_TEM_H_
|
||||
|
||||
#include "symbol.h"
|
||||
#include "result.h"
|
||||
#include "datatype.h"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@@ -29,6 +26,9 @@
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include "symbol.h"
|
||||
#include "result.h"
|
||||
#include "datatype.h"
|
||||
|
||||
/** @file tem.h
|
||||
* Contributed data types for TEM devices not part of regular releases.
|
||||
@@ -71,4 +71,4 @@ public:
|
||||
*/
|
||||
void contrib_tem_register();
|
||||
|
||||
#endif // LIBEBUS_CONTRIB_TEM_H_
|
||||
#endif // LIB_EBUS_CONTRIB_TEM_H_
|
||||
|
||||
@@ -16,18 +16,19 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tem.h"
|
||||
#include "data.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "tem.h"
|
||||
#include "data.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static bool error = false;
|
||||
|
||||
void verify(bool expectFailMatch, string type, string input,
|
||||
bool match, string expectStr, string gotStr)
|
||||
{
|
||||
bool match, string expectStr, string gotStr) {
|
||||
match = match && expectStr == gotStr;
|
||||
if (expectFailMatch) {
|
||||
if (match) {
|
||||
@@ -46,8 +47,7 @@ void verify(bool expectFailMatch, string type, string input,
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
DataType* type = DataTypeList::getInstance()->get("TEM_P");
|
||||
if (type == NULL) {
|
||||
cout << "datatype not registered" << endl;
|
||||
@@ -108,7 +108,7 @@ int main()
|
||||
fields = NULL;
|
||||
}
|
||||
vector<string>::iterator it = entries.begin();
|
||||
result = DataField::create(it, entries.end(), templates, fields, isSet, false, (mstr[1]==BROADCAST || isMaster(mstr[1])));
|
||||
result = DataField::create(it, entries.end(), templates, fields, isSet, false, (mstr[1] == BROADCAST || isMaster(mstr[1])));
|
||||
if (result != RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": create error: " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
@@ -145,7 +145,7 @@ int main()
|
||||
if (result >= RESULT_OK) {
|
||||
result = fields->read(pt_slaveData, sstr, 0, output, 0, -1, !output.str().empty());
|
||||
}
|
||||
if (failedRead)
|
||||
if (failedRead) {
|
||||
if (result >= RESULT_OK) {
|
||||
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
|
||||
<< "< error: unexpectedly succeeded" << endl;
|
||||
@@ -154,20 +154,20 @@ int main()
|
||||
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
|
||||
<< "< OK" << endl;
|
||||
}
|
||||
else if (result < RESULT_OK) {
|
||||
} else if (result < RESULT_OK) {
|
||||
cout << " read " << fields->getName() << " >" << check[2] << " " << check[3]
|
||||
<< "< error: " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
bool match = strcasecmp(output.str().c_str(), expectStr.c_str()) == 0;
|
||||
verify(failedReadMatch, "read", check[2], match, expectStr, output.str());
|
||||
}
|
||||
|
||||
istringstream input(expectStr);
|
||||
result = fields->write(input, pt_masterData, writeMstr, 0);
|
||||
if (result >= RESULT_OK)
|
||||
if (result >= RESULT_OK) {
|
||||
result = fields->write(input, pt_slaveData, writeSstr, 0);
|
||||
}
|
||||
if (failedWrite) {
|
||||
if (result >= RESULT_OK) {
|
||||
cout << " failed write " << fields->getName() << " >"
|
||||
@@ -177,8 +177,7 @@ int main()
|
||||
cout << " failed write " << fields->getName() << " >"
|
||||
<< expectStr << "< OK" << endl;
|
||||
}
|
||||
}
|
||||
else if (result < RESULT_OK) {
|
||||
} else if (result < RESULT_OK) {
|
||||
cout << " write " << fields->getName() << " >" << expectStr
|
||||
<< "< error: " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
@@ -191,6 +190,5 @@ int main()
|
||||
}
|
||||
|
||||
delete templates;
|
||||
|
||||
return error ? 1 : 0;
|
||||
}
|
||||
|
||||
+189
-199
@@ -21,12 +21,13 @@
|
||||
#endif
|
||||
|
||||
#include "data.h"
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -39,14 +40,13 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
DataFieldTemplates* templates, DataField*& returnField,
|
||||
const bool isWriteMessage,
|
||||
const bool isTemplate, const bool isBroadcastOrMasterDestination,
|
||||
const unsigned char maxFieldLength)
|
||||
{
|
||||
const unsigned char maxFieldLength) {
|
||||
vector<SingleDataField*> fields;
|
||||
string firstName, firstComment;
|
||||
result_t result = RESULT_OK;
|
||||
if (it == end)
|
||||
if (it == end) {
|
||||
return RESULT_ERR_EOF;
|
||||
|
||||
}
|
||||
while (it != end && result == RESULT_OK) {
|
||||
string unit, comment;
|
||||
PartType partType;
|
||||
@@ -58,8 +58,9 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
// std: name,part,basetype[:len]|template[:name][,[divisor|values][,[unit][,[comment]]]]
|
||||
const string name = *it++; // name
|
||||
if (it == end) {
|
||||
if (!name.empty())
|
||||
if (!name.empty()) {
|
||||
result = RESULT_ERR_MISSING_TYPE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -69,8 +70,9 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
const char* partStr = (*it++).c_str(); // part
|
||||
hasPartStr = partStr[0] != 0;
|
||||
if (it == end) {
|
||||
if (!name.empty() || hasPartStr)
|
||||
if (!name.empty() || hasPartStr) {
|
||||
result = RESULT_ERR_MISSING_TYPE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (isBroadcastOrMasterDestination
|
||||
@@ -110,7 +112,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
if (equalPos == string::npos) {
|
||||
divisor = parseSignedInt(divisorStr.c_str(), 10, -MAX_DIVISOR, MAX_DIVISOR, result);
|
||||
} else if (equalPos == 0 && divisorStr.length() > 1) {
|
||||
verifyValue = divisorStr[1]=='='; // == forced verification of constant value
|
||||
verifyValue = divisorStr[1] == '='; // == forced verification of constant value
|
||||
if (verifyValue && divisorStr.length() == 1) {
|
||||
result = RESULT_ERR_INVALID_LIST;
|
||||
break;
|
||||
@@ -188,7 +190,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
length = 0; // no length specified
|
||||
typeName = token;
|
||||
} else {
|
||||
if (pos+2==token.length() && token[pos+1]=='*') {
|
||||
if (pos+2 == token.length() && token[pos+1] == '*') {
|
||||
length = REMAIN_LEN;
|
||||
} else {
|
||||
length = (unsigned char)parseInt(token.substr(pos+1).c_str(), 10, 1, maxFieldLength, result);
|
||||
@@ -245,8 +247,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void DataField::dumpString(ostream& output, const string str, const bool prependFieldSeparator)
|
||||
{
|
||||
void DataField::dumpString(ostream& output, const string str, const bool prependFieldSeparator) {
|
||||
if (prependFieldSeparator) {
|
||||
output << FIELD_SEPARATOR;
|
||||
}
|
||||
@@ -260,9 +261,8 @@ void DataField::dumpString(ostream& output, const string str, const bool prepend
|
||||
result_t SingleDataField::create(const string id, const unsigned char length,
|
||||
const string name, const string comment, const string unit,
|
||||
const PartType partType, int divisor, map<unsigned int, string> values,
|
||||
const string constantValue, const bool verifyValue, SingleDataField* &returnField)
|
||||
{
|
||||
DataType* dataType = DataTypeList::getInstance()->get(id, length==REMAIN_LEN ? (unsigned char)0 : length);
|
||||
const string constantValue, const bool verifyValue, SingleDataField* &returnField) {
|
||||
DataType* dataType = DataTypeList::getInstance()->get(id, length == REMAIN_LEN ? (unsigned char)0 : length);
|
||||
if (!dataType) {
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
@@ -298,7 +298,7 @@ result_t SingleDataField::create(const string id, const unsigned char length,
|
||||
values[numType->getMinValue() + i] = dayNames[i];
|
||||
}
|
||||
result_t result = numType->derive(divisor, bitCount, numType);
|
||||
if (result!=RESULT_OK) {
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
if (values.empty()) {
|
||||
@@ -318,15 +318,15 @@ result_t SingleDataField::create(const string id, const unsigned char length,
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void SingleDataField::dump(ostream& output)
|
||||
{
|
||||
void SingleDataField::dump(ostream& output) {
|
||||
output << setw(0) << dec; // initialize formatting
|
||||
dumpString(output, m_name, false);
|
||||
output << FIELD_SEPARATOR;
|
||||
if (m_partType == pt_masterData)
|
||||
if (m_partType == pt_masterData) {
|
||||
output << "m";
|
||||
else if (m_partType == pt_slaveData)
|
||||
} else if (m_partType == pt_slaveData) {
|
||||
output << "s";
|
||||
}
|
||||
output << FIELD_SEPARATOR;
|
||||
m_dataType->dump(output, m_length);
|
||||
dumpString(output, m_unit);
|
||||
@@ -336,11 +336,10 @@ void SingleDataField::dump(ostream& output)
|
||||
|
||||
result_t SingleDataField::read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
unsigned int& output, const char* fieldName, signed char fieldIndex)
|
||||
{
|
||||
if (partType != m_partType)
|
||||
unsigned int& output, const char* fieldName, signed char fieldIndex) {
|
||||
if (partType != m_partType) {
|
||||
return RESULT_EMPTY;
|
||||
|
||||
}
|
||||
switch (m_partType)
|
||||
{
|
||||
case pt_masterData:
|
||||
@@ -352,7 +351,7 @@ result_t SingleDataField::read(const PartType partType,
|
||||
default:
|
||||
return RESULT_ERR_INVALID_PART;
|
||||
}
|
||||
bool remainder = m_length==REMAIN_LEN && m_dataType->isAdjustableLength();
|
||||
bool remainder = m_length == REMAIN_LEN && m_dataType->isAdjustableLength();
|
||||
if (offset + (remainder?1:m_length) > data.size()) {
|
||||
return RESULT_ERR_INVALID_POS;
|
||||
}
|
||||
@@ -365,8 +364,7 @@ result_t SingleDataField::read(const PartType partType,
|
||||
result_t SingleDataField::read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
ostringstream& output, OutputFormat outputFormat, signed char outputIndex,
|
||||
bool leadingSeparator, const char* fieldName, signed char fieldIndex)
|
||||
{
|
||||
bool leadingSeparator, const char* fieldName, signed char fieldIndex) {
|
||||
if (partType != m_partType) {
|
||||
return RESULT_OK;
|
||||
}
|
||||
@@ -381,7 +379,7 @@ result_t SingleDataField::read(const PartType partType,
|
||||
default:
|
||||
return RESULT_ERR_INVALID_PART;
|
||||
}
|
||||
bool remainder = m_length==REMAIN_LEN && m_dataType->isAdjustableLength();
|
||||
bool remainder = m_length == REMAIN_LEN && m_dataType->isAdjustableLength();
|
||||
if (offset + (remainder?1:m_length) > data.size()) {
|
||||
return RESULT_ERR_INVALID_POS;
|
||||
}
|
||||
@@ -393,8 +391,8 @@ result_t SingleDataField::read(const PartType partType,
|
||||
if (leadingSeparator) {
|
||||
output << ",";
|
||||
}
|
||||
if (outputIndex>=0 || m_name.empty() || !(outputFormat & OF_NAMES)) {
|
||||
output << "\n \"" << static_cast<signed int>(outputIndex<0?0:outputIndex) << "\": {\"name\": \"" << m_name << "\"" << ", \"value\": ";
|
||||
if (outputIndex >= 0 || m_name.empty() || !(outputFormat & OF_NAMES)) {
|
||||
output << "\n \"" << static_cast<signed int>(outputIndex < 0 ? 0 : outputIndex) << "\": {\"name\": \"" << m_name << "\"" << ", \"value\": ";
|
||||
} else {
|
||||
output << "\n \"" << m_name << "\": {\"value\": ";
|
||||
}
|
||||
@@ -407,7 +405,7 @@ result_t SingleDataField::read(const PartType partType,
|
||||
}
|
||||
}
|
||||
|
||||
result_t result = readSymbols(data, m_partType==pt_masterData, offset, output, outputFormat);
|
||||
result_t result = readSymbols(data, m_partType == pt_masterData, offset, output, outputFormat);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -433,8 +431,7 @@ result_t SingleDataField::read(const PartType partType,
|
||||
|
||||
result_t SingleDataField::write(istringstream& input,
|
||||
const PartType partType, SymbolString& data,
|
||||
unsigned char offset, char separator, unsigned char* length)
|
||||
{
|
||||
unsigned char offset, char separator, unsigned char* length) {
|
||||
if (partType != m_partType) {
|
||||
return RESULT_OK;
|
||||
}
|
||||
@@ -449,50 +446,52 @@ result_t SingleDataField::write(istringstream& input,
|
||||
default:
|
||||
return RESULT_ERR_INVALID_PART;
|
||||
}
|
||||
return writeSymbols(input, (const unsigned char)offset, data, m_partType==pt_masterData, length);
|
||||
return writeSymbols(input, (const unsigned char)offset, data, m_partType == pt_masterData, length);
|
||||
}
|
||||
|
||||
result_t SingleDataField::readSymbols(SymbolString& input, const bool isMaster,
|
||||
const unsigned char offset,
|
||||
ostringstream& output, OutputFormat outputFormat)
|
||||
{
|
||||
ostringstream& output, OutputFormat outputFormat) {
|
||||
return m_dataType->readSymbols(input, isMaster, offset, m_length, output, outputFormat);
|
||||
}
|
||||
|
||||
result_t SingleDataField::writeSymbols(istringstream& input,
|
||||
const unsigned char offset,
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength)
|
||||
{
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength) {
|
||||
return m_dataType->writeSymbols(input, offset, m_length, output, isMaster, usedLength);
|
||||
}
|
||||
|
||||
SingleDataField* SingleDataField::clone()
|
||||
{
|
||||
SingleDataField* SingleDataField::clone() {
|
||||
return new SingleDataField(*this);
|
||||
}
|
||||
|
||||
result_t SingleDataField::derive(string name, string comment,
|
||||
string unit, const PartType partType,
|
||||
int divisor, map<unsigned int, string> values,
|
||||
vector<SingleDataField*>& fields)
|
||||
{
|
||||
if (m_partType != pt_any && partType == pt_any)
|
||||
vector<SingleDataField*>& fields) {
|
||||
if (m_partType != pt_any && partType == pt_any) {
|
||||
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
|
||||
}
|
||||
bool numeric = m_dataType->isNumeric();
|
||||
if (!numeric && (divisor != 0 || !values.empty()))
|
||||
if (!numeric && (divisor != 0 || !values.empty())) {
|
||||
return RESULT_ERR_INVALID_ARG; // cannot set divisor or values for non-numeric field
|
||||
if (name.empty())
|
||||
}
|
||||
if (name.empty()) {
|
||||
name = m_name;
|
||||
if (comment.empty())
|
||||
}
|
||||
if (comment.empty()) {
|
||||
comment = m_comment;
|
||||
if (unit.empty())
|
||||
}
|
||||
if (unit.empty()) {
|
||||
unit = m_unit;
|
||||
}
|
||||
DataType* dataType = m_dataType;
|
||||
if (numeric) {
|
||||
NumberDataType* numType = (NumberDataType*)m_dataType;
|
||||
result_t result = numType->derive(divisor, 0, numType);
|
||||
if (result != RESULT_OK)
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
dataType = numType;
|
||||
}
|
||||
if (values.empty()) {
|
||||
@@ -503,23 +502,20 @@ result_t SingleDataField::derive(string name, string comment,
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
bool SingleDataField::hasField(const char* fieldName, bool numeric)
|
||||
{
|
||||
bool SingleDataField::hasField(const char* fieldName, bool numeric) {
|
||||
bool numericType = m_dataType->isNumeric();
|
||||
return numeric==numericType && (fieldName==NULL || fieldName==m_name);
|
||||
return numeric == numericType && (fieldName == NULL || fieldName == m_name);
|
||||
}
|
||||
|
||||
unsigned char SingleDataField::getLength(PartType partType, unsigned char maxLength)
|
||||
{
|
||||
unsigned char SingleDataField::getLength(PartType partType, unsigned char maxLength) {
|
||||
if (partType != m_partType) {
|
||||
return (unsigned char)0;
|
||||
}
|
||||
bool remainder = m_length==REMAIN_LEN && m_dataType->isAdjustableLength();
|
||||
bool remainder = m_length == REMAIN_LEN && m_dataType->isAdjustableLength();
|
||||
return remainder ? maxLength : m_length;
|
||||
}
|
||||
|
||||
bool SingleDataField::hasFullByteOffset(bool after)
|
||||
{
|
||||
bool SingleDataField::hasFullByteOffset(bool after) {
|
||||
if (m_length > 1 || !m_dataType->isNumeric()) {
|
||||
return true;
|
||||
}
|
||||
@@ -529,49 +525,50 @@ bool SingleDataField::hasFullByteOffset(bool after)
|
||||
}
|
||||
|
||||
|
||||
ValueListDataField* ValueListDataField::clone()
|
||||
{
|
||||
ValueListDataField* ValueListDataField::clone() {
|
||||
return new ValueListDataField(*this);
|
||||
}
|
||||
|
||||
result_t ValueListDataField::derive(string name, string comment,
|
||||
string unit, const PartType partType,
|
||||
int divisor, map<unsigned int, string> values,
|
||||
vector<SingleDataField*>& fields)
|
||||
{
|
||||
if (m_partType != pt_any && partType == pt_any)
|
||||
vector<SingleDataField*>& fields) {
|
||||
if (m_partType != pt_any && partType == pt_any) {
|
||||
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
|
||||
if (name.empty())
|
||||
}
|
||||
if (name.empty()) {
|
||||
name = m_name;
|
||||
if (comment.empty())
|
||||
}
|
||||
if (comment.empty()) {
|
||||
comment = m_comment;
|
||||
if (unit.empty())
|
||||
}
|
||||
if (unit.empty()) {
|
||||
unit = m_unit;
|
||||
if (divisor != 0 && divisor != 1)
|
||||
}
|
||||
if (divisor != 0 && divisor != 1) {
|
||||
return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field
|
||||
|
||||
}
|
||||
if (!values.empty()) {
|
||||
NumberDataType* num = (NumberDataType*)m_dataType;
|
||||
if (values.begin()->first < num->getMinValue() || values.rbegin()->first > num->getMaxValue())
|
||||
if (values.begin()->first < num->getMinValue() || values.rbegin()->first > num->getMaxValue()) {
|
||||
return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field
|
||||
}
|
||||
else
|
||||
}
|
||||
} else {
|
||||
values = m_values;
|
||||
|
||||
}
|
||||
fields.push_back(new ValueListDataField(name, comment, unit, (NumberDataType*)m_dataType, partType, m_length, values));
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void ValueListDataField::dump(ostream& output)
|
||||
{
|
||||
void ValueListDataField::dump(ostream& output) {
|
||||
output << setw(0) << dec; // initialize formatting
|
||||
dumpString(output, m_name, false);
|
||||
output << FIELD_SEPARATOR;
|
||||
if (m_partType == pt_masterData)
|
||||
if (m_partType == pt_masterData) {
|
||||
output << "m";
|
||||
else if (m_partType == pt_slaveData)
|
||||
} else if (m_partType == pt_slaveData) {
|
||||
output << "s";
|
||||
}
|
||||
output << FIELD_SEPARATOR;
|
||||
if (!m_dataType->dump(output, m_length)) { // no divisor appended
|
||||
for (map<unsigned int, string>::iterator it = m_values.begin(); it != m_values.end(); it++) {
|
||||
@@ -587,13 +584,13 @@ void ValueListDataField::dump(ostream& output)
|
||||
|
||||
result_t ValueListDataField::readSymbols(SymbolString& input, const bool isMaster,
|
||||
const unsigned char offset,
|
||||
ostringstream& output, OutputFormat outputFormat)
|
||||
{
|
||||
ostringstream& output, OutputFormat outputFormat) {
|
||||
unsigned int value = 0;
|
||||
|
||||
result_t result = m_dataType->readRawValue(input, offset, m_length, value);
|
||||
if (result != RESULT_OK)
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
map<unsigned int, string>::iterator it = m_values.find(value);
|
||||
if (it == m_values.end() && value != m_dataType->getReplacement()) {
|
||||
// fall back to raw value in input
|
||||
@@ -601,85 +598,90 @@ result_t ValueListDataField::readSymbols(SymbolString& input, const bool isMaste
|
||||
return RESULT_OK;
|
||||
}
|
||||
if (it == m_values.end()) {
|
||||
if (outputFormat & OF_JSON)
|
||||
if (outputFormat & OF_JSON) {
|
||||
output << "null";
|
||||
else if (value == m_dataType->getReplacement())
|
||||
} else if (value == m_dataType->getReplacement()) {
|
||||
output << NULL_VALUE;
|
||||
} else if (outputFormat & OF_NUMERIC)
|
||||
}
|
||||
} else if (outputFormat & OF_NUMERIC) {
|
||||
output << setw(0) << dec << static_cast<unsigned>(value);
|
||||
else if (outputFormat & OF_JSON)
|
||||
} else if (outputFormat & OF_JSON) {
|
||||
output << '"' << it->second << '"';
|
||||
else
|
||||
} else {
|
||||
output << it->second;
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t ValueListDataField::writeSymbols(istringstream& input,
|
||||
const unsigned char offset,
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength)
|
||||
{
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength) {
|
||||
NumberDataType* numType = (NumberDataType*)m_dataType;
|
||||
if (isIgnored())
|
||||
if (isIgnored()) {
|
||||
return numType->writeRawValue(numType->getReplacement(), offset, m_length, output, usedLength); // replacement value
|
||||
|
||||
}
|
||||
const char* str = input.str().c_str();
|
||||
|
||||
for (map<unsigned int, string>::iterator it = m_values.begin(); it != m_values.end(); it++)
|
||||
if (it->second.compare(str) == 0)
|
||||
for (map<unsigned int, string>::iterator it = m_values.begin(); it != m_values.end(); it++) {
|
||||
if (it->second.compare(str) == 0) {
|
||||
return numType->writeRawValue(it->first, offset, m_length, output, usedLength);
|
||||
|
||||
if (strcasecmp(str, NULL_VALUE) == 0)
|
||||
}
|
||||
}
|
||||
if (strcasecmp(str, NULL_VALUE) == 0) {
|
||||
return numType->writeRawValue(numType->getReplacement(), offset, m_length, output, usedLength); // replacement value
|
||||
|
||||
}
|
||||
char* strEnd = NULL; // fall back to raw value in input
|
||||
unsigned int value;
|
||||
value = (unsigned int)strtoul(str, &strEnd, 10);
|
||||
if (strEnd == NULL || strEnd == str || (*strEnd != 0 && *strEnd != '.'))
|
||||
if (strEnd == NULL || strEnd == str || (*strEnd != 0 && *strEnd != '.')) {
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
if (m_values.find(value) != m_values.end())
|
||||
}
|
||||
if (m_values.find(value) != m_values.end()) {
|
||||
return numType->writeRawValue(value, offset, m_length, output, usedLength);
|
||||
|
||||
}
|
||||
return RESULT_ERR_NOTFOUND; // value assignment not found
|
||||
}
|
||||
|
||||
|
||||
ConstantDataField* ConstantDataField::clone()
|
||||
{
|
||||
ConstantDataField* ConstantDataField::clone() {
|
||||
return new ConstantDataField(*this);
|
||||
}
|
||||
|
||||
result_t ConstantDataField::derive(string name, string comment,
|
||||
string unit, const PartType partType,
|
||||
int divisor, map<unsigned int, string> values,
|
||||
vector<SingleDataField*>& fields)
|
||||
{
|
||||
if (m_partType != pt_any && partType == pt_any)
|
||||
vector<SingleDataField*>& fields) {
|
||||
if (m_partType != pt_any && partType == pt_any) {
|
||||
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
|
||||
if (name.empty())
|
||||
}
|
||||
if (name.empty()) {
|
||||
name = m_name;
|
||||
if (comment.empty())
|
||||
}
|
||||
if (comment.empty()) {
|
||||
comment = m_comment;
|
||||
if (unit.empty())
|
||||
}
|
||||
if (unit.empty()) {
|
||||
unit = m_unit;
|
||||
if (divisor != 0)
|
||||
}
|
||||
if (divisor != 0) {
|
||||
return RESULT_ERR_INVALID_ARG; // cannot use other than current divisor for constant value field
|
||||
}
|
||||
if (!values.empty()) {
|
||||
return RESULT_ERR_INVALID_ARG; // cannot use value list for constant value field
|
||||
}
|
||||
fields.push_back(new ConstantDataField(name, comment, unit, m_dataType, partType, m_length, m_value, m_verify));
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void ConstantDataField::dump(ostream& output)
|
||||
{
|
||||
void ConstantDataField::dump(ostream& output) {
|
||||
output << setw(0) << dec; // initialize formatting
|
||||
dumpString(output, m_name, false);
|
||||
output << FIELD_SEPARATOR;
|
||||
if (m_partType == pt_masterData)
|
||||
if (m_partType == pt_masterData) {
|
||||
output << "m";
|
||||
else if (m_partType == pt_slaveData)
|
||||
} else if (m_partType == pt_slaveData) {
|
||||
output << "s";
|
||||
}
|
||||
output << FIELD_SEPARATOR;
|
||||
if (!m_dataType->dump(output, m_length)) { // no divisor appended
|
||||
output << (m_verify?"==":"=") << m_value;
|
||||
@@ -690,8 +692,7 @@ void ConstantDataField::dump(ostream& output)
|
||||
|
||||
result_t ConstantDataField::readSymbols(SymbolString& input, const bool isMaster,
|
||||
const unsigned char offset,
|
||||
ostringstream& output, OutputFormat outputFormat)
|
||||
{
|
||||
ostringstream& output, OutputFormat outputFormat) {
|
||||
ostringstream coutput;
|
||||
result_t result = SingleDataField::readSymbols(input, isMaster, offset, coutput, 0);
|
||||
if (result != RESULT_OK) {
|
||||
@@ -700,7 +701,7 @@ result_t ConstantDataField::readSymbols(SymbolString& input, const bool isMaster
|
||||
if (m_verify) {
|
||||
string value = coutput.str();
|
||||
FileReader::trim(value);
|
||||
if (value!=m_value) {
|
||||
if (value != m_value) {
|
||||
return RESULT_ERR_OUT_OF_RANGE;
|
||||
}
|
||||
}
|
||||
@@ -709,8 +710,7 @@ result_t ConstantDataField::readSymbols(SymbolString& input, const bool isMaster
|
||||
|
||||
result_t ConstantDataField::writeSymbols(istringstream& input,
|
||||
const unsigned char offset,
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength)
|
||||
{
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength) {
|
||||
istringstream cinput(m_value);
|
||||
return SingleDataField::writeSymbols(cinput, offset, output, isMaster, usedLength);
|
||||
}
|
||||
@@ -718,9 +718,8 @@ result_t ConstantDataField::writeSymbols(istringstream& input,
|
||||
|
||||
DataFieldSet* DataFieldSet::s_identFields = NULL;
|
||||
|
||||
DataFieldSet* DataFieldSet::getIdentFields()
|
||||
{
|
||||
if (s_identFields==NULL) {
|
||||
DataFieldSet* DataFieldSet::getIdentFields() {
|
||||
if (s_identFields == NULL) {
|
||||
NumberDataType* uchDataType = (NumberDataType*)DataTypeList::getInstance()->get("UCH");
|
||||
StringDataType* stringDataType = (StringDataType*)DataTypeList::getInstance()->get("STR");
|
||||
NumberDataType* pinDataType = (NumberDataType*)DataTypeList::getInstance()->get("PIN");
|
||||
@@ -760,16 +759,14 @@ DataFieldSet* DataFieldSet::getIdentFields()
|
||||
return s_identFields;
|
||||
}
|
||||
|
||||
DataFieldSet::~DataFieldSet()
|
||||
{
|
||||
DataFieldSet::~DataFieldSet() {
|
||||
while (!m_fields.empty()) {
|
||||
delete m_fields.back();
|
||||
m_fields.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
DataFieldSet* DataFieldSet::clone()
|
||||
{
|
||||
DataFieldSet* DataFieldSet::clone() {
|
||||
vector<SingleDataField*> fields;
|
||||
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
|
||||
fields.push_back((*it)->clone());
|
||||
@@ -777,23 +774,22 @@ DataFieldSet* DataFieldSet::clone()
|
||||
return new DataFieldSet(m_name, m_comment, fields);
|
||||
}
|
||||
|
||||
unsigned char DataFieldSet::getLength(PartType partType, unsigned char maxLength)
|
||||
{
|
||||
unsigned char DataFieldSet::getLength(PartType partType, unsigned char maxLength) {
|
||||
unsigned char length = 0;
|
||||
|
||||
bool previousFullByteOffset[] = { true, true, true, true };
|
||||
|
||||
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
|
||||
SingleDataField* field = *it;
|
||||
if (field->getPartType() == partType) {
|
||||
if (!previousFullByteOffset[partType] && !field->hasFullByteOffset(false))
|
||||
if (!previousFullByteOffset[partType] && !field->hasFullByteOffset(false)) {
|
||||
length--;
|
||||
|
||||
}
|
||||
unsigned char fieldLength = field->getLength(partType, maxLength);
|
||||
if (fieldLength>=maxLength)
|
||||
if (fieldLength >= maxLength) {
|
||||
maxLength = 0;
|
||||
else
|
||||
} else {
|
||||
maxLength = (unsigned char)(maxLength-fieldLength);
|
||||
}
|
||||
length = (unsigned char)(length + fieldLength);
|
||||
|
||||
previousFullByteOffset[partType] = field->hasFullByteOffset(true);
|
||||
@@ -803,12 +799,11 @@ unsigned char DataFieldSet::getLength(PartType partType, unsigned char maxLength
|
||||
return length;
|
||||
}
|
||||
|
||||
string DataFieldSet::getName(signed char fieldIndex)
|
||||
{
|
||||
if (fieldIndex<0) {
|
||||
string DataFieldSet::getName(signed char fieldIndex) {
|
||||
if (fieldIndex < 0) {
|
||||
return m_name;
|
||||
}
|
||||
if ((unsigned char)fieldIndex>=m_fields.size()) {
|
||||
if ((unsigned char)fieldIndex >= m_fields.size()) {
|
||||
return "";
|
||||
}
|
||||
if (m_uniqueNames) {
|
||||
@@ -822,33 +817,33 @@ string DataFieldSet::getName(signed char fieldIndex)
|
||||
result_t DataFieldSet::derive(string name, string comment,
|
||||
string unit, const PartType partType,
|
||||
int divisor, map<unsigned int, string> values,
|
||||
vector<SingleDataField*>& fields)
|
||||
{
|
||||
if (!values.empty())
|
||||
vector<SingleDataField*>& fields) {
|
||||
if (!values.empty()) {
|
||||
return RESULT_ERR_INVALID_ARG; // value list not allowed in set derive
|
||||
}
|
||||
bool first = true;
|
||||
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
|
||||
result_t result = (*it)->derive("", first?comment:"", first?unit:"", partType, divisor, values, fields);
|
||||
if (result != RESULT_OK)
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
bool DataFieldSet::hasField(const char* fieldName, bool numeric)
|
||||
{
|
||||
bool DataFieldSet::hasField(const char* fieldName, bool numeric) {
|
||||
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
|
||||
SingleDataField* field = *it;
|
||||
if (field->hasField(fieldName, numeric)==0)
|
||||
if (field->hasField(fieldName, numeric) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DataFieldSet::dump(ostream& output)
|
||||
{
|
||||
void DataFieldSet::dump(ostream& output) {
|
||||
bool first = true;
|
||||
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
|
||||
if (first) {
|
||||
@@ -862,22 +857,20 @@ void DataFieldSet::dump(ostream& output)
|
||||
|
||||
result_t DataFieldSet::read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
unsigned int& output, const char* fieldName, signed char fieldIndex)
|
||||
{
|
||||
unsigned int& output, const char* fieldName, signed char fieldIndex) {
|
||||
bool previousFullByteOffset = true, found = false, findFieldIndex = fieldName != NULL && fieldIndex >= 0;
|
||||
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
|
||||
SingleDataField* field = *it;
|
||||
if (partType != pt_any && field->getPartType() != partType)
|
||||
if (partType != pt_any && field->getPartType() != partType) {
|
||||
continue;
|
||||
|
||||
if (!previousFullByteOffset && !field->hasFullByteOffset(false))
|
||||
}
|
||||
if (!previousFullByteOffset && !field->hasFullByteOffset(false)) {
|
||||
offset--;
|
||||
|
||||
}
|
||||
result_t result = field->read(partType, data, offset, output, fieldName, fieldIndex);
|
||||
|
||||
if (result < RESULT_OK)
|
||||
if (result < RESULT_OK) {
|
||||
return result;
|
||||
|
||||
}
|
||||
offset = (unsigned char)(offset + field->getLength(partType, (unsigned char)(data.size()-offset)));
|
||||
previousFullByteOffset = field->hasFullByteOffset(true);
|
||||
if (result != RESULT_EMPTY) {
|
||||
@@ -885,8 +878,9 @@ result_t DataFieldSet::read(const PartType partType,
|
||||
}
|
||||
if (findFieldIndex && fieldName == field->getName()) {
|
||||
if (fieldIndex == 0) {
|
||||
if (!found)
|
||||
if (!found) {
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
break;
|
||||
}
|
||||
fieldIndex--;
|
||||
@@ -903,26 +897,26 @@ result_t DataFieldSet::read(const PartType partType,
|
||||
result_t DataFieldSet::read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
ostringstream& output, OutputFormat outputFormat, signed char outputIndex,
|
||||
bool leadingSeparator, const char* fieldName, signed char fieldIndex)
|
||||
{
|
||||
bool leadingSeparator, const char* fieldName, signed char fieldIndex) {
|
||||
bool previousFullByteOffset = true, found = false, findFieldIndex = fieldName != NULL && fieldIndex >= 0;
|
||||
if (!m_uniqueNames && outputIndex<0)
|
||||
if (!m_uniqueNames && outputIndex < 0) {
|
||||
outputIndex = 0;
|
||||
}
|
||||
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
|
||||
SingleDataField* field = *it;
|
||||
if (partType != pt_any && field->getPartType() != partType) {
|
||||
if (outputIndex>=0 && !field->isIgnored())
|
||||
if (outputIndex >= 0 && !field->isIgnored()) {
|
||||
outputIndex++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!previousFullByteOffset && !field->hasFullByteOffset(false))
|
||||
if (!previousFullByteOffset && !field->hasFullByteOffset(false)) {
|
||||
offset--;
|
||||
|
||||
}
|
||||
result_t result = field->read(partType, data, offset, output, outputFormat, outputIndex, leadingSeparator, fieldName, fieldIndex);
|
||||
|
||||
if (result < RESULT_OK)
|
||||
if (result < RESULT_OK) {
|
||||
return result;
|
||||
|
||||
}
|
||||
offset = (unsigned char)(offset + field->getLength(partType, (unsigned char)(data.size()-offset)));
|
||||
previousFullByteOffset = field->hasFullByteOffset(true);
|
||||
if (result != RESULT_EMPTY) {
|
||||
@@ -931,14 +925,16 @@ result_t DataFieldSet::read(const PartType partType,
|
||||
}
|
||||
if (findFieldIndex && fieldName == field->getName()) {
|
||||
if (fieldIndex == 0) {
|
||||
if (!found)
|
||||
if (!found) {
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
break;
|
||||
}
|
||||
fieldIndex--;
|
||||
}
|
||||
if (outputIndex>=0 && !field->isIgnored())
|
||||
if (outputIndex >= 0 && !field->isIgnored()) {
|
||||
outputIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
@@ -957,57 +953,54 @@ result_t DataFieldSet::read(const PartType partType,
|
||||
|
||||
result_t DataFieldSet::write(istringstream& input,
|
||||
const PartType partType, SymbolString& data,
|
||||
unsigned char offset, char separator, unsigned char* length)
|
||||
{
|
||||
unsigned char offset, char separator, unsigned char* length) {
|
||||
string token;
|
||||
|
||||
bool previousFullByteOffset = true;
|
||||
unsigned char baseOffset = offset;
|
||||
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
|
||||
SingleDataField* field = *it;
|
||||
if (partType != pt_any && field->getPartType() != partType)
|
||||
if (partType != pt_any && field->getPartType() != partType) {
|
||||
continue;
|
||||
|
||||
if (!previousFullByteOffset && !field->hasFullByteOffset(false))
|
||||
}
|
||||
if (!previousFullByteOffset && !field->hasFullByteOffset(false)) {
|
||||
offset--;
|
||||
|
||||
}
|
||||
result_t result;
|
||||
unsigned char fieldLength;
|
||||
if (m_fields.size() > 1) {
|
||||
if (field->isIgnored())
|
||||
if (field->isIgnored()) {
|
||||
token.clear();
|
||||
else if (!getline(input, token, separator))
|
||||
} else if (!getline(input, token, separator)) {
|
||||
token.clear();
|
||||
|
||||
}
|
||||
istringstream single(token);
|
||||
result = (*it)->write(single, partType, data, offset, separator, &fieldLength);
|
||||
}
|
||||
else
|
||||
} else {
|
||||
result = (*it)->write(input, partType, data, offset, separator, &fieldLength);
|
||||
|
||||
if (result != RESULT_OK)
|
||||
}
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
|
||||
}
|
||||
offset = (unsigned char)(offset+fieldLength);
|
||||
previousFullByteOffset = field->hasFullByteOffset(true);
|
||||
}
|
||||
|
||||
if (length!=NULL)
|
||||
if (length != NULL) {
|
||||
*length = (unsigned char)(offset-baseOffset);
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
DataFieldTemplates::DataFieldTemplates(DataFieldTemplates& other)
|
||||
: FileReader::FileReader(false)
|
||||
{
|
||||
: FileReader::FileReader(false) {
|
||||
for (map<string, DataField*>::iterator it = other.m_fieldsByName.begin(); it != other.m_fieldsByName.end(); it++) {
|
||||
m_fieldsByName[it->first] = it->second->clone();
|
||||
}
|
||||
}
|
||||
|
||||
void DataFieldTemplates::clear()
|
||||
{
|
||||
void DataFieldTemplates::clear() {
|
||||
for (map<string, DataField*>::iterator it = m_fieldsByName.begin(); it != m_fieldsByName.end(); it++) {
|
||||
delete it->second;
|
||||
it->second = NULL;
|
||||
@@ -1015,58 +1008,55 @@ void DataFieldTemplates::clear()
|
||||
m_fieldsByName.clear();
|
||||
}
|
||||
|
||||
result_t DataFieldTemplates::add(DataField* field, string name, bool replace)
|
||||
{
|
||||
if (name.length() == 0)
|
||||
result_t DataFieldTemplates::add(DataField* field, string name, bool replace) {
|
||||
if (name.length() == 0) {
|
||||
name = field->getName();
|
||||
}
|
||||
map<string, DataField*>::iterator it = m_fieldsByName.find(name);
|
||||
if (it != m_fieldsByName.end()) {
|
||||
if (!replace)
|
||||
if (!replace) {
|
||||
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
|
||||
|
||||
}
|
||||
delete it->second;
|
||||
it->second = field;
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
m_fieldsByName[name] = field;
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t DataFieldTemplates::addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end,
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
|
||||
const string& filename, unsigned int lineNo)
|
||||
{
|
||||
const string& filename, unsigned int lineNo) {
|
||||
vector<string>::iterator restart = begin;
|
||||
DataField* field = NULL;
|
||||
string name;
|
||||
if (begin != end) {
|
||||
size_t colon = begin->find(':');
|
||||
if (colon!=string::npos) {
|
||||
if (colon != string::npos) {
|
||||
name = begin->substr(0, colon);
|
||||
begin->erase(0, colon+1);
|
||||
}
|
||||
}
|
||||
result_t result = DataField::create(begin, end, this, field, false, true, false);
|
||||
if (result != RESULT_OK)
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
|
||||
}
|
||||
result = add(field, name, true);
|
||||
if (result==RESULT_ERR_DUPLICATE_NAME)
|
||||
if (result == RESULT_ERR_DUPLICATE_NAME) {
|
||||
begin = restart+1; // mark name as invalid
|
||||
if (result != RESULT_OK)
|
||||
}
|
||||
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);
|
||||
if (ref == m_fieldsByName.end())
|
||||
if (ref == m_fieldsByName.end()) {
|
||||
return NULL;
|
||||
|
||||
}
|
||||
return ref->second;
|
||||
}
|
||||
|
||||
+34
-32
@@ -16,19 +16,19 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_DATA_H_
|
||||
#define LIBEBUS_DATA_H_
|
||||
#ifndef LIB_EBUS_DATA_H_
|
||||
#define LIB_EBUS_DATA_H_
|
||||
|
||||
#include "symbol.h"
|
||||
#include "result.h"
|
||||
#include "filereader.h"
|
||||
#include "datatype.h"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "symbol.h"
|
||||
#include "result.h"
|
||||
#include "filereader.h"
|
||||
#include "datatype.h"
|
||||
|
||||
/** @file data.h
|
||||
* Classes related to defining fields based on data types in symbols on the
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
DataFieldTemplates* templates, DataField*& returnField,
|
||||
const bool isWriteMessage,
|
||||
const bool isTemplate, const bool isBroadcastOrMasterDestination,
|
||||
const unsigned char maxFieldLength=MAX_POS);
|
||||
const unsigned char maxFieldLength = MAX_POS);
|
||||
|
||||
/**
|
||||
* Dump the @a string optionally embedded in @a TEXT_SEPARATOR to the output.
|
||||
@@ -101,7 +101,7 @@ public:
|
||||
* @param str the @a string to dump.
|
||||
* @param prependFieldSeparator whether to start with a @a FIELD_SEPARATOR.
|
||||
*/
|
||||
static void dumpString(ostream& output, const string str, const bool prependFieldSeparator=true);
|
||||
static void dumpString(ostream& output, const string str, const bool prependFieldSeparator = true);
|
||||
|
||||
/**
|
||||
* Returns the length of this field (or contained fields) in bytes.
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
* @param maxLength the maximum length for calculating remainder of input.
|
||||
* @return the length of this field (or contained fields) in bytes.
|
||||
*/
|
||||
virtual unsigned char getLength(PartType partType, unsigned char maxLength=MAX_LEN) = 0;
|
||||
virtual unsigned char getLength(PartType partType, unsigned char maxLength = MAX_LEN) = 0;
|
||||
|
||||
/**
|
||||
* Derive a new @a DataField from this field.
|
||||
@@ -132,7 +132,7 @@ public:
|
||||
* @param fieldIndex the index of the field, or -1 for this.
|
||||
* @return the field name, or the index as string if not unique or not available.
|
||||
*/
|
||||
virtual string getName(signed char fieldIndex=-1) { return m_name; }
|
||||
virtual string getName(signed char fieldIndex = -1) { return m_name; }
|
||||
|
||||
/**
|
||||
* Get the field comment.
|
||||
@@ -169,7 +169,7 @@ public:
|
||||
*/
|
||||
virtual result_t read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
unsigned int& output, const char* fieldName=NULL, signed char fieldIndex=-1) = 0;
|
||||
unsigned int& output, const char* fieldName = NULL, signed char fieldIndex = -1) = 0;
|
||||
|
||||
/**
|
||||
* Reads the value from the @a SymbolString.
|
||||
@@ -188,8 +188,8 @@ public:
|
||||
*/
|
||||
virtual result_t read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
ostringstream& output, OutputFormat outputFormat, signed char outputIndex=-1,
|
||||
bool leadingSeparator=false, const char* fieldName=NULL, signed char fieldIndex=-1) = 0;
|
||||
ostringstream& output, OutputFormat outputFormat, signed char outputIndex = -1,
|
||||
bool leadingSeparator = false, const char* fieldName = NULL, signed char fieldIndex = -1) = 0;
|
||||
|
||||
/**
|
||||
* Writes the value to the master or slave @a SymbolString.
|
||||
@@ -203,7 +203,7 @@ public:
|
||||
*/
|
||||
virtual result_t write(istringstream& input,
|
||||
const PartType partType, SymbolString& data,
|
||||
unsigned char offset, char separator=UI_FIELD_SEPARATOR, unsigned char* length=NULL) = 0;
|
||||
unsigned char offset, char separator = UI_FIELD_SEPARATOR, unsigned char* length = NULL) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -287,7 +287,7 @@ public:
|
||||
PartType getPartType() const { return m_partType; }
|
||||
|
||||
// @copydoc
|
||||
virtual unsigned char getLength(PartType partType, unsigned char maxLength=MAX_LEN);
|
||||
virtual unsigned char getLength(PartType partType, unsigned char maxLength = MAX_LEN);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t derive(string name, string comment,
|
||||
@@ -312,18 +312,18 @@ public:
|
||||
// @copydoc
|
||||
virtual result_t read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
unsigned int& output, const char* fieldName=NULL, signed char fieldIndex=-1);
|
||||
unsigned int& output, const char* fieldName = NULL, signed char fieldIndex = -1);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
ostringstream& output, OutputFormat outputFormat, signed char outputIndex=-1,
|
||||
bool leadingSeparator=false, const char* fieldName=NULL, signed char fieldIndex=-1);
|
||||
ostringstream& output, OutputFormat outputFormat, signed char outputIndex = -1,
|
||||
bool leadingSeparator = false, const char* fieldName = NULL, signed char fieldIndex = -1);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t write(istringstream& input,
|
||||
const PartType partType, SymbolString& data,
|
||||
unsigned char offset, char separator=UI_FIELD_SEPARATOR, unsigned char* length=NULL);
|
||||
unsigned char offset, char separator = UI_FIELD_SEPARATOR, unsigned char* length = NULL);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -526,11 +526,13 @@ public:
|
||||
{
|
||||
bool uniqueNames = true;
|
||||
map<string, string> names;
|
||||
for (vector<SingleDataField*>::const_iterator it=fields.begin(); it!=fields.end(); it++) {
|
||||
for (vector<SingleDataField*>::const_iterator it = fields.begin(); it != fields.end(); it++) {
|
||||
SingleDataField* field = *it;
|
||||
if (field->isIgnored()) continue;
|
||||
if (field->isIgnored()) {
|
||||
continue;
|
||||
}
|
||||
string name = field->getName();
|
||||
if (name.empty() || names.find(name)!=names.end()) {
|
||||
if (name.empty() || names.find(name) != names.end()) {
|
||||
uniqueNames = false;
|
||||
break;
|
||||
}
|
||||
@@ -548,10 +550,10 @@ public:
|
||||
virtual DataFieldSet* clone();
|
||||
|
||||
// @copydoc
|
||||
virtual unsigned char getLength(PartType partType, unsigned char maxLength=MAX_LEN);
|
||||
virtual unsigned char getLength(PartType partType, unsigned char maxLength = MAX_LEN);
|
||||
|
||||
// @copydoc
|
||||
virtual string getName(signed char fieldIndex=-1);
|
||||
virtual string getName(signed char fieldIndex = -1);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t derive(string name, string comment,
|
||||
@@ -564,14 +566,14 @@ public:
|
||||
* @param index the index of the @a SingleDataField to return.
|
||||
* @return the @a SingleDataField at the specified index, or NULL.
|
||||
*/
|
||||
SingleDataField* operator[](const size_t index) { if (index >= m_fields.size()) return NULL; return m_fields[index]; }
|
||||
SingleDataField* operator[](const size_t index) { if (index >= m_fields.size()) { return NULL; } return m_fields[index]; }
|
||||
|
||||
/**
|
||||
* Returns the @a SingleDataField at the specified index.
|
||||
* @param index the index of the @a SingleDataField to return.
|
||||
* @return the @a SingleDataField at the specified index, or NULL.
|
||||
*/
|
||||
const SingleDataField* operator[](const size_t index) const { if (index >= m_fields.size()) return NULL; return m_fields[index]; }
|
||||
const SingleDataField* operator[](const size_t index) const { if (index >= m_fields.size()) { return NULL; } return m_fields[index]; }
|
||||
|
||||
/**
|
||||
* Returns the number of @a SingleDataFields instances in this set.
|
||||
@@ -588,18 +590,18 @@ public:
|
||||
// @copydoc
|
||||
virtual result_t read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
unsigned int& output, const char* fieldName=NULL, signed char fieldIndex=-1);
|
||||
unsigned int& output, const char* fieldName = NULL, signed char fieldIndex = -1);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
ostringstream& output, OutputFormat outputFormat, signed char outputIndex=-1,
|
||||
bool leadingSeparator=false, const char* fieldName=NULL, signed char fieldIndex=-1);
|
||||
ostringstream& output, OutputFormat outputFormat, signed char outputIndex = -1,
|
||||
bool leadingSeparator = false, const char* fieldName = NULL, signed char fieldIndex = -1);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t write(istringstream& input,
|
||||
const PartType partType, SymbolString& data,
|
||||
unsigned char offset, char separator=UI_FIELD_SEPARATOR, unsigned char* length=NULL);
|
||||
unsigned char offset, char separator = UI_FIELD_SEPARATOR, unsigned char* length = NULL);
|
||||
|
||||
private:
|
||||
|
||||
@@ -653,7 +655,7 @@ public:
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
* Note: the caller may not free the added instance on success.
|
||||
*/
|
||||
result_t add(DataField* field, string name="", bool replace=false);
|
||||
result_t add(DataField* field, string name = "", bool replace = false);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end,
|
||||
@@ -675,4 +677,4 @@ private:
|
||||
|
||||
};
|
||||
|
||||
#endif // LIBEBUS_DATA_H_
|
||||
#endif // LIB_EBUS_DATA_H_
|
||||
|
||||
+53
-66
@@ -21,13 +21,12 @@
|
||||
#endif
|
||||
|
||||
#include "datatype.h"
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef HAVE_CONTRIB
|
||||
# include "contrib/contrib.h"
|
||||
#endif
|
||||
@@ -76,8 +75,7 @@ int parseSignedInt(const char* str, int base, const int minValue, const int maxV
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end, vector<string>::iterator pos, string filename, size_t lineNo, result_t result)
|
||||
{
|
||||
void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end, vector<string>::iterator pos, string filename, size_t lineNo, result_t result) {
|
||||
if (pos > begin) {
|
||||
pos--;
|
||||
}
|
||||
@@ -105,7 +103,7 @@ void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<st
|
||||
} else {
|
||||
i = item.find(FIELD_SEPARATOR);
|
||||
}
|
||||
if (i!=string::npos) {
|
||||
if (i != string::npos) {
|
||||
out << TEXT_SEPARATOR << item << TEXT_SEPARATOR;
|
||||
if (begin < pos) {
|
||||
cnt += 2;
|
||||
@@ -129,7 +127,7 @@ bool DataType::dump(ostream& output, const unsigned char length) const
|
||||
{
|
||||
output << m_id;
|
||||
if (isAdjustableLength()) {
|
||||
if (length==REMAIN_LEN) {
|
||||
if (length == REMAIN_LEN) {
|
||||
output << ":*";
|
||||
} else {
|
||||
output << ":" << static_cast<unsigned>(length);
|
||||
@@ -141,20 +139,18 @@ bool DataType::dump(ostream& output, const unsigned char length) const
|
||||
|
||||
|
||||
result_t StringDataType::readRawValue(SymbolString& input, const unsigned char offset,
|
||||
const unsigned char length, unsigned int& value)
|
||||
{
|
||||
const unsigned char length, unsigned int& value) {
|
||||
return RESULT_EMPTY;
|
||||
}
|
||||
|
||||
result_t StringDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
const unsigned char baseOffset, const unsigned char length,
|
||||
ostringstream& output, OutputFormat outputFormat)
|
||||
{
|
||||
ostringstream& output, OutputFormat outputFormat) {
|
||||
size_t start = 0, count = length;
|
||||
int incr = 1;
|
||||
unsigned char ch;
|
||||
bool terminated = false;
|
||||
if (count==REMAIN_LEN && input.size()>baseOffset) {
|
||||
if (count == REMAIN_LEN && input.size() > baseOffset) {
|
||||
count = input.size()-baseOffset;
|
||||
} else if (baseOffset + count > input.size()) {
|
||||
return RESULT_ERR_INVALID_POS;
|
||||
@@ -200,10 +196,9 @@ result_t StringDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
|
||||
result_t StringDataType::writeSymbols(istringstream& input,
|
||||
unsigned char baseOffset, const unsigned char length,
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength)
|
||||
{
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength) {
|
||||
size_t start = 0, count = length;
|
||||
bool remainder = count==REMAIN_LEN && hasFlag(ADJ);
|
||||
bool remainder = count == REMAIN_LEN && hasFlag(ADJ);
|
||||
int incr = 1;
|
||||
unsigned int value = 0;
|
||||
string token;
|
||||
@@ -219,7 +214,7 @@ result_t StringDataType::writeSymbols(istringstream& input,
|
||||
for (size_t offset = start, i = 0; i < count; offset += incr, i++) {
|
||||
output[baseOffset + offset] = (unsigned char)m_replacement; // fill up with replacement
|
||||
}
|
||||
if (usedLength!=NULL) {
|
||||
if (usedLength != NULL) {
|
||||
*usedLength = (unsigned char)count;
|
||||
}
|
||||
return RESULT_OK;
|
||||
@@ -244,16 +239,18 @@ result_t StringDataType::writeSymbols(istringstream& input,
|
||||
return RESULT_ERR_INVALID_NUM; // too short hex value
|
||||
}
|
||||
value = parseInt(token.c_str(), 16, 0, 0xff, result);
|
||||
if (result != RESULT_OK)
|
||||
if (result != RESULT_OK) {
|
||||
return result; // invalid hex value
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (input.eof()) {
|
||||
value = m_replacement;
|
||||
} else {
|
||||
value = input.get();
|
||||
if (input.eof() || value < 0x20)
|
||||
if (input.eof() || value < 0x20) {
|
||||
value = m_replacement;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (remainder && input.eof() && i > 0) {
|
||||
@@ -272,7 +269,7 @@ result_t StringDataType::writeSymbols(istringstream& input,
|
||||
if (!remainder && i < count) {
|
||||
return RESULT_ERR_EOF; // input too short
|
||||
}
|
||||
if (usedLength!=NULL) {
|
||||
if (usedLength != NULL) {
|
||||
*usedLength = (unsigned char)((offset-start)*incr);
|
||||
}
|
||||
return RESULT_OK;
|
||||
@@ -280,19 +277,17 @@ result_t StringDataType::writeSymbols(istringstream& input,
|
||||
|
||||
|
||||
result_t DateTimeDataType::readRawValue(SymbolString& input, const unsigned char offset,
|
||||
const unsigned char length, unsigned int& value)
|
||||
{
|
||||
const unsigned char length, unsigned int& value) {
|
||||
return RESULT_EMPTY;
|
||||
}
|
||||
|
||||
result_t DateTimeDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
const unsigned char baseOffset, const unsigned char length,
|
||||
ostringstream& output, OutputFormat outputFormat)
|
||||
{
|
||||
ostringstream& output, OutputFormat outputFormat) {
|
||||
size_t start = 0, count = length;
|
||||
int incr = 1;
|
||||
unsigned char ch, last = 0, hour = 0;
|
||||
if (count==REMAIN_LEN && input.size()>baseOffset) {
|
||||
if (count == REMAIN_LEN && input.size() > baseOffset) {
|
||||
count = input.size()-baseOffset;
|
||||
} else if (baseOffset + count > input.size()) {
|
||||
return RESULT_ERR_INVALID_POS;
|
||||
@@ -341,7 +336,7 @@ result_t DateTimeDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
int m = (int)((mjd-14956.1-(int)(y*365.25))/30.6001);
|
||||
int d = mjd-14956-(int)(y*365.25)-(int)(m*30.6001);
|
||||
m--;
|
||||
if (m>=13) {
|
||||
if (m >= 13) {
|
||||
y++;
|
||||
m -= 12;
|
||||
}
|
||||
@@ -402,8 +397,9 @@ result_t DateTimeDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
} else if (ch > 59 || (hour == 24 && ch > 0)) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid time
|
||||
}
|
||||
if (i > 0)
|
||||
if (i > 0) {
|
||||
output << ":";
|
||||
}
|
||||
output << setw(2) << dec << setfill('0') << static_cast<unsigned>(ch);
|
||||
break;
|
||||
}
|
||||
@@ -417,10 +413,9 @@ result_t DateTimeDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
|
||||
result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
unsigned char baseOffset, const unsigned char length,
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength)
|
||||
{
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength) {
|
||||
size_t start = 0, count = length;
|
||||
bool remainder = count==REMAIN_LEN && hasFlag(ADJ);
|
||||
bool remainder = count == REMAIN_LEN && hasFlag(ADJ);
|
||||
int incr = 1;
|
||||
unsigned int value = 0, last = 0, lastLast = 0;
|
||||
string token;
|
||||
@@ -436,7 +431,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
for (size_t offset = start, i = 0; i < count; offset += incr, i++) {
|
||||
output[baseOffset + offset] = (unsigned char)m_replacement; // fill up with replacement
|
||||
}
|
||||
if (usedLength!=NULL) {
|
||||
if (usedLength != NULL) {
|
||||
*usedLength = (unsigned char)count;
|
||||
}
|
||||
return RESULT_OK;
|
||||
@@ -450,8 +445,9 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
switch (type)
|
||||
{
|
||||
case 2: // date only
|
||||
if (length == 4 && i == 2)
|
||||
if (length == 4 && i == 2) {
|
||||
continue; // skip weekday in between
|
||||
}
|
||||
if (input.eof() || !getline(input, token, '.')) {
|
||||
return RESULT_ERR_EOF; // incomplete
|
||||
}
|
||||
@@ -469,11 +465,11 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
count++;
|
||||
} else if (i + 1 == count) {
|
||||
int y = (value < 100 ? value + 2000 : value) - 1900;
|
||||
int l = last<=2 ? 1 : 0;
|
||||
int l = last <= 2 ? 1 : 0;
|
||||
int mjd = 14956 + lastLast + (int)((y-l)*365.25) + (int)((last+1+l*12)*30.6001);
|
||||
value = mjd - 15020; // 01.01.1900
|
||||
output[baseOffset + offset] = (unsigned char)(value&0xff);
|
||||
value >>= 8;
|
||||
value >>= 8;
|
||||
offset += incr;
|
||||
skip = false;
|
||||
break;
|
||||
@@ -483,13 +479,13 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
if (length == 4) {
|
||||
// calculate local week day
|
||||
int y = (value < 100 ? value + 2000 : value) - 1900;
|
||||
int l = last<=2 ? 1 : 0;
|
||||
int l = last <= 2 ? 1 : 0;
|
||||
int mjd = 14956 + lastLast + (int)((y-l)*365.25) + (int)((last+1+l*12)*30.6001);
|
||||
int daysSinceSunday = (mjd+3) % 7; // Sun=0
|
||||
if (hasFlag(BCD)) {
|
||||
output[baseOffset + offset - incr] = (unsigned char)((6+daysSinceSunday) % 7); // Sun=0x06
|
||||
} else {
|
||||
output[baseOffset + offset - incr] = (unsigned char)(daysSinceSunday==0 ? 7 : daysSinceSunday); // Sun=0x07
|
||||
output[baseOffset + offset - incr] = (unsigned char)(daysSinceSunday == 0 ? 7 : daysSinceSunday); // Sun=0x07
|
||||
}
|
||||
}
|
||||
if (value >= 2000) {
|
||||
@@ -535,7 +531,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
}
|
||||
value += last*60;
|
||||
output[baseOffset + offset] = (unsigned char)(value&0xff);
|
||||
value >>= 8;
|
||||
value >>= 8;
|
||||
offset += incr;
|
||||
} else if (length == 1) { // truncated time
|
||||
if (i == 0) {
|
||||
@@ -569,7 +565,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
if (!remainder && i < count) {
|
||||
return RESULT_ERR_EOF; // input too short
|
||||
}
|
||||
if (usedLength!=NULL) {
|
||||
if (usedLength != NULL) {
|
||||
*usedLength = (unsigned char)((offset-start)*incr);
|
||||
}
|
||||
return RESULT_OK;
|
||||
@@ -600,15 +596,14 @@ bool NumberDataType::dump(ostream& output, unsigned char length) const
|
||||
output << static_cast<int>(m_divisor / m_baseType->m_divisor);
|
||||
return true;
|
||||
}
|
||||
} else if (m_divisor!=1) {
|
||||
} else if (m_divisor != 1) {
|
||||
output << static_cast<int>(m_divisor);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
result_t NumberDataType::derive(int divisor, unsigned char bitCount, NumberDataType* &derived)
|
||||
{
|
||||
result_t NumberDataType::derive(int divisor, unsigned char bitCount, NumberDataType* &derived) {
|
||||
if (divisor == 0) {
|
||||
divisor = 1;
|
||||
}
|
||||
@@ -663,8 +658,7 @@ result_t NumberDataType::derive(int divisor, unsigned char bitCount, NumberDataT
|
||||
|
||||
result_t NumberDataType::readRawValue(SymbolString& input,
|
||||
unsigned char baseOffset, const unsigned char length,
|
||||
unsigned int& value)
|
||||
{
|
||||
unsigned int& value) {
|
||||
size_t start = 0, count = length;
|
||||
int incr = 1;
|
||||
unsigned char ch;
|
||||
@@ -687,21 +681,22 @@ result_t NumberDataType::readRawValue(SymbolString& input,
|
||||
return RESULT_OK;
|
||||
}
|
||||
if (!hasFlag(HCD)) {
|
||||
if ((ch & 0xf0) > 0x90 || (ch & 0x0f) > 0x09)
|
||||
if ((ch & 0xf0) > 0x90 || (ch & 0x0f) > 0x09) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid BCD
|
||||
|
||||
}
|
||||
ch = (unsigned char)((ch >> 4) * 10 + (ch & 0x0f));
|
||||
} else if (ch > 0x63)
|
||||
} else if (ch > 0x63) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid HCD
|
||||
}
|
||||
value += ch * exp;
|
||||
exp *= 100;
|
||||
} else {
|
||||
value |= ch * exp;
|
||||
exp <<= 8;
|
||||
exp <<= 8;
|
||||
}
|
||||
}
|
||||
if (m_firstBit > 0) {
|
||||
value >>= m_firstBit;
|
||||
value >>= m_firstBit;
|
||||
}
|
||||
if (m_bitCount < 8) {
|
||||
value &= (1 << m_bitCount) - 1;
|
||||
@@ -711,8 +706,7 @@ result_t NumberDataType::readRawValue(SymbolString& input,
|
||||
|
||||
result_t NumberDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
const unsigned char baseOffset, const unsigned char length,
|
||||
ostringstream& output, OutputFormat outputFormat)
|
||||
{
|
||||
ostringstream& output, OutputFormat outputFormat) {
|
||||
unsigned int value = 0;
|
||||
int signedValue;
|
||||
|
||||
@@ -810,8 +804,7 @@ result_t NumberDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
|
||||
result_t NumberDataType::writeRawValue(unsigned int value,
|
||||
const unsigned char baseOffset, const unsigned char length,
|
||||
SymbolString& output, unsigned char* usedLength)
|
||||
{
|
||||
SymbolString& output, unsigned char* usedLength) {
|
||||
size_t start = 0, count = length;
|
||||
int incr = 1;
|
||||
unsigned char ch;
|
||||
@@ -820,7 +813,7 @@ result_t NumberDataType::writeRawValue(unsigned int value,
|
||||
return RESULT_ERR_OUT_OF_RANGE;
|
||||
}
|
||||
if (m_firstBit > 0) {
|
||||
value <<= m_firstBit;
|
||||
value <<= m_firstBit;
|
||||
}
|
||||
|
||||
if (hasFlag(REV)) { // reverted binary representation (most significant byte first)
|
||||
@@ -841,7 +834,7 @@ result_t NumberDataType::writeRawValue(unsigned int value,
|
||||
exp *= 100;
|
||||
} else {
|
||||
ch = (value / exp) & 0xff;
|
||||
exp <<= 8;
|
||||
exp <<= 8;
|
||||
}
|
||||
if (offset == start && (m_bitCount % 8) != 0 && baseOffset + offset < output.size()) {
|
||||
output[baseOffset + offset] |= ch;
|
||||
@@ -849,7 +842,7 @@ result_t NumberDataType::writeRawValue(unsigned int value,
|
||||
output[baseOffset + offset] = ch;
|
||||
}
|
||||
}
|
||||
if (usedLength!=NULL) {
|
||||
if (usedLength != NULL) {
|
||||
*usedLength = length;
|
||||
}
|
||||
return RESULT_OK;
|
||||
@@ -857,8 +850,7 @@ result_t NumberDataType::writeRawValue(unsigned int value,
|
||||
|
||||
result_t NumberDataType::writeSymbols(istringstream& input,
|
||||
const unsigned char baseOffset, const unsigned char length,
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength)
|
||||
{
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength) {
|
||||
unsigned int value;
|
||||
|
||||
const char* str = input.str().c_str();
|
||||
@@ -972,8 +964,7 @@ bool DataTypeList::s_contrib_initialized = libebus_contrib_register();
|
||||
#endif
|
||||
|
||||
|
||||
DataTypeList::DataTypeList()
|
||||
{
|
||||
DataTypeList::DataTypeList() {
|
||||
add(new StringDataType("STR", MAX_LEN*8, ADJ, ' ')); // >= 1 byte character string filled up with space
|
||||
add(new NumberDataType("PIN", 16, FIX|BCD|REV, 0xffff, 0, 0x9999, 1)); // unsigned decimal in BCD, 0000 - 9999 (fixed length)
|
||||
add(new NumberDataType("UCH", 8, 0, 0xff, 0, 0xfe, 1)); // unsigned integer, 0 - 254
|
||||
@@ -1036,13 +1027,11 @@ DataTypeList::DataTypeList()
|
||||
add(new NumberDataType("BI7", 1, ADJ|REQ, 0, 7, 1)); // bit 7
|
||||
}
|
||||
|
||||
DataTypeList* DataTypeList::getInstance()
|
||||
{
|
||||
DataTypeList* DataTypeList::getInstance() {
|
||||
return &s_instance;
|
||||
}
|
||||
|
||||
void DataTypeList::clear()
|
||||
{
|
||||
void DataTypeList::clear() {
|
||||
for (list<DataType*>::iterator it = m_cleanupTypes.begin(); it != m_cleanupTypes.end(); it++) {
|
||||
delete *it;
|
||||
}
|
||||
@@ -1051,12 +1040,11 @@ void DataTypeList::clear()
|
||||
m_typesById.clear();
|
||||
}
|
||||
|
||||
result_t DataTypeList::add(DataType* dataType)
|
||||
{
|
||||
result_t DataTypeList::add(DataType* dataType) {
|
||||
if (!dataType->isAdjustableLength()) {
|
||||
ostringstream str;
|
||||
unsigned char bitCount = dataType->getBitCount();
|
||||
str << dataType->getId() << LENGTH_SEPARATOR << static_cast<unsigned>(bitCount>=8?bitCount/8:bitCount);
|
||||
str << dataType->getId() << LENGTH_SEPARATOR << static_cast<unsigned>(bitCount >= 8?bitCount/8:bitCount);
|
||||
map<string, DataType*>::iterator it = m_typesByIdLength.find(str.str());
|
||||
if (it != m_typesByIdLength.end()) {
|
||||
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
|
||||
@@ -1074,8 +1062,7 @@ result_t DataTypeList::add(DataType* dataType)
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
DataType* DataTypeList::get(const string id, const unsigned char length)
|
||||
{
|
||||
DataType* DataTypeList::get(const string id, const unsigned char length) {
|
||||
DataType* dataType = NULL;
|
||||
if (length > 0) {
|
||||
ostringstream str;
|
||||
|
||||
+11
-11
@@ -16,12 +16,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_DATATYPE_H_
|
||||
#define LIBEBUS_DATATYPE_H_
|
||||
#ifndef LIB_EBUS_DATATYPE_H_
|
||||
#define LIB_EBUS_DATATYPE_H_
|
||||
|
||||
#include "symbol.h"
|
||||
#include "result.h"
|
||||
#include "filereader.h"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@@ -29,6 +26,9 @@
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include "symbol.h"
|
||||
#include "result.h"
|
||||
#include "filereader.h"
|
||||
|
||||
/** @file datatype.h
|
||||
* Classes, functions, and constants related to decoding/encoding of symbols
|
||||
@@ -116,7 +116,7 @@ static const unsigned int CON = 0x1000; //!< marker for a constant value
|
||||
* @param length the optional variable in which to store the number of read characters.
|
||||
* @return the parsed value.
|
||||
*/
|
||||
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue, result_t& result, unsigned int* length=NULL);
|
||||
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue, result_t& result, unsigned int* length = NULL);
|
||||
|
||||
/**
|
||||
* Parse a signed int value.
|
||||
@@ -128,7 +128,7 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co
|
||||
* @param length the optional variable in which to store the number of read characters.
|
||||
* @return the parsed value.
|
||||
*/
|
||||
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result, unsigned int* length=NULL);
|
||||
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result, unsigned int* length = NULL);
|
||||
|
||||
/**
|
||||
* Print the error position of the iterator.
|
||||
@@ -284,7 +284,7 @@ public:
|
||||
* @param isHex true for hex digits instead of characters.
|
||||
*/
|
||||
StringDataType(const string id, const unsigned char bitCount, const unsigned short flags,
|
||||
const unsigned int replacement, bool isHex=false)
|
||||
const unsigned int replacement, bool isHex = false)
|
||||
: DataType(id, bitCount, flags, replacement), m_isHex(isHex) {}
|
||||
|
||||
/**
|
||||
@@ -494,7 +494,7 @@ public:
|
||||
*/
|
||||
virtual result_t writeRawValue(unsigned int value,
|
||||
const unsigned char offset, const unsigned char length,
|
||||
SymbolString& output, unsigned char* usedLength=NULL);
|
||||
SymbolString& output, unsigned char* usedLength = NULL);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t writeSymbols(istringstream& input,
|
||||
@@ -575,7 +575,7 @@ public:
|
||||
* @return the @a DataType instance, or NULL if not available.
|
||||
* Note: the caller may not free the instance.
|
||||
*/
|
||||
DataType* get(const string id, const unsigned char length=0);
|
||||
DataType* get(const string id, const unsigned char length = 0);
|
||||
|
||||
private:
|
||||
|
||||
@@ -599,4 +599,4 @@ private:
|
||||
|
||||
};
|
||||
|
||||
#endif // LIBEBUS_DATATYPE_H_
|
||||
#endif // LIB_EBUS_DATATYPE_H_
|
||||
|
||||
+26
-41
@@ -21,47 +21,44 @@
|
||||
#endif
|
||||
|
||||
#include "device.h"
|
||||
#include "data.h"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fcntl.h>
|
||||
#include <fstream>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_PPOLL
|
||||
# include <poll.h>
|
||||
#endif
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include "data.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
Device::~Device()
|
||||
{
|
||||
Device::~Device() {
|
||||
close();
|
||||
}
|
||||
|
||||
Device* Device::create(const char* name, const bool checkDevice, const bool readOnly, const bool initialSend)
|
||||
{
|
||||
Device* Device::create(const char* name, const bool checkDevice, const bool readOnly, const bool initialSend) {
|
||||
if (strchr(name, '/') == NULL && strchr(name, ':') != NULL) {
|
||||
char* in = strdup(name);
|
||||
bool udp = false;
|
||||
char* addrpos = in;
|
||||
char* portpos = strchr(addrpos, ':');
|
||||
if (portpos==addrpos+3 && (strncmp(addrpos, "tcp", 3)==0 || (udp=(strncmp(addrpos, "udp", 3)==0)))) {
|
||||
if (portpos == addrpos+3 && (strncmp(addrpos, "tcp", 3) == 0 || (udp=(strncmp(addrpos, "udp", 3) == 0)))) {
|
||||
addrpos += 4;
|
||||
portpos = strchr(addrpos, ':');
|
||||
}
|
||||
if (portpos==NULL) {
|
||||
if (portpos == NULL) {
|
||||
free(in);
|
||||
return NULL; // invalid protocol or missing port
|
||||
}
|
||||
result_t result = RESULT_OK;
|
||||
unsigned int port = parseInt(portpos+1, 10, 1, 65535, result);
|
||||
if (result!=RESULT_OK) {
|
||||
if (result != RESULT_OK) {
|
||||
free(in);
|
||||
return NULL; // invalid port
|
||||
}
|
||||
@@ -84,16 +81,14 @@ Device* Device::create(const char* name, const bool checkDevice, const bool read
|
||||
return new SerialDevice(name, checkDevice, readOnly, initialSend);
|
||||
}
|
||||
|
||||
void Device::close()
|
||||
{
|
||||
void Device::close() {
|
||||
if (m_fd != -1) {
|
||||
::close(m_fd);
|
||||
m_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool Device::isValid()
|
||||
{
|
||||
bool Device::isValid() {
|
||||
if (m_fd == -1) {
|
||||
return false;
|
||||
}
|
||||
@@ -103,8 +98,7 @@ bool Device::isValid()
|
||||
return m_fd != -1;
|
||||
}
|
||||
|
||||
result_t Device::send(const unsigned char value)
|
||||
{
|
||||
result_t Device::send(const unsigned char value) {
|
||||
if (!isValid()) {
|
||||
return RESULT_ERR_DEVICE;
|
||||
}
|
||||
@@ -117,8 +111,7 @@ result_t Device::send(const unsigned char value)
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t Device::recv(const long timeout, unsigned char& value)
|
||||
{
|
||||
result_t Device::recv(const long timeout, unsigned char& value) {
|
||||
if (!isValid()) {
|
||||
return RESULT_ERR_DEVICE;
|
||||
}
|
||||
@@ -175,8 +168,7 @@ result_t Device::recv(const long timeout, unsigned char& value)
|
||||
}
|
||||
|
||||
|
||||
result_t SerialDevice::open()
|
||||
{
|
||||
result_t SerialDevice::open() {
|
||||
if (m_fd != -1) {
|
||||
close();
|
||||
}
|
||||
@@ -228,8 +220,7 @@ result_t SerialDevice::open()
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void SerialDevice::close()
|
||||
{
|
||||
void SerialDevice::close() {
|
||||
if (m_fd != -1) {
|
||||
// empty device buffer
|
||||
tcflush(m_fd, TCIOFLUSH);
|
||||
@@ -240,8 +231,7 @@ void SerialDevice::close()
|
||||
Device::close();
|
||||
}
|
||||
|
||||
void SerialDevice::checkDevice()
|
||||
{
|
||||
void SerialDevice::checkDevice() {
|
||||
int port;
|
||||
if (ioctl(m_fd, TIOCMGET, &port) == -1) {
|
||||
close();
|
||||
@@ -249,8 +239,7 @@ void SerialDevice::checkDevice()
|
||||
}
|
||||
|
||||
|
||||
result_t NetworkDevice::open()
|
||||
{
|
||||
result_t NetworkDevice::open() {
|
||||
if (m_fd != -1) {
|
||||
close();
|
||||
}
|
||||
@@ -269,7 +258,7 @@ result_t NetworkDevice::open()
|
||||
value = 1;
|
||||
setsockopt(m_fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&value, sizeof(value));
|
||||
}
|
||||
if (ret==0) {
|
||||
if (ret == 0) {
|
||||
ret = connect(m_fd, (struct sockaddr*)&m_address, sizeof(m_address));
|
||||
}
|
||||
if (ret < 0) {
|
||||
@@ -282,7 +271,7 @@ result_t NetworkDevice::open()
|
||||
unsigned char buf[256];
|
||||
while (::read(m_fd, &buf, 256) > 0);
|
||||
}
|
||||
if (m_bufSize==0) {
|
||||
if (m_bufSize == 0) {
|
||||
m_bufSize = MAX_LEN+1;
|
||||
m_buffer = (unsigned char*)malloc(m_bufSize);
|
||||
if (!m_buffer) {
|
||||
@@ -296,8 +285,7 @@ result_t NetworkDevice::open()
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void NetworkDevice::checkDevice()
|
||||
{
|
||||
void NetworkDevice::checkDevice() {
|
||||
unsigned char value;
|
||||
ssize_t c = ::recv(m_fd, &value, 1, MSG_PEEK | MSG_DONTWAIT);
|
||||
if (c == 0 || (c < 0 && errno != EAGAIN)) {
|
||||
@@ -306,28 +294,25 @@ void NetworkDevice::checkDevice()
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkDevice::available()
|
||||
{
|
||||
return m_buffer && m_bufLen>0;
|
||||
bool NetworkDevice::available() {
|
||||
return m_buffer && m_bufLen > 0;
|
||||
}
|
||||
|
||||
ssize_t NetworkDevice::write(const unsigned char value)
|
||||
{
|
||||
ssize_t NetworkDevice::write(const unsigned char value) {
|
||||
m_bufLen = 0; // flush read buffer
|
||||
return Device::write(value);
|
||||
}
|
||||
|
||||
ssize_t NetworkDevice::read(unsigned char& value)
|
||||
{
|
||||
ssize_t NetworkDevice::read(unsigned char& value) {
|
||||
if (available()) {
|
||||
value = m_buffer[m_bufPos];
|
||||
m_bufPos = (unsigned char)((m_bufPos+1)%m_bufSize);
|
||||
m_bufLen--;
|
||||
return 1;
|
||||
}
|
||||
if (m_bufSize>0) {
|
||||
if (m_bufSize > 0) {
|
||||
ssize_t size = ::read(m_fd, m_buffer, m_bufSize);
|
||||
if (size<=0) {
|
||||
if (size <= 0) {
|
||||
return size;
|
||||
}
|
||||
value = m_buffer[0];
|
||||
|
||||
@@ -16,15 +16,15 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_DEVICE_H_
|
||||
#define LIBEBUS_DEVICE_H_
|
||||
#ifndef LIB_EBUS_DEVICE_H_
|
||||
#define LIB_EBUS_DEVICE_H_
|
||||
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "result.h"
|
||||
|
||||
/** @file device.h
|
||||
@@ -92,7 +92,7 @@ public:
|
||||
* @return the new @a Device, or NULL on error.
|
||||
* Note: the caller needs to free the created instance.
|
||||
*/
|
||||
static Device* create(const char* name, const bool checkDevice=true, const bool readOnly=false, const bool initialSend=false);
|
||||
static Device* create(const char* name, const bool checkDevice = true, const bool readOnly = false, const bool initialSend = false);
|
||||
|
||||
/**
|
||||
* Get the transfer latency of this device.
|
||||
@@ -290,4 +290,4 @@ private:
|
||||
|
||||
};
|
||||
|
||||
#endif // LIBEBUS_DEVICE_H_
|
||||
#endif // LIB_EBUS_DEVICE_H_
|
||||
|
||||
+40
-37
@@ -16,11 +16,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_FILEREADER_H_
|
||||
#define LIBEBUS_FILEREADER_H_
|
||||
#ifndef LIB_EBUS_FILEREADER_H_
|
||||
#define LIB_EBUS_FILEREADER_H_
|
||||
|
||||
#include "symbol.h"
|
||||
#include "result.h"
|
||||
#include <climits>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
@@ -28,6 +26,8 @@
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include "symbol.h"
|
||||
#include "result.h"
|
||||
|
||||
/** @file filereader.h
|
||||
* Helper class and constants for reading configuration files.
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
* @param defaultSuffix the default circuit name suffix (starting with a ".", may be overwritten by file name, or empty.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t readFromFile(const string filename, bool verbose=false,
|
||||
virtual result_t readFromFile(const string filename, bool verbose = false,
|
||||
string defaultDest = "", string defaultCircuit = "", string defaultSuffix = "")
|
||||
{
|
||||
ifstream ifs;
|
||||
@@ -94,7 +94,7 @@ public:
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
size_t lastSep = filename.find_last_of('/');
|
||||
if (lastSep!=string::npos) { // potential destination address, matches "^ZZ."
|
||||
if (lastSep != string::npos) { // potential destination address, matches "^ZZ."
|
||||
// extract defaultDest, defaultCircuit, defaultSuffix from filename:
|
||||
// ZZ.IDENT[.CIRCUIT][.SUFFIX].*csv
|
||||
unsigned char checkDest;
|
||||
@@ -114,9 +114,9 @@ public:
|
||||
vector<string> row;
|
||||
vector< vector<string> > defaults;
|
||||
while (splitFields(ifs, row, lineNo)) {
|
||||
if (row.empty())
|
||||
if (row.empty()) {
|
||||
continue;
|
||||
|
||||
}
|
||||
result_t result;
|
||||
vector<string>::iterator it = row.begin();
|
||||
const vector<string>::iterator end = row.end();
|
||||
@@ -124,31 +124,33 @@ public:
|
||||
if (row[0][0] == '*') {
|
||||
row[0] = row[0].substr(1);
|
||||
result = addDefaultFromFile(defaults, row, it, defaultDest, defaultCircuit, defaultSuffix, filename, lineNo);
|
||||
if (result == RESULT_OK)
|
||||
if (result == RESULT_OK) {
|
||||
continue;
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
result = addFromFile(it, end, &defaults, defaultDest, defaultCircuit, defaultSuffix, filename, lineNo);
|
||||
}
|
||||
else
|
||||
}
|
||||
} else {
|
||||
result = addFromFile(it, end, NULL, defaultDest, defaultCircuit, defaultSuffix, filename, lineNo);
|
||||
|
||||
}
|
||||
if (result != RESULT_OK) {
|
||||
if (!verbose) {
|
||||
ifs.close();
|
||||
ostringstream error;
|
||||
error << filename << ":" << static_cast<unsigned>(lineNo);
|
||||
if (m_lastError.length()>0) {
|
||||
if (m_lastError.length() > 0) {
|
||||
error << ": " << m_lastError;
|
||||
}
|
||||
m_lastError = error.str();
|
||||
return result;
|
||||
}
|
||||
if (m_lastError.length()>0) {
|
||||
if (m_lastError.length() > 0) {
|
||||
cout << m_lastError << endl;
|
||||
}
|
||||
printErrorPos(cout, row.begin(), end, it, filename, lineNo, result);
|
||||
} else if (!verbose)
|
||||
} else if (!verbose) {
|
||||
m_lastError = "";
|
||||
}
|
||||
}
|
||||
|
||||
ifs.close();
|
||||
@@ -205,11 +207,11 @@ public:
|
||||
static void trim(string& str)
|
||||
{
|
||||
size_t pos = str.find_first_not_of(" \t");
|
||||
if (pos!=string::npos) {
|
||||
if (pos != string::npos) {
|
||||
str.erase(0, pos);
|
||||
}
|
||||
pos = str.find_last_not_of(" \t");
|
||||
if (pos!=string::npos) {
|
||||
if (pos != string::npos) {
|
||||
str.erase(pos+1);
|
||||
}
|
||||
}
|
||||
@@ -244,9 +246,9 @@ public:
|
||||
trim(line);
|
||||
|
||||
size_t length = line.length();
|
||||
if (!quotedText && (length == 0 || line[0] == '#' || (line.length() > 1 && line[0] == '/' && line[1] == '/')))
|
||||
if (!quotedText && (length == 0 || line[0] == '#' || (line.length() > 1 && line[0] == '/' && line[1] == '/'))) {
|
||||
continue; // skip empty lines and comments
|
||||
|
||||
}
|
||||
for (size_t pos = 0; pos < length; pos++) {
|
||||
char ch = line[pos];
|
||||
switch (ch)
|
||||
@@ -278,10 +280,10 @@ public:
|
||||
case '\r':
|
||||
break;
|
||||
default:
|
||||
if (prev==TEXT_SEPARATOR && !quotedText && wasQuoted) {
|
||||
if (prev == TEXT_SEPARATOR && !quotedText && wasQuoted) {
|
||||
field << TEXT_SEPARATOR; // single dquote in the middle of formerly quoted text
|
||||
quotedText = true;
|
||||
} else if (quotedText && pos==0 && field.tellp()>0 && *(field.str().end()-1)!=VALUE_SEPARATOR) {
|
||||
} else if (quotedText && pos == 0 && field.tellp() > 0 && *(field.str().end()-1) != VALUE_SEPARATOR) {
|
||||
field << VALUE_SEPARATOR;
|
||||
}
|
||||
field << ch;
|
||||
@@ -289,8 +291,9 @@ public:
|
||||
}
|
||||
prev = ch;
|
||||
}
|
||||
if (!quotedText)
|
||||
if (!quotedText) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
string str = field.str();
|
||||
trim(str);
|
||||
@@ -318,51 +321,51 @@ public:
|
||||
{
|
||||
ident = circuit = suffix = "";
|
||||
software = hardware = UINT_MAX;
|
||||
if (name.length()>4 && name.substr(name.length()-4)==".csv") {
|
||||
if (name.length() > 4 && name.substr(name.length()-4) == ".csv") {
|
||||
name = name.substr(0, name.length()-3); // including trailing "."
|
||||
}
|
||||
size_t pos = name.find('.');
|
||||
if (pos!=2) {
|
||||
if (pos != 2) {
|
||||
return false; // missing "ZZ."
|
||||
}
|
||||
result_t result = RESULT_OK;
|
||||
dest = (unsigned char)parseInt(name.substr(0, pos).c_str(), 16, 0, 0xff, result, NULL);
|
||||
if (result!=RESULT_OK || !isValidAddress(dest)) {
|
||||
if (result != RESULT_OK || !isValidAddress(dest)) {
|
||||
return false; // invalid "ZZ"
|
||||
}
|
||||
name.erase(0, pos);
|
||||
if (name.length()>1) {
|
||||
if (name.length() > 1) {
|
||||
pos = name.rfind(".SW"); // check for ".SWxxxx."
|
||||
if (pos!=string::npos && name.find(".", pos+1)==pos+7) {
|
||||
if (pos != string::npos && name.find(".", pos+1) == pos+7) {
|
||||
software = parseInt(name.substr(pos+3, 4).c_str(), 10, 0, 9999, result, NULL);
|
||||
if (result!=RESULT_OK) {
|
||||
if (result != RESULT_OK) {
|
||||
return false; // invalid "SWxxxx"
|
||||
}
|
||||
name.erase(pos, 7);
|
||||
}
|
||||
}
|
||||
if (name.length()>1) {
|
||||
if (name.length() > 1) {
|
||||
pos = name.rfind(".HW"); // check for ".HWxxxx."
|
||||
if (pos!=string::npos && name.find(".", pos+1)==pos+7) {
|
||||
if (pos != string::npos && name.find(".", pos+1) == pos+7) {
|
||||
hardware = parseInt(name.substr(pos+3, 4).c_str(), 10, 0, 9999, result, NULL);
|
||||
if (result!=RESULT_OK) {
|
||||
if (result != RESULT_OK) {
|
||||
return false; // invalid "HWxxxx"
|
||||
}
|
||||
name.erase(pos, 7);
|
||||
}
|
||||
}
|
||||
if (name.length()>1) {
|
||||
if (name.length() > 1) {
|
||||
pos = name.find('.', 1); // check for ".IDENT."
|
||||
if (pos!=string::npos && pos>=1 && pos<=6) { // up to 5 chars between two "."s, immediately after "ZZ.", or ".."
|
||||
if (pos != string::npos && pos >= 1 && pos <= 6) { // up to 5 chars between two "."s, immediately after "ZZ.", or ".."
|
||||
ident = circuit = name.substr(1, pos-1);
|
||||
name.erase(0, pos);
|
||||
pos = name.find('.', 1); // check for ".CIRCUIT."
|
||||
if (pos!=string::npos && (pos>2 || name[1]<'0' || name[1]>'9')) {
|
||||
if (pos != string::npos && (pos>2 || name[1]<'0' || name[1]>'9')) {
|
||||
circuit = name.substr(1, pos-1);
|
||||
name.erase(0, pos);
|
||||
pos = name.find('.', 1); // check for ".SUFFIX."
|
||||
}
|
||||
if (pos!=string::npos && pos==2 && name[1]>='0' && name[1]<='9') {
|
||||
if (pos != string::npos && pos == 2 && name[1] >= '0' && name[1] <= '9') {
|
||||
suffix = name.substr(0, 2);
|
||||
name.erase(0, pos);
|
||||
}
|
||||
@@ -383,4 +386,4 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
#endif // LIBEBUS_FILEREADER_H_
|
||||
#endif // LIB_EBUS_FILEREADER_H_
|
||||
|
||||
+466
-437
File diff suppressed because it is too large
Load Diff
+52
-50
@@ -16,16 +16,18 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_MESSAGE_H_
|
||||
#define LIBEBUS_MESSAGE_H_
|
||||
#ifndef LIB_EBUS_MESSAGE_H_
|
||||
#define LIB_EBUS_MESSAGE_H_
|
||||
|
||||
#include "data.h"
|
||||
#include "result.h"
|
||||
#include "symbol.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <functional>
|
||||
#include "data.h"
|
||||
#include "result.h"
|
||||
#include "symbol.h"
|
||||
|
||||
/** @file message.h
|
||||
* Classes and functions for decoding and encoding of complete messages on the
|
||||
@@ -117,8 +119,8 @@ public:
|
||||
const unsigned char srcAddress, const unsigned char dstAddress,
|
||||
const vector<unsigned char> id,
|
||||
DataField* data, const bool deleteData,
|
||||
const unsigned char pollPriority=0,
|
||||
Condition* condition=NULL);
|
||||
const unsigned char pollPriority = 0,
|
||||
Condition* condition = NULL);
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -142,7 +144,7 @@ public:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~Message() { if (m_deleteData) delete m_data; }
|
||||
virtual ~Message() { if (m_deleteData) { delete m_data; } }
|
||||
|
||||
/**
|
||||
* Calculate the key for the ID.
|
||||
@@ -166,7 +168,7 @@ public:
|
||||
* @return the key for the ID, or -1LL if the data is invalid.
|
||||
*/
|
||||
static unsigned long long createKey(SymbolString& master,
|
||||
unsigned char maxIdLength, bool anyDestination=false);
|
||||
unsigned char maxIdLength, bool anyDestination = false);
|
||||
|
||||
/**
|
||||
* Get the length field from the key.
|
||||
@@ -222,7 +224,7 @@ public:
|
||||
* @param circuit the new circuit name, or empty to use the current circuit name.
|
||||
* @return the derived @a Message instance.
|
||||
*/
|
||||
virtual Message* derive(const unsigned char dstAddress, const unsigned char srcAddress=SYN, const string circuit="");
|
||||
virtual Message* derive(const unsigned char dstAddress, const unsigned char srcAddress = SYN, const string circuit = "");
|
||||
|
||||
/**
|
||||
* Derive a new @a Message from this message.
|
||||
@@ -313,7 +315,7 @@ public:
|
||||
* @param index the variable in which to store the message part index, or NULL to ignore.
|
||||
* @return true if the ID matches, false otherwise.
|
||||
*/
|
||||
virtual bool checkId(SymbolString& master, unsigned char* index=NULL);
|
||||
virtual bool checkId(SymbolString& master, unsigned char* index = NULL);
|
||||
|
||||
/**
|
||||
* Check the ID against the other @a Message.
|
||||
@@ -357,7 +359,7 @@ public:
|
||||
* Return whether this @a Message depends on a @a Condition.
|
||||
* @return true when this @a Message depends on a @a Condition.
|
||||
*/
|
||||
bool isConditional() const { return m_condition!=NULL; }
|
||||
bool isConditional() const { return m_condition != NULL; }
|
||||
|
||||
/**
|
||||
* Return whether this @a Message is available (optionally depending on a @a Condition evaluation).
|
||||
@@ -371,7 +373,7 @@ public:
|
||||
* @param numeric true for a numeric field, false for a string field.
|
||||
* @return true if the field is available.
|
||||
*/
|
||||
bool hasField(const char* fieldName, bool numeric=true);
|
||||
bool hasField(const char* fieldName, bool numeric = true);
|
||||
|
||||
/**
|
||||
* @return the number of parts this message is composed of.
|
||||
@@ -389,8 +391,8 @@ public:
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t prepareMaster(const unsigned char srcAddress, SymbolString& masterData,
|
||||
istringstream& input, char separator=UI_FIELD_SEPARATOR,
|
||||
const unsigned char dstAddress=SYN, unsigned char index=0);
|
||||
istringstream& input, char separator = UI_FIELD_SEPARATOR,
|
||||
const unsigned char dstAddress = SYN, unsigned char index = 0);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -442,8 +444,8 @@ public:
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t decodeLastData(const PartType partType,
|
||||
ostringstream& output, OutputFormat outputFormat=0,
|
||||
bool leadingSeparator=false, const char* fieldName=NULL, signed char fieldIndex=-1);
|
||||
ostringstream& output, OutputFormat outputFormat = 0,
|
||||
bool leadingSeparator = false, const char* fieldName = NULL, signed char fieldIndex = -1);
|
||||
|
||||
/**
|
||||
* Decode the value from the last stored data.
|
||||
@@ -454,8 +456,8 @@ public:
|
||||
* @param fieldIndex the optional index of the named field to limit the output to, or -1.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t decodeLastData(ostringstream& output, OutputFormat outputFormat=0,
|
||||
bool leadingSeparator=false, const char* fieldName=NULL, signed char fieldIndex=-1);
|
||||
virtual result_t decodeLastData(ostringstream& output, OutputFormat outputFormat = 0,
|
||||
bool leadingSeparator = false, const char* fieldName = NULL, signed char fieldIndex = -1);
|
||||
|
||||
/**
|
||||
* Decode a particular numeric field value from the last stored data.
|
||||
@@ -464,7 +466,7 @@ public:
|
||||
* @param fieldIndex the optional index of the named field, or -1.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t decodeLastDataNumField(unsigned int& output, const char* fieldName, signed char fieldIndex=-1);
|
||||
virtual result_t decodeLastDataNumField(unsigned int& output, const char* fieldName, signed char fieldIndex = -1);
|
||||
|
||||
/**
|
||||
* Get the last seen master data.
|
||||
@@ -509,7 +511,7 @@ public:
|
||||
* @param columns the list of column indexes to write, or NULL for all (see @p COLUMN_TYPE index constants).
|
||||
* @param withConditions whether to include the optional conditions prefix.
|
||||
*/
|
||||
void dump(ostream& output, vector<size_t>* columns=NULL, bool withConditions=false);
|
||||
void dump(ostream& output, vector<size_t>* columns = NULL, bool withConditions = false);
|
||||
|
||||
/**
|
||||
* Write the specified column to the @a ostream.
|
||||
@@ -517,7 +519,7 @@ public:
|
||||
* @param column the column index to write (see @p COLUMN_TYPE index constants).
|
||||
* @param withConditions whether to include the optional conditions prefix.
|
||||
*/
|
||||
virtual void dumpColumn(ostream& output, size_t column, bool withConditions=false);
|
||||
virtual void dumpColumn(ostream& output, size_t column, bool withConditions = false);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -638,18 +640,18 @@ public:
|
||||
vector< vector<unsigned char> > ids, vector<unsigned char> lengths,
|
||||
DataField* data, const bool deleteData,
|
||||
const unsigned char pollPriority,
|
||||
Condition* condition=NULL);
|
||||
Condition* condition = NULL);
|
||||
|
||||
virtual ~ChainedMessage();
|
||||
|
||||
// @copydoc
|
||||
virtual Message* derive(const unsigned char dstAddress, const unsigned char srcAddress=SYN, const string circuit="");
|
||||
virtual Message* derive(const unsigned char dstAddress, const unsigned char srcAddress = SYN, const string circuit = "");
|
||||
|
||||
// @copydoc
|
||||
virtual unsigned char getIdLength() const { return (unsigned char)(m_ids[0].size() - 2); }
|
||||
|
||||
// @copydoc
|
||||
virtual bool checkId(SymbolString& master, unsigned char* index=NULL);
|
||||
virtual bool checkId(SymbolString& master, unsigned char* index = NULL);
|
||||
|
||||
// @copydoc
|
||||
virtual bool checkId(Message& other);
|
||||
@@ -673,7 +675,7 @@ public:
|
||||
protected:
|
||||
|
||||
// @copydoc
|
||||
virtual void dumpColumn(ostream& output, size_t column, bool withConditions=false);
|
||||
virtual void dumpColumn(ostream& output, size_t column, bool withConditions = false);
|
||||
|
||||
private:
|
||||
|
||||
@@ -729,7 +731,7 @@ public:
|
||||
void push(const value_type& __x)
|
||||
{
|
||||
for (vector<Message*>::iterator it = c.begin(); it != c.end(); it++) {
|
||||
if (*it==__x) {
|
||||
if (*it == __x) {
|
||||
c.erase(it);
|
||||
break;
|
||||
}
|
||||
@@ -781,7 +783,7 @@ public:
|
||||
* @param output the @a ostream to append to.
|
||||
* @param matched true for dumping the matched value if the condition is true, false for dumping the definition.
|
||||
*/
|
||||
virtual void dump(ostream& output, bool matched=false) = 0;
|
||||
virtual void dump(ostream& output, bool matched = false) = 0;
|
||||
|
||||
/**
|
||||
* Combine this condition with another instance using a logical and.
|
||||
@@ -797,7 +799,7 @@ public:
|
||||
* @param readMessageFunc the function to call for immediate reading of a @a Message from the bus, or NULL.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message)=NULL) = 0;
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message) = NULL) = 0;
|
||||
|
||||
/**
|
||||
* Check and return whether this condition is fulfilled.
|
||||
@@ -833,7 +835,7 @@ public:
|
||||
* @param field the field name.
|
||||
* @param hasValues whether a value has to be checked against.
|
||||
*/
|
||||
SimpleCondition(const string condName, const string refName, const string circuit, const string name, const unsigned char dstAddress, const string field, const bool hasValues=false)
|
||||
SimpleCondition(const string condName, const string refName, const string circuit, const string name, const unsigned char dstAddress, const string field, const bool hasValues = false)
|
||||
: Condition(),
|
||||
m_condName(condName), m_refName(refName), m_circuit(circuit), m_name(name), m_dstAddress(dstAddress), m_field(field), m_hasValues(hasValues), m_message(NULL) { }
|
||||
|
||||
@@ -846,13 +848,13 @@ public:
|
||||
virtual SimpleCondition* derive(string valueList);
|
||||
|
||||
// @copydoc
|
||||
virtual void dump(ostream& output, bool matched=false);
|
||||
virtual void dump(ostream& output, bool matched = false);
|
||||
|
||||
// @copydoc
|
||||
virtual CombinedCondition* combineAnd(Condition* other);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message)=NULL);
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message) = NULL);
|
||||
|
||||
// @copydoc
|
||||
virtual bool isTrue();
|
||||
@@ -1005,13 +1007,13 @@ public:
|
||||
virtual ~CombinedCondition() {}
|
||||
|
||||
// @copydoc
|
||||
virtual void dump(ostream& output, bool matched=false);
|
||||
virtual void dump(ostream& output, bool matched = false);
|
||||
|
||||
// @copydoc
|
||||
virtual CombinedCondition* combineAnd(Condition* other) { m_conditions.push_back(other); return this; }
|
||||
|
||||
// @copydoc
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message)=NULL);
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message) = NULL);
|
||||
|
||||
// @copydoc
|
||||
virtual bool isTrue();
|
||||
@@ -1158,7 +1160,7 @@ public:
|
||||
* Construct a new instance.
|
||||
* @param addAll whether to add all messages, even if duplicate.
|
||||
*/
|
||||
MessageMap(const bool addAll=false) : FileReader::FileReader(true),
|
||||
MessageMap(const bool addAll = false) : FileReader::FileReader(true),
|
||||
m_addAll(addAll), m_maxIdLength(0), m_messageCount(0), m_conditionalMessageCount(0), m_passiveMessageCount(0)
|
||||
{
|
||||
m_scanMessage = Message::createScanMessage();
|
||||
@@ -1179,7 +1181,7 @@ public:
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
* Note: the caller may not free the added instance on success.
|
||||
*/
|
||||
result_t add(Message* message, bool storeByName=true);
|
||||
result_t add(Message* message, bool storeByName = true);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t addDefaultFromFile(vector< vector<string> >& defaults, vector<string>& row,
|
||||
@@ -1205,14 +1207,14 @@ public:
|
||||
* @param dstAddress the destination address, or @a SYN for the base scan @a Message.
|
||||
* @return the scan @a Message instance, or NULL if the dstAddress is no slave.
|
||||
*/
|
||||
Message* getScanMessage(const unsigned char dstAddress=SYN);
|
||||
Message* getScanMessage(const unsigned char dstAddress = SYN);
|
||||
|
||||
/**
|
||||
* Resolve all @a Condition instances.
|
||||
* @param verbose whether to verbosely add all problems to the error message.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t resolveConditions(bool verbose=false);
|
||||
result_t resolveConditions(bool verbose = false);
|
||||
|
||||
/**
|
||||
* Resolve a @a Condition.
|
||||
@@ -1220,7 +1222,7 @@ public:
|
||||
* @param readMessageFunc the function to call for immediate reading of a @a Message from the bus, or NULL.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t resolveCondition(Condition* condition, void (*readMessageFunc)(Message* message)=NULL);
|
||||
result_t resolveCondition(Condition* condition, void (*readMessageFunc)(Message* message) = NULL);
|
||||
|
||||
/**
|
||||
* Run all executable @a Instruction instances.
|
||||
@@ -1229,7 +1231,7 @@ public:
|
||||
* @a Message values from the bus required for singleton instructions, or NULL.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t executeInstructions(ostringstream& log, void (*readMessageFunc)(Message* message)=NULL);
|
||||
result_t executeInstructions(ostringstream& log, void (*readMessageFunc)(Message* message) = NULL);
|
||||
|
||||
/**
|
||||
* Add a loaded file to a participant.
|
||||
@@ -1263,7 +1265,7 @@ public:
|
||||
* @return the @a Message instance, or NULL.
|
||||
* Note: the caller may not free the returned instance.
|
||||
*/
|
||||
Message* find(const string& circuit, const string& name, const bool isWrite, const bool isPassive=false);
|
||||
Message* find(const string& circuit, const string& name, const bool isWrite, const bool isPassive = false);
|
||||
|
||||
/**
|
||||
* Find all active get @a Message instances for the specified circuit and name.
|
||||
@@ -1280,10 +1282,10 @@ public:
|
||||
* @param until the end time to which to add updates (exclusive, also removes messages with unset destination address), or 0 to ignore.
|
||||
* Note: the caller may not free the returned instances.
|
||||
*/
|
||||
deque<Message*> findAll(const string& circuit, const string& name, const bool completeMatch=true,
|
||||
const bool withRead=true, const bool withWrite=false, const bool withPassive=false,
|
||||
const bool completeMatchIgnoreCircuitSuffix=false, const bool onlyAvailable=true,
|
||||
const time_t since=0, const time_t until=0);
|
||||
deque<Message*> findAll(const string& circuit, const string& name, const bool completeMatch = true,
|
||||
const bool withRead = true, const bool withWrite = false, const bool withPassive = false,
|
||||
const bool completeMatchIgnoreCircuitSuffix = false, const bool onlyAvailable = true,
|
||||
const time_t since = 0, const time_t until = 0);
|
||||
|
||||
/**
|
||||
* Find the @a Message instance for the specified master data.
|
||||
@@ -1295,8 +1297,8 @@ public:
|
||||
* @return the @a Message instance, or NULL.
|
||||
* Note: the caller may not free the returned instance.
|
||||
*/
|
||||
Message* find(SymbolString& master, bool anyDestination=false,
|
||||
const bool withRead=true, const bool withWrite=true, const bool withPassive=true);
|
||||
Message* find(SymbolString& master, bool anyDestination = false,
|
||||
const bool withRead = true, const bool withWrite = true, const bool withPassive = true);
|
||||
|
||||
/**
|
||||
* Invalidate cached data of the @a Message and all other instances with a matching name key.
|
||||
@@ -1309,7 +1311,7 @@ public:
|
||||
* @param message the @a Message to poll.
|
||||
* @param toFront whether to add the @a Message to the very front of the poll queue.
|
||||
*/
|
||||
void addPollMessage(Message* message, bool toFront=false);
|
||||
void addPollMessage(Message* message, bool toFront = false);
|
||||
|
||||
/**
|
||||
* Removes all @a Message instances.
|
||||
@@ -1364,7 +1366,7 @@ public:
|
||||
* @param output the @a ostream to append the formatted messages to.
|
||||
* @param withConditions whether to include the optional conditions prefix.
|
||||
*/
|
||||
void dump(ostream& output, bool withConditions=false);
|
||||
void dump(ostream& output, bool withConditions = false);
|
||||
|
||||
private:
|
||||
|
||||
@@ -1406,4 +1408,4 @@ private:
|
||||
|
||||
};
|
||||
|
||||
#endif // LIBEBUS_MESSAGE_H_
|
||||
#endif // LIB_EBUS_MESSAGE_H_
|
||||
|
||||
@@ -51,8 +51,9 @@ const char* getResultCode(result_t resultCode) {
|
||||
case RESULT_ERR_SYN: return "ERR: SYN received";
|
||||
|
||||
default:
|
||||
if (resultCode >= 0)
|
||||
if (resultCode >= 0) {
|
||||
return "done: unknown result code";
|
||||
}
|
||||
return "ERR: unknown result code";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_RESULT_H_
|
||||
#define LIBEBUS_RESULT_H_
|
||||
#ifndef LIB_EBUS_RESULT_H_
|
||||
#define LIB_EBUS_RESULT_H_
|
||||
|
||||
/** @file result.h
|
||||
* Functions, and constants related to execution results.
|
||||
@@ -70,4 +70,4 @@ enum result_t {
|
||||
*/
|
||||
const char* getResultCode(result_t resultCode);
|
||||
|
||||
#endif // LIBEBUS_RESULT_H_
|
||||
#endif // LIB_EBUS_RESULT_H_
|
||||
|
||||
+12
-14
@@ -17,9 +17,11 @@
|
||||
*/
|
||||
|
||||
#include "symbol.h"
|
||||
#include "result.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "result.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -47,13 +49,12 @@ static const unsigned char CRC_LOOKUP_TABLE[] =
|
||||
};
|
||||
|
||||
|
||||
void SymbolString::addAll(const SymbolString& str, bool skipLastSymbol)
|
||||
{
|
||||
void SymbolString::addAll(const SymbolString& str, bool skipLastSymbol) {
|
||||
bool addCrc = m_unescapeState == 0;
|
||||
bool isEscaped = str.m_unescapeState == 0;
|
||||
vector<unsigned char> data = str.m_data;
|
||||
size_t end = data.size();
|
||||
if (end>0 && skipLastSymbol) {
|
||||
if (end > 0 && skipLastSymbol) {
|
||||
end--;
|
||||
}
|
||||
for (size_t i = 0; i < end; i++) {
|
||||
@@ -64,8 +65,7 @@ void SymbolString::addAll(const SymbolString& str, bool skipLastSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
result_t SymbolString::parseHex(const string& str, const bool isEscaped)
|
||||
{
|
||||
result_t SymbolString::parseHex(const string& str, const bool isEscaped) {
|
||||
bool addCrc = m_unescapeState == 0;
|
||||
for (size_t i = 0; i < str.size(); i += 2) {
|
||||
char* strEnd = NULL;
|
||||
@@ -83,8 +83,7 @@ result_t SymbolString::parseHex(const string& str, const bool isEscaped)
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
const string SymbolString::getDataStr(const bool unescape, const bool skipLastSymbol)
|
||||
{
|
||||
const string SymbolString::getDataStr(const bool unescape, const bool skipLastSymbol) {
|
||||
stringstream sstr;
|
||||
bool previousEscape = false;
|
||||
|
||||
@@ -111,8 +110,7 @@ const string SymbolString::getDataStr(const bool unescape, const bool skipLastSy
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
result_t SymbolString::push_back(const unsigned char value, const bool isEscaped, const bool updateCRC)
|
||||
{
|
||||
result_t SymbolString::push_back(const unsigned char value, const bool isEscaped, const bool updateCRC) {
|
||||
if (m_unescapeState == 0) { // store escaped data
|
||||
if (!isEscaped && value == ESC) {
|
||||
m_data.push_back(ESC);
|
||||
@@ -214,8 +212,8 @@ unsigned char getMasterPartIndex(unsigned char bits) {
|
||||
}
|
||||
|
||||
bool isMaster(unsigned char addr) {
|
||||
return getMasterPartIndex(addr & 0x0F)>0
|
||||
&& getMasterPartIndex((addr & 0xF0) >> 4)>0;
|
||||
return getMasterPartIndex(addr & 0x0F) > 0
|
||||
&& getMasterPartIndex((addr & 0xF0)>>4) > 0;
|
||||
}
|
||||
|
||||
bool isSlaveMaster(unsigned char addr) {
|
||||
@@ -245,11 +243,11 @@ unsigned char getMasterAddress(unsigned char addr) {
|
||||
|
||||
unsigned char getMasterNumber(unsigned char addr) {
|
||||
unsigned char priority = getMasterPartIndex(addr & 0x0F);
|
||||
if (priority==0) {
|
||||
if (priority == 0) {
|
||||
return 0;
|
||||
}
|
||||
unsigned char index = getMasterPartIndex((addr & 0xF0) >> 4);
|
||||
if (index==0) {
|
||||
if (index == 0) {
|
||||
return 0;
|
||||
}
|
||||
return (unsigned char)(5*(priority-1) + index);
|
||||
|
||||
+30
-20
@@ -16,14 +16,18 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_SYMBOL_H_
|
||||
#define LIBEBUS_SYMBOL_H_
|
||||
#ifndef LIB_EBUS_SYMBOL_H_
|
||||
#define LIB_EBUS_SYMBOL_H_
|
||||
|
||||
#include "result.h"
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "result.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/** @file symbol.h
|
||||
* Classes, functions, and constants related to symbols on the eBUS.
|
||||
@@ -61,8 +65,6 @@
|
||||
* non-acknowledge, the receiving slave has to repeat its data once.
|
||||
*/
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const unsigned char ESC = 0xA9; //!< escape symbol, either followed by 0x00 for the value 0xA9, or 0x01 for the value 0xAA
|
||||
static const unsigned char SYN = 0xAA; //!< synchronization symbol
|
||||
static const unsigned char ACK = 0x00; //!< positive acknowledge
|
||||
@@ -81,14 +83,14 @@ public:
|
||||
* Creates a new empty escaped or unescaped instance.
|
||||
* @param escaped whether to create an escaped instance.
|
||||
*/
|
||||
SymbolString(const bool escaped=true) : m_unescapeState(escaped ? 0 : 1), m_crc(0) {}
|
||||
SymbolString(const bool escaped = true) : m_unescapeState(escaped ? 0 : 1), m_crc(0) {}
|
||||
|
||||
/**
|
||||
* Add all symbols from the other @a SymbolString and the calculated CRC if escaped.
|
||||
* @param str the @a SymbolString to copy from.
|
||||
* @param skipLastSymbol whether to skip the last symbol (probably the CRC).
|
||||
*/
|
||||
void addAll(const SymbolString& str, const bool skipLastSymbol=false);
|
||||
void addAll(const SymbolString& str, const bool skipLastSymbol = false);
|
||||
|
||||
/**
|
||||
* Parse the escaped or unescaped hex @a string, add all symbols, and add the calculated CRC if escaped.
|
||||
@@ -96,7 +98,7 @@ public:
|
||||
* @param isEscaped whether the hex string is escaped.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t parseHex(const string& str, const bool isEscaped=false);
|
||||
result_t parseHex(const string& str, const bool isEscaped = false);
|
||||
|
||||
/**
|
||||
* Return the symbols as hex string.
|
||||
@@ -104,28 +106,28 @@ public:
|
||||
* @param skipLastSymbol whether to skip the last symbol (probably the CRC).
|
||||
* @return the symbols as hex string.
|
||||
*/
|
||||
const string getDataStr(const bool unescape=true, const bool skipLastSymbol=true);
|
||||
const string getDataStr(const bool unescape = true, const bool skipLastSymbol = true);
|
||||
|
||||
/**
|
||||
* Return a reference to the symbol at the specified index.
|
||||
* @param index the index of the symbol to return.
|
||||
* @return the reference to the symbol at the specified index.
|
||||
*/
|
||||
unsigned char& operator[](const size_t index) { if (index >= m_data.size()) m_data.resize(index+1, 0); return m_data[index]; }
|
||||
unsigned char& operator[](const size_t index) { if (index >= m_data.size()) { m_data.resize(index+1, 0); } return m_data[index]; }
|
||||
|
||||
/**
|
||||
* Return whether this instance is equal to the other instance.
|
||||
* @param other the other instance.
|
||||
* @return true if this instance is equal to the other instance (i.e. both escaped or both unescaped and same symbols).
|
||||
*/
|
||||
bool operator==(SymbolString& other) { return m_unescapeState==other.m_unescapeState && m_data==other.m_data; }
|
||||
bool operator == (SymbolString& other) { return m_unescapeState == other.m_unescapeState && m_data == other.m_data; }
|
||||
|
||||
/**
|
||||
* Return whether this instance is different from the other instance.
|
||||
* @param other the other instance.
|
||||
* @return true if this instance is different from the other instance.
|
||||
*/
|
||||
bool operator!=(SymbolString& other) { return m_unescapeState!=other.m_unescapeState || m_data!=other.m_data; }
|
||||
bool operator != (SymbolString& other) { return m_unescapeState != other.m_unescapeState || m_data != other.m_data; }
|
||||
|
||||
/**
|
||||
* Compares this instance to the other instance while treating both as master data (i.e. starting with the master address and ending with the CRC).
|
||||
@@ -135,10 +137,18 @@ public:
|
||||
* 2 if this instance only differs from the other instance in the first byte (the master address).
|
||||
*/
|
||||
int compareMaster(SymbolString& other) {
|
||||
if (m_unescapeState!=other.m_unescapeState || m_data.size()!=other.m_data.size()) return 1;
|
||||
if (m_data==other.m_data) return 0;
|
||||
if (m_data.size()==1) return 2;
|
||||
if (equal(m_data.begin()+1, m_data.end()-1, other.m_data.begin()+1)) return 2;
|
||||
if (m_unescapeState != other.m_unescapeState || m_data.size() != other.m_data.size()) {
|
||||
return 1;
|
||||
}
|
||||
if (m_data == other.m_data) {
|
||||
return 0;
|
||||
}
|
||||
if (m_data.size() == 1) {
|
||||
return 2;
|
||||
}
|
||||
if (equal(m_data.begin()+1, m_data.end()-1, other.m_data.begin()+1)) {
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -151,7 +161,7 @@ public:
|
||||
* RESULT_IN_ESC if this is an unescaped instance and the symbol is escaped and the start of the escape sequence was received,
|
||||
* RESULT_ERR_ESC if this is an unescaped instance and an invalid escaped sequence was detected.
|
||||
*/
|
||||
result_t push_back(const unsigned char value, const bool isEscaped=true, const bool updateCRC=true);
|
||||
result_t push_back(const unsigned char value, const bool isEscaped = true, const bool updateCRC = true);
|
||||
|
||||
/**
|
||||
* Return the number of symbols in this symbol string.
|
||||
@@ -168,7 +178,7 @@ public:
|
||||
/**
|
||||
* Clear the symbols.
|
||||
*/
|
||||
void clear() { m_data.clear(); m_unescapeState = m_unescapeState==0 ? 0 : 1; m_crc = 0; }
|
||||
void clear() { m_data.clear(); m_unescapeState = m_unescapeState == 0 ? 0 : 1; m_crc = 0; }
|
||||
|
||||
/**
|
||||
* Clear the symbols and adjust the escape mode.
|
||||
@@ -247,6 +257,6 @@ unsigned char getMasterNumber(unsigned char addr);
|
||||
* @param allowBroadcast whether to also allow @a addr to be the broadcast address (default true).
|
||||
* @return <code>true</code> if the specified address is a valid bus address.
|
||||
*/
|
||||
bool isValidAddress(unsigned char addr, bool allowBroadcast=true);
|
||||
bool isValidAddress(unsigned char addr, bool allowBroadcast = true);
|
||||
|
||||
#endif // LIBEBUS_SYMBOL_H_
|
||||
#endif // LIB_EBUS_SYMBOL_H_
|
||||
|
||||
@@ -16,17 +16,18 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "data.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "data.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static bool error = false;
|
||||
|
||||
void verify(bool expectFailMatch, string type, string input,
|
||||
bool match, string expectStr, string gotStr)
|
||||
{
|
||||
bool match, string expectStr, string gotStr) {
|
||||
match = match && expectStr == gotStr;
|
||||
if (expectFailMatch) {
|
||||
if (match) {
|
||||
@@ -45,8 +46,7 @@ void verify(bool expectFailMatch, string type, string input,
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
string checks[][5] = {
|
||||
// entry: definition, decoded value, master data, slave data, flags
|
||||
// definition: name,part,type[:len][,[divisor|values][,[unit][,[comment]]]]
|
||||
@@ -63,9 +63,9 @@ int main()
|
||||
{"x,,str:*", "abcde", "10fe0700056162636465", "00", ""},
|
||||
{"x,,str,2", "", "", "", "c"},
|
||||
{"x,,str:10,=dummy", "", "10fe07000a48616c6c6f2044752120", "00", "W"},
|
||||
{"x,,str:10,==dummy", "", "10fe07000a48616c6c6f2044752120", "00", "rW"},
|
||||
{"x,,str:10, == dummy", "", "10fe07000a48616c6c6f2044752120", "00", "rW"},
|
||||
{"x,,str:10,=dummy", "", "10fe07000a64756d6d792020202020", "00", ""},
|
||||
{"x,,str:10,==dummy", "", "10fe07000a64756d6d792020202020", "00", ""},
|
||||
{"x,,str:10, == dummy", "", "10fe07000a64756d6d792020202020", "00", ""},
|
||||
{"x,,nts:10", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""},
|
||||
{"x,,nts:10", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""},
|
||||
{"x,,nts:10", "Hallo, Du", "10fe07000a48616c6c6f2c20447500", "00", ""},
|
||||
@@ -83,9 +83,9 @@ int main()
|
||||
{"x,,hex:11", "", "10fe07000a48616c6c6f2c20447521", "00", "rW"},
|
||||
{"x,,hex,2", "", "", "", "c"},
|
||||
{"x,,hex:5,=48 61 6c 6c 6f", "", "10fe070005ababababab", "00", "W"},
|
||||
{"x,,hex:5,==48 61 6c 6c 6f", "", "10fe070005ababababab", "00", "rW"},
|
||||
{"x,,hex:5, == 48 61 6c 6c 6f", "", "10fe070005ababababab", "00", "rW"},
|
||||
{"x,,hex:5,=48 61 6c 6c 6f", "", "10fe07000548616c6c6f", "00", ""},
|
||||
{"x,,hex:5,==48 61 6c 6c 6f", "", "10fe07000548616c6c6f", "00", ""},
|
||||
{"x,,hex:5, == 48 61 6c 6c 6f", "", "10fe07000548616c6c6f", "00", ""},
|
||||
{"x,,bda", "26.10.2014","10fe07000426100614", "00", ""}, // Sunday
|
||||
{"x,,bda", "01.01.2000","10fe07000401010500", "00", ""}, // Saturday
|
||||
{"x,,bda", "31.12.2099","10fe07000431120399", "00", ""}, // Thursday
|
||||
@@ -264,9 +264,9 @@ int main()
|
||||
{"x,,uch,10", "3.8", "10feffff0126", "00", ""},
|
||||
{"x,,uch,-10", "380","10feffff0126", "00", ""},
|
||||
{"x,,uch,=48", "", "10feffff01ab", "00", "W"},
|
||||
{"x,,uch,==48", "", "10feffff01ab", "00", "rW"},
|
||||
{"x,,uch, == 48", "", "10feffff01ab", "00", "rW"},
|
||||
{"x,,uch,=48", "", "10feffff0130", "00", ""},
|
||||
{"x,,uch,==48", "", "10feffff0130", "00", ""},
|
||||
{"x,,uch, == 48", "", "10feffff0130", "00", ""},
|
||||
{"x,,sch", "-90", "10feffff01a6", "00", ""},
|
||||
{"x,,sch", "0", "10feffff0100", "00", ""},
|
||||
{"x,,sch", "-1", "10feffff01ff", "00", ""},
|
||||
@@ -510,7 +510,7 @@ int main()
|
||||
fields = NULL;
|
||||
}
|
||||
vector<string>::iterator it = entries.begin();
|
||||
result = DataField::create(it, entries.end(), templates, fields, isSet, isTemplate, !isTemplate && (mstr[1]==BROADCAST || isMaster(mstr[1])));
|
||||
result = DataField::create(it, entries.end(), templates, fields, isSet, isTemplate, !isTemplate && (mstr[1] == BROADCAST || isMaster(mstr[1])));
|
||||
if (failedCreate) {
|
||||
if (result == RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": failed create error: unexpectedly succeeded" << endl;
|
||||
@@ -568,7 +568,7 @@ int main()
|
||||
if (result >= RESULT_OK) {
|
||||
result = fields->read(pt_slaveData, sstr, 0, output, verbosity|(numeric?OF_NUMERIC:0), -1, !output.str().empty());
|
||||
}
|
||||
if (failedRead)
|
||||
if (failedRead) {
|
||||
if (result >= RESULT_OK) {
|
||||
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
|
||||
<< "< error: unexpectedly succeeded" << endl;
|
||||
@@ -577,21 +577,21 @@ int main()
|
||||
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
|
||||
<< "< OK" << endl;
|
||||
}
|
||||
else if (result < RESULT_OK) {
|
||||
} else if (result < RESULT_OK) {
|
||||
cout << " read " << fields->getName() << " >" << check[2] << " " << check[3]
|
||||
<< "< error: " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
bool match = strcasecmp(output.str().c_str(), expectStr.c_str()) == 0;
|
||||
verify(failedReadMatch, "read", check[2], match, expectStr, output.str());
|
||||
}
|
||||
|
||||
if (verbosity==0) {
|
||||
if (verbosity == 0) {
|
||||
istringstream input(expectStr);
|
||||
result = fields->write(input, pt_masterData, writeMstr, 0);
|
||||
if (result >= RESULT_OK)
|
||||
if (result >= RESULT_OK) {
|
||||
result = fields->write(input, pt_slaveData, writeSstr, 0);
|
||||
}
|
||||
if (failedWrite) {
|
||||
if (result >= RESULT_OK) {
|
||||
cout << " failed write " << fields->getName() << " >"
|
||||
@@ -601,8 +601,7 @@ int main()
|
||||
cout << " failed write " << fields->getName() << " >"
|
||||
<< expectStr << "< OK" << endl;
|
||||
}
|
||||
}
|
||||
else if (result < RESULT_OK) {
|
||||
} else if (result < RESULT_OK) {
|
||||
cout << " write " << fields->getName() << " >" << expectStr
|
||||
<< "< error: " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
|
||||
@@ -16,14 +16,13 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "device.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include "device.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main ()
|
||||
{
|
||||
int main () {
|
||||
Device* device = Device::create("/dev/ttyUSB20", true, false, false);
|
||||
if (device == NULL) {
|
||||
cout << "unable to create device" << endl;
|
||||
@@ -33,26 +32,27 @@ int main ()
|
||||
if (result != RESULT_OK) {
|
||||
cout << "open failed: " << getResultCode(result) << endl;
|
||||
} else {
|
||||
if (!device->isValid())
|
||||
if (!device->isValid()) {
|
||||
cout << "device not available." << endl;
|
||||
|
||||
}
|
||||
int count = 0;
|
||||
|
||||
while (1) {
|
||||
unsigned char byte = 0;
|
||||
result = device->recv(0, byte);
|
||||
|
||||
if (result == RESULT_OK)
|
||||
if (result == RESULT_OK) {
|
||||
cout << hex << setw(2) << setfill('0')
|
||||
<< static_cast<unsigned>(byte) << endl;
|
||||
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
device->close();
|
||||
|
||||
if (!device->isValid())
|
||||
if (!device->isValid()) {
|
||||
cout << "close successful." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
delete device;
|
||||
|
||||
@@ -16,17 +16,18 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "filereader.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "filereader.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static bool error = false;
|
||||
|
||||
void verify(bool expectFailMatch, string type, string input,
|
||||
bool match, string expectStr, string gotStr)
|
||||
{
|
||||
bool match, string expectStr, string gotStr) {
|
||||
match = match && expectStr == gotStr;
|
||||
if (expectFailMatch) {
|
||||
if (match) {
|
||||
@@ -45,8 +46,7 @@ void verify(bool expectFailMatch, string type, string input,
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
istringstream ifs(
|
||||
"line 1 col 1,line 1 col 2,line 1 col 3\n"
|
||||
"line 2 col 1,\"line 2 col 2\",\"line 2 \"\"col 3\"\"\"\n"
|
||||
|
||||
@@ -16,41 +16,43 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "message.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "message.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void verify(bool expectFailMatch, string type, string input,
|
||||
bool match, string expectStr, string gotStr)
|
||||
{
|
||||
bool match, string expectStr, string gotStr) {
|
||||
if (expectFailMatch) {
|
||||
if (match)
|
||||
if (match) {
|
||||
cout << " failed " << type << " match >" << input
|
||||
<< "< error: unexpectedly succeeded" << endl;
|
||||
else
|
||||
} else {
|
||||
cout << " failed " << type << " match >" << input << "< OK" << endl;
|
||||
}
|
||||
else if (match)
|
||||
}
|
||||
} else if (match) {
|
||||
cout << " " << type << " match >" << input << "< OK" << endl;
|
||||
else
|
||||
} else {
|
||||
cout << " " << type << " match >" << input << "< error: got >"
|
||||
<< gotStr << "<, expected >" << expectStr << "<" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
DataFieldTemplates* templates = NULL;
|
||||
|
||||
DataFieldTemplates* getTemplates(const string filename)
|
||||
{
|
||||
if (filename=="") // avoid compiler warning
|
||||
DataFieldTemplates* getTemplates(const string filename) {
|
||||
if (filename == "") { // avoid compiler warning
|
||||
return templates;
|
||||
}
|
||||
return templates;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
// message: [type],[circuit],name,[comment],[QQ[;QQ]*],[ZZ],[PBSB],[ID],fields...
|
||||
// field: name,part,type[:len][,[divisor|values][,[unit][,[comment]]]]
|
||||
// template: name,type[:len][,[divisor|values][,[unit][,[comment]]]]
|
||||
@@ -167,17 +169,16 @@ int main()
|
||||
DataField* fields = NULL;
|
||||
vector<string>::iterator it = entries.begin();
|
||||
result = DataField::create(it, entries.end(), templates, fields, false, true, false);
|
||||
if (result != RESULT_OK)
|
||||
if (result != RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": template fields create error: " << getResultCode(result) << endl;
|
||||
else if (it != entries.end()) {
|
||||
} else if (it != entries.end()) {
|
||||
cout << "\"" << check[0] << "\": template fields create error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
cout << "\"" << check[0] << "\": create template OK" << endl;
|
||||
result = templates->add(fields, "", true);
|
||||
if (result == RESULT_OK)
|
||||
if (result == RESULT_OK) {
|
||||
cout << " store template OK" << endl;
|
||||
else {
|
||||
} else {
|
||||
cout << " store template error: " << getResultCode(result) << endl;
|
||||
delete fields;
|
||||
}
|
||||
@@ -189,21 +190,22 @@ int main()
|
||||
vector<string>::iterator it = entries.begin();
|
||||
size_t oldSize = conditions.size();
|
||||
result = messages->addDefaultFromFile(defaultsRows, entries, it, "", "", "", "no file", 1);
|
||||
if (result != RESULT_OK)
|
||||
if (result != RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": defaults read error: " << getResultCode(result) << endl;
|
||||
else if (it != entries.end())
|
||||
} else if (it != entries.end()) {
|
||||
cout << "\"" << check[0] << "\": defaults read error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl;
|
||||
else {
|
||||
} else {
|
||||
cout << "\"" << check[0] << "\": read defaults OK" << endl;
|
||||
if (isCondition) {
|
||||
if (conditions.size()==oldSize) {
|
||||
if (conditions.size() == oldSize) {
|
||||
cout << " create condition error" << endl;
|
||||
} else {
|
||||
result = messages->resolveConditions();
|
||||
if (result != RESULT_OK)
|
||||
if (result != RESULT_OK) {
|
||||
cout << " resolve conditions error: " << getResultCode(result) << " " << messages->getLastError() << endl;
|
||||
else
|
||||
} else {
|
||||
cout << " resolve conditions OK" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,10 +216,11 @@ int main()
|
||||
string token;
|
||||
istringstream stream(check[2]);
|
||||
while (getline(stream, token, VALUE_SEPARATOR)) {
|
||||
if (pos >= mstrs.size())
|
||||
if (pos >= mstrs.size()) {
|
||||
mstrs.resize(pos+1);
|
||||
else if (mstrs[pos]!=NULL)
|
||||
} else if (mstrs[pos] != NULL) {
|
||||
delete mstrs[pos];
|
||||
}
|
||||
mstrs[pos] = new SymbolString(false);
|
||||
result = mstrs[pos]->parseHex(token);
|
||||
if (result != RESULT_OK) {
|
||||
@@ -230,10 +233,11 @@ int main()
|
||||
stream.str(check[3]);
|
||||
stream.clear();
|
||||
while (getline(stream, token, VALUE_SEPARATOR)) {
|
||||
if (pos >= sstrs.size())
|
||||
if (pos >= sstrs.size()) {
|
||||
sstrs.resize(pos+1);
|
||||
else if (sstrs[pos]!=NULL)
|
||||
} else if (sstrs[pos] != NULL) {
|
||||
delete sstrs[pos];
|
||||
}
|
||||
sstrs[pos] = new SymbolString(false);
|
||||
result = sstrs[pos]->parseHex(token);
|
||||
if (result != RESULT_OK) {
|
||||
@@ -242,19 +246,22 @@ int main()
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
if (result != RESULT_OK)
|
||||
if (result != RESULT_OK) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (mstrs[0]!=NULL)
|
||||
if (mstrs[0] != NULL) {
|
||||
delete mstrs[0];
|
||||
}
|
||||
mstrs[0] = new SymbolString(false);
|
||||
result = mstrs[0]->parseHex(check[2]);
|
||||
if (result != RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": parse \"" << check[2] << "\" error: " << getResultCode(result) << endl;
|
||||
continue;
|
||||
}
|
||||
if (sstrs[0]!=NULL)
|
||||
if (sstrs[0] != NULL) {
|
||||
delete sstrs[0];
|
||||
}
|
||||
sstrs[0] = new SymbolString(false);
|
||||
result = sstrs[0]->parseHex(check[3]);
|
||||
if (result != RESULT_OK) {
|
||||
@@ -263,7 +270,7 @@ int main()
|
||||
}
|
||||
}
|
||||
|
||||
if (deleteMessages.size()>0) {
|
||||
if (deleteMessages.size() > 0) {
|
||||
for (vector<Message*>::iterator it = deleteMessages.begin(); it != deleteMessages.end(); it++) {
|
||||
Message* deleteMessage = *it;
|
||||
delete deleteMessage;
|
||||
@@ -282,15 +289,16 @@ int main()
|
||||
string types = *it;
|
||||
Condition* condition = NULL;
|
||||
result = messages->readConditions(types, "no file", condition);
|
||||
if (result==RESULT_OK) {
|
||||
if (result == RESULT_OK) {
|
||||
*it = types;
|
||||
result = Message::create(it, entries.end(), &defaultsRows, condition, "no file", templates, deleteMessages);
|
||||
}
|
||||
if (failedCreate) {
|
||||
if (result == RESULT_OK)
|
||||
if (result == RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": failed create error: unexpectedly succeeded" << endl;
|
||||
else
|
||||
} else {
|
||||
cout << "\"" << check[0] << "\": failed create OK" << endl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (result != RESULT_OK) {
|
||||
@@ -299,7 +307,7 @@ int main()
|
||||
printErrorPos(cout, entries.begin(), entries.end(), it, "", 0, result);
|
||||
continue;
|
||||
}
|
||||
if (deleteMessages.size()==0) {
|
||||
if (deleteMessages.size() == 0) {
|
||||
cout << "\"" << check[0] << "\": create error: NULL" << endl;
|
||||
continue;
|
||||
}
|
||||
@@ -307,11 +315,11 @@ int main()
|
||||
cout << "\"" << check[0] << "\": create error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl;
|
||||
continue;
|
||||
}
|
||||
if (multi && deleteMessages.size()==1) {
|
||||
if (multi && deleteMessages.size() == 1) {
|
||||
cout << "\"" << check[0] << "\": create error: single message instead of multiple" << endl;
|
||||
continue;
|
||||
}
|
||||
if (!multi && deleteMessages.size()>1) {
|
||||
if (!multi && deleteMessages.size() > 1) {
|
||||
cout << "\"" << check[0] << "\": create error: multiple messages instead of single" << endl;
|
||||
continue;
|
||||
}
|
||||
@@ -327,28 +335,31 @@ int main()
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result != RESULT_OK)
|
||||
if (result != RESULT_OK) {
|
||||
continue;
|
||||
}
|
||||
cout << " map OK" << endl;
|
||||
message = deleteMessages.front();
|
||||
deleteMessages.clear();
|
||||
if (onlyMap)
|
||||
if (onlyMap) {
|
||||
continue;
|
||||
}
|
||||
Message* foundMessage = messages->find(*mstrs[0]);
|
||||
if (foundMessage == message)
|
||||
if (foundMessage == message) {
|
||||
cout << " find OK" << endl;
|
||||
else if (foundMessage == NULL)
|
||||
} else if (foundMessage == NULL) {
|
||||
cout << " find error: NULL" << endl;
|
||||
else
|
||||
} else {
|
||||
cout << " find error: different" << endl;
|
||||
}
|
||||
else
|
||||
}
|
||||
} else {
|
||||
message = deleteMessages.front();
|
||||
}
|
||||
}
|
||||
|
||||
if (message->isPassive() || decode) {
|
||||
ostringstream output;
|
||||
for (unsigned char index=0; index<message->getCount(); index++) {
|
||||
for (unsigned char index = 0; index < message->getCount(); index++) {
|
||||
message->storeLastData(*mstrs[index], *sstrs[index]);
|
||||
}
|
||||
if (withMessageDump && !decodeJson) {
|
||||
@@ -370,10 +381,11 @@ int main()
|
||||
SymbolString writeMstr(false);
|
||||
result = message->prepareMaster(0xff, writeMstr, input);
|
||||
if (failedPrepare) {
|
||||
if (result == RESULT_OK)
|
||||
if (result == RESULT_OK) {
|
||||
cout << " \"" << inputStr << "\": failed prepare error: unexpectedly succeeded" << endl;
|
||||
else
|
||||
} else {
|
||||
cout << " \"" << inputStr << "\": failed prepare OK" << endl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -384,12 +396,12 @@ int main()
|
||||
}
|
||||
cout << " \"" << inputStr << "\": prepare OK" << endl;
|
||||
|
||||
bool match = writeMstr==*mstrs[0];
|
||||
bool match = writeMstr == *mstrs[0];
|
||||
verify(failedPrepareMatch, "prepare", inputStr, match, mstrs[0]->getDataStr(true, false), writeMstr.getDataStr(true, false));
|
||||
}
|
||||
}
|
||||
|
||||
if (deleteMessages.size()>0) {
|
||||
if (deleteMessages.size() > 0) {
|
||||
for (vector<Message*>::iterator it = deleteMessages.begin(); it != deleteMessages.end(); it++) {
|
||||
Message* deleteMessage = *it;
|
||||
delete deleteMessage;
|
||||
@@ -399,10 +411,10 @@ int main()
|
||||
|
||||
delete templates;
|
||||
delete messages;
|
||||
for (vector<SymbolString*>::iterator it = mstrs.begin(); it!=mstrs.end(); it++) {
|
||||
for (vector<SymbolString*>::iterator it = mstrs.begin(); it != mstrs.end(); it++) {
|
||||
delete *it;
|
||||
}
|
||||
for (vector<SymbolString*>::iterator it = sstrs.begin(); it!=sstrs.end(); it++) {
|
||||
for (vector<SymbolString*>::iterator it = sstrs.begin(); it != sstrs.end(); it++) {
|
||||
delete *it;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -16,17 +16,17 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "symbol.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include "symbol.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static bool error = false;
|
||||
|
||||
void verify(bool expectFailMatch, string type, string input,
|
||||
bool match, string expectStr, string gotStr)
|
||||
{
|
||||
bool match, string expectStr, string gotStr) {
|
||||
match = match && expectStr == gotStr;
|
||||
if (expectFailMatch) {
|
||||
if (match) {
|
||||
@@ -45,11 +45,10 @@ void verify(bool expectFailMatch, string type, string input,
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int main(int argc, char** argv) {
|
||||
SymbolString sstr(true);
|
||||
|
||||
if (argc>1) {
|
||||
if (argc > 1) {
|
||||
result_t result = sstr.parseHex(argv[1], true);
|
||||
if (result != RESULT_OK) {
|
||||
cout << "parse escaped error: " << getResultCode(result) << endl;
|
||||
@@ -76,7 +75,7 @@ int main(int argc, char** argv)
|
||||
ostr.str("");
|
||||
ostr << nouppercase << setw(2) << hex << setfill('0') << static_cast<unsigned>(gotCrc);
|
||||
gotStr = ostr.str();
|
||||
verify(false, "CRC", "10feb5050427a915aa", gotCrc==expectCrc, expectStr, gotStr);
|
||||
verify(false, "CRC", "10feb5050427a915aa", gotCrc == expectCrc, expectStr, gotStr);
|
||||
|
||||
gotStr = sstr.getDataStr(true, false), expectStr = "10feb5050427a915aa77";
|
||||
verify(false, "unescape", "10feb5050427a915aa", true, expectStr, gotStr);
|
||||
|
||||
Reference in New Issue
Block a user