added support for conditions based on raw value of numeric fields, adjust error position cout in case of duplicate, added ostream arg to printErrorPos, added separate RESULT_ERR_DUPLICATE_NAME
This commit is contained in:
+105
-8
@@ -135,19 +135,19 @@ int parseSignedInt(const char* str, int base, const int minValue, const int maxV
|
|||||||
return (int)ret;
|
return (int)ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printErrorPos(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)
|
if (pos > begin)
|
||||||
pos--;
|
pos--;
|
||||||
cout << "Error reading \"" << filename << "\" line " << setw(0) << dec << static_cast<unsigned>(lineNo) << " field " << static_cast<unsigned>(1+pos.base()-begin.base()) << " value \"" << *pos << "\": " << getResultCode(result) << endl;
|
out << "Error reading \"" << filename << "\" line " << setw(0) << dec << static_cast<unsigned>(lineNo) << " field " << static_cast<unsigned>(1+pos.base()-begin.base()) << " value \"" << *pos << "\": " << getResultCode(result) << endl;
|
||||||
cout << "Erroneous item is here:" << endl;
|
out << "Erroneous item is here:" << endl;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
while (begin != end) {
|
while (begin != end) {
|
||||||
if (first)
|
if (first)
|
||||||
first = false;
|
first = false;
|
||||||
else {
|
else {
|
||||||
cout << FIELD_SEPARATOR;
|
out << FIELD_SEPARATOR;
|
||||||
if (begin <= pos) {
|
if (begin <= pos) {
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
@@ -158,10 +158,10 @@ void printErrorPos(vector<string>::iterator begin, const vector<string>::iterato
|
|||||||
cnt++;
|
cnt++;
|
||||||
|
|
||||||
string item = *begin++;
|
string item = *begin++;
|
||||||
cout << TEXT_SEPARATOR << item << TEXT_SEPARATOR;
|
out << TEXT_SEPARATOR << item << TEXT_SEPARATOR;
|
||||||
}
|
}
|
||||||
cout << endl;
|
out << endl;
|
||||||
cout << setw(cnt) << " " << setw(0) << "^" << endl;
|
out << setw(cnt) << " " << setw(0) << "^" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -435,6 +435,35 @@ void SingleDataField::dump(ostream& output)
|
|||||||
dumpString(output, m_dataType.name);
|
dumpString(output, m_dataType.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
return RESULT_EMPTY;
|
||||||
|
|
||||||
|
switch (m_partType)
|
||||||
|
{
|
||||||
|
case pt_masterData:
|
||||||
|
offset = (unsigned char)(offset + 5); // skip QQ ZZ PB SB NN
|
||||||
|
break;
|
||||||
|
case pt_slaveData:
|
||||||
|
offset++; // skip NN
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return RESULT_ERR_INVALID_PART;
|
||||||
|
}
|
||||||
|
if (isIgnored() || (fieldName != NULL && (m_name != fieldName || fieldIndex > 0))) {
|
||||||
|
if (offset + m_length > data.size()) {
|
||||||
|
return RESULT_ERR_INVALID_POS;
|
||||||
|
}
|
||||||
|
return RESULT_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return readRawValue(data, offset, output);
|
||||||
|
}
|
||||||
|
|
||||||
result_t SingleDataField::read(const PartType partType,
|
result_t SingleDataField::read(const PartType partType,
|
||||||
SymbolString& data, unsigned char offset,
|
SymbolString& data, unsigned char offset,
|
||||||
ostringstream& output, OutputFormat outputFormat,
|
ostringstream& output, OutputFormat outputFormat,
|
||||||
@@ -539,6 +568,11 @@ result_t StringDataField::derive(string name, string comment,
|
|||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool StringDataField::hasField(const char* fieldName, bool numeric)
|
||||||
|
{
|
||||||
|
return !numeric && fieldName==m_name;
|
||||||
|
}
|
||||||
|
|
||||||
void StringDataField::dump(ostream& output)
|
void StringDataField::dump(ostream& output)
|
||||||
{
|
{
|
||||||
SingleDataField::dump(output);
|
SingleDataField::dump(output);
|
||||||
@@ -549,6 +583,11 @@ void StringDataField::dump(ostream& output)
|
|||||||
dumpString(output, m_comment);
|
dumpString(output, m_comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result_t StringDataField::readRawValue(SymbolString& input, const unsigned char offset, unsigned int& value)
|
||||||
|
{
|
||||||
|
return RESULT_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
result_t StringDataField::readSymbols(SymbolString& input, const unsigned char baseOffset,
|
result_t StringDataField::readSymbols(SymbolString& input, const unsigned char baseOffset,
|
||||||
ostringstream& output, OutputFormat outputFormat)
|
ostringstream& output, OutputFormat outputFormat)
|
||||||
{
|
{
|
||||||
@@ -799,6 +838,11 @@ bool NumericDataField::hasFullByteOffset(bool after)
|
|||||||
|| (after && m_bitOffset + (m_bitCount % 8) >= 8);
|
|| (after && m_bitOffset + (m_bitCount % 8) >= 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NumericDataField::hasField(const char* fieldName, bool numeric)
|
||||||
|
{
|
||||||
|
return numeric && fieldName==m_name;
|
||||||
|
}
|
||||||
|
|
||||||
void NumericDataField::dump(ostream& output)
|
void NumericDataField::dump(ostream& output)
|
||||||
{
|
{
|
||||||
SingleDataField::dump(output);
|
SingleDataField::dump(output);
|
||||||
@@ -1275,6 +1319,16 @@ result_t DataFieldSet::derive(string name, string comment,
|
|||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void DataFieldSet::dump(ostream& output)
|
void DataFieldSet::dump(ostream& output)
|
||||||
{
|
{
|
||||||
bool first = true;
|
bool first = true;
|
||||||
@@ -1287,6 +1341,46 @@ 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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!previousFullByteOffset && !field->hasFullByteOffset(false))
|
||||||
|
offset--;
|
||||||
|
|
||||||
|
result_t result = field->read(partType, data, offset, output, fieldName, fieldIndex);
|
||||||
|
|
||||||
|
if (result < RESULT_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
offset = (unsigned char)(offset + field->getLength(partType));
|
||||||
|
previousFullByteOffset = field->hasFullByteOffset(true);
|
||||||
|
if (result != RESULT_EMPTY) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
if (findFieldIndex && fieldName == field->getName()) {
|
||||||
|
if (fieldIndex == 0) {
|
||||||
|
if (!found)
|
||||||
|
return RESULT_ERR_NOTFOUND;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fieldIndex--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
return RESULT_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
result_t DataFieldSet::read(const PartType partType,
|
result_t DataFieldSet::read(const PartType partType,
|
||||||
SymbolString& data, unsigned char offset,
|
SymbolString& data, unsigned char offset,
|
||||||
ostringstream& output, OutputFormat outputFormat,
|
ostringstream& output, OutputFormat outputFormat,
|
||||||
@@ -1390,7 +1484,7 @@ result_t DataFieldTemplates::add(DataField* field, string name, bool replace)
|
|||||||
map<string, DataField*>::iterator it = m_fieldsByName.find(name);
|
map<string, DataField*>::iterator it = m_fieldsByName.find(name);
|
||||||
if (it != m_fieldsByName.end()) {
|
if (it != m_fieldsByName.end()) {
|
||||||
if (!replace)
|
if (!replace)
|
||||||
return RESULT_ERR_DUPLICATE; // duplicate key
|
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
|
||||||
|
|
||||||
delete it->second;
|
delete it->second;
|
||||||
it->second = field;
|
it->second = field;
|
||||||
@@ -1405,6 +1499,7 @@ result_t DataFieldTemplates::add(DataField* field, string name, bool replace)
|
|||||||
|
|
||||||
result_t DataFieldTemplates::addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end, void* arg, vector< vector<string> >* defaults, const string& filename, unsigned int lineNo)
|
result_t DataFieldTemplates::addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end, void* arg, vector< vector<string> >* defaults, const string& filename, unsigned int lineNo)
|
||||||
{
|
{
|
||||||
|
vector<string>::iterator restart = begin;
|
||||||
DataField* field = NULL;
|
DataField* field = NULL;
|
||||||
string name;
|
string name;
|
||||||
if (begin != end) {
|
if (begin != end) {
|
||||||
@@ -1419,6 +1514,8 @@ result_t DataFieldTemplates::addFromFile(vector<string>::iterator& begin, const
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
result = add(field, name, true);
|
result = add(field, name, true);
|
||||||
|
if (result==RESULT_ERR_DUPLICATE_NAME)
|
||||||
|
begin = restart+1; // mark name as invalid
|
||||||
if (result != RESULT_OK)
|
if (result != RESULT_OK)
|
||||||
delete field;
|
delete field;
|
||||||
|
|
||||||
|
|||||||
+62
-11
@@ -122,7 +122,8 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co
|
|||||||
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 to stdout.
|
* Print the error position of the iterator.
|
||||||
|
* @param out the @a ostream to print to.
|
||||||
* @param begin the iterator to the beginning of the items.
|
* @param begin the iterator to the beginning of the items.
|
||||||
* @param end the iterator to the end of the items.
|
* @param end the iterator to the end of the items.
|
||||||
* @param pos the iterator with the erroneous position.
|
* @param pos the iterator with the erroneous position.
|
||||||
@@ -130,7 +131,7 @@ int parseSignedInt(const char* str, int base, const int minValue, const int maxV
|
|||||||
* @param lineNo the current line number in the file being read.
|
* @param lineNo the current line number in the file being read.
|
||||||
* @param result the result code.
|
* @param result the result code.
|
||||||
*/
|
*/
|
||||||
void printErrorPos(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);
|
||||||
|
|
||||||
|
|
||||||
class DataFieldTemplates;
|
class DataFieldTemplates;
|
||||||
@@ -222,6 +223,31 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void dump(ostream& output) = 0;
|
virtual void dump(ostream& output) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether the field is available.
|
||||||
|
* @param fieldName the name of the field to find.
|
||||||
|
* @param numeric true for a numeric field, false for a string field.
|
||||||
|
* @return true if the field is available.
|
||||||
|
*/
|
||||||
|
virtual bool hasField(const char* fieldName, bool numeric) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the numeric value from the @a SymbolString.
|
||||||
|
* @param partType the @a PartType of the data.
|
||||||
|
* @param data the unescaped data @a SymbolString for reading binary data.
|
||||||
|
* @param offset the additional offset to add for reading binary data.
|
||||||
|
* @param output the variable in which to store the numeric value.
|
||||||
|
* @param fieldName the name of the field to read, or NULL for the first field.
|
||||||
|
* @param fieldIndex the optional index of the named field, or -1.
|
||||||
|
* @return @a RESULT_OK on success,
|
||||||
|
* or @a RESULT_EMPTY if the field was skipped (either if the partType does
|
||||||
|
* not match or ignored, or due to @a fieldName or @a fieldIndex),
|
||||||
|
* or an error code.
|
||||||
|
*/
|
||||||
|
virtual result_t read(const PartType partType,
|
||||||
|
SymbolString& data, unsigned char offset,
|
||||||
|
unsigned int& output, const char* fieldName=NULL, signed char fieldIndex=-1) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the value from the @a SymbolString.
|
* Reads the value from the @a SymbolString.
|
||||||
* @param partType the @a PartType of the data.
|
* @param partType the @a PartType of the data.
|
||||||
@@ -233,7 +259,7 @@ public:
|
|||||||
* @param fieldName the optional name of a field to limit the output to.
|
* @param fieldName the optional name of a field to limit the output to.
|
||||||
* @param fieldIndex the optional index of the named field to limit the output to, or -1.
|
* @param fieldIndex the optional index of the named field to limit the output to, or -1.
|
||||||
* @return @a RESULT_OK on success (or if the partType does not match),
|
* @return @a RESULT_OK on success (or if the partType does not match),
|
||||||
* or @a RESULT_EMPTY if the field was skipped (either ignored or due to @a filterName),
|
* or @a RESULT_EMPTY if the field was skipped (either ignored or due to @a fieldName or @a fieldIndex),
|
||||||
* or an error code.
|
* or an error code.
|
||||||
*/
|
*/
|
||||||
virtual result_t read(const PartType partType,
|
virtual result_t read(const PartType partType,
|
||||||
@@ -345,6 +371,11 @@ public:
|
|||||||
// @copydoc
|
// @copydoc
|
||||||
virtual void dump(ostream& output);
|
virtual void dump(ostream& output);
|
||||||
|
|
||||||
|
// @copydoc
|
||||||
|
virtual result_t read(const PartType partType,
|
||||||
|
SymbolString& data, unsigned char offset,
|
||||||
|
unsigned int& output, const char* fieldName=NULL, signed char fieldIndex=-1);
|
||||||
|
|
||||||
// @copydoc
|
// @copydoc
|
||||||
virtual result_t read(const PartType partType,
|
virtual result_t read(const PartType partType,
|
||||||
SymbolString& data, unsigned char offset,
|
SymbolString& data, unsigned char offset,
|
||||||
@@ -358,6 +389,15 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal method for reading the numeric raw value from a @a SymbolString.
|
||||||
|
* @param input the unescaped @a SymbolString to read the binary value from.
|
||||||
|
* @param offset the offset in the @a SymbolString.
|
||||||
|
* @param value the variable in which to store the numeric raw value.
|
||||||
|
* @return @a RESULT_OK on success, or an error code.
|
||||||
|
*/
|
||||||
|
virtual result_t readRawValue(SymbolString& input, const unsigned char offset, unsigned int& value) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal method for reading the field from a @a SymbolString.
|
* Internal method for reading the field from a @a SymbolString.
|
||||||
* @param input the unescaped @a SymbolString to read the binary value from.
|
* @param input the unescaped @a SymbolString to read the binary value from.
|
||||||
@@ -427,11 +467,17 @@ public:
|
|||||||
int divisor, map<unsigned int, string> values,
|
int divisor, map<unsigned int, string> values,
|
||||||
vector<SingleDataField*>& fields);
|
vector<SingleDataField*>& fields);
|
||||||
|
|
||||||
|
// @copydoc
|
||||||
|
virtual bool hasField(const char* fieldName, bool numeric);
|
||||||
|
|
||||||
// @copydoc
|
// @copydoc
|
||||||
virtual void dump(ostream& output);
|
virtual void dump(ostream& output);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
// @copydoc
|
||||||
|
virtual result_t readRawValue(SymbolString& input, const unsigned char offset, unsigned int& value);
|
||||||
|
|
||||||
// @copydoc
|
// @copydoc
|
||||||
virtual result_t readSymbols(SymbolString& input, const unsigned char baseOffset,
|
virtual result_t readSymbols(SymbolString& input, const unsigned char baseOffset,
|
||||||
ostringstream& output, OutputFormat outputFormat);
|
ostringstream& output, OutputFormat outputFormat);
|
||||||
@@ -474,19 +520,16 @@ public:
|
|||||||
// @copydoc
|
// @copydoc
|
||||||
virtual bool hasFullByteOffset(bool after);
|
virtual bool hasFullByteOffset(bool after);
|
||||||
|
|
||||||
|
// @copydoc
|
||||||
|
virtual bool hasField(const char* fieldName, bool numeric);
|
||||||
|
|
||||||
// @copydoc
|
// @copydoc
|
||||||
virtual void dump(ostream& output);
|
virtual void dump(ostream& output);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/**
|
// @copydoc
|
||||||
* Internal method for reading the raw value from a @a SymbolString.
|
virtual result_t readRawValue(SymbolString& input, const unsigned char offset, unsigned int& value);
|
||||||
* @param input the unescaped @a SymbolString to read the binary value from.
|
|
||||||
* @param offset the offset in the @a SymbolString.
|
|
||||||
* @param value the variable in which to store the raw value.
|
|
||||||
* @return @a RESULT_OK on success, or an error code.
|
|
||||||
*/
|
|
||||||
result_t readRawValue(SymbolString& input, const unsigned char offset, unsigned int& value);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal method for writing the raw value to a @a SymbolString.
|
* Internal method for writing the raw value to a @a SymbolString.
|
||||||
@@ -678,9 +721,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
size_t size() const { return m_fields.size(); }
|
size_t size() const { return m_fields.size(); }
|
||||||
|
|
||||||
|
// @copydoc
|
||||||
|
virtual bool hasField(const char* fieldName, bool numeric);
|
||||||
|
|
||||||
// @copydoc
|
// @copydoc
|
||||||
virtual void dump(ostream& output);
|
virtual void dump(ostream& output);
|
||||||
|
|
||||||
|
// @copydoc
|
||||||
|
virtual result_t read(const PartType partType,
|
||||||
|
SymbolString& data, unsigned char offset,
|
||||||
|
unsigned int& output, const char* fieldName=NULL, signed char fieldIndex=-1);
|
||||||
|
|
||||||
// @copydoc
|
// @copydoc
|
||||||
virtual result_t read(const PartType partType,
|
virtual result_t read(const PartType partType,
|
||||||
SymbolString& data, unsigned char offset,
|
SymbolString& data, unsigned char offset,
|
||||||
|
|||||||
Reference in New Issue
Block a user