introduced DataFormat and support for JSON
This commit is contained in:
+68
-32
@@ -430,8 +430,7 @@ void SingleDataField::dump(ostream& output)
|
||||
result_t SingleDataField::read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
ostringstream& output, bool leadingSeparator,
|
||||
bool verbose, const char* fieldName, signed char fieldIndex,
|
||||
char separator)
|
||||
DataFormat dataFormat, const char* fieldName, signed char fieldIndex)
|
||||
{
|
||||
if (partType != m_partType)
|
||||
return RESULT_OK;
|
||||
@@ -454,21 +453,38 @@ result_t SingleDataField::read(const PartType partType,
|
||||
return RESULT_EMPTY;
|
||||
}
|
||||
|
||||
if (leadingSeparator)
|
||||
output << separator;
|
||||
if (leadingSeparator) {
|
||||
if (dataFormat==df_json)
|
||||
output << ",";
|
||||
else
|
||||
output << UI_FIELD_SEPARATOR;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
if (dataFormat==df_verbose)
|
||||
output << m_name << "=";
|
||||
else if (dataFormat==df_json)
|
||||
output << "\n {\"name\": \"" << m_name << "\"";
|
||||
|
||||
result_t result = readSymbols(data, offset, output);
|
||||
if (dataFormat==df_json)
|
||||
output << ", \"value\": ";
|
||||
result_t result = readSymbols(data, offset, output, dataFormat);
|
||||
if (result != RESULT_OK)
|
||||
return result;
|
||||
|
||||
if (verbose && m_unit.length() > 0)
|
||||
output << " " << m_unit;
|
||||
if (verbose && m_comment.length() > 0)
|
||||
output << " [" << m_comment << "]";
|
||||
|
||||
if (m_unit.length() > 0) {
|
||||
if (dataFormat==df_verbose)
|
||||
output << " " << m_unit;
|
||||
else if (dataFormat==df_json)
|
||||
output << ", \"unit\": \"" << m_unit << '"';
|
||||
}
|
||||
if (m_comment.length() > 0) {
|
||||
if (dataFormat==df_verbose)
|
||||
output << " [" << m_comment << "]";
|
||||
else if (dataFormat==df_json)
|
||||
output << ", \"comment\": \"" << m_comment << '"';
|
||||
}
|
||||
if (dataFormat==df_json)
|
||||
output << "}";
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
@@ -525,8 +541,9 @@ void StringDataField::dump(ostream& output)
|
||||
dumpString(output, m_comment);
|
||||
}
|
||||
|
||||
result_t StringDataField::readSymbols(SymbolString& input,
|
||||
unsigned char baseOffset, ostringstream& output)
|
||||
result_t StringDataField::readSymbols(SymbolString& input, const unsigned char baseOffset,
|
||||
ostringstream& output,
|
||||
DataFormat dataFormat)
|
||||
{
|
||||
size_t start = 0, count = m_length;
|
||||
int incr = 1;
|
||||
@@ -541,6 +558,8 @@ result_t StringDataField::readSymbols(SymbolString& input,
|
||||
incr = -1;
|
||||
}
|
||||
|
||||
if (dataFormat==df_json)
|
||||
output << '"';
|
||||
for (size_t offset = start, i = 0; i < count; offset += incr, i++) {
|
||||
if (m_length == 4 && i == 2 && m_dataType.type == bt_dat)
|
||||
continue; // skip weekday in between
|
||||
@@ -614,6 +633,8 @@ result_t StringDataField::readSymbols(SymbolString& input,
|
||||
}
|
||||
last = ch;
|
||||
}
|
||||
if (dataFormat==df_json)
|
||||
output << '"';
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
@@ -940,8 +961,9 @@ void NumberDataField::dump(ostream& output)
|
||||
dumpString(output, m_comment);
|
||||
}
|
||||
|
||||
result_t NumberDataField::readSymbols(SymbolString& input,
|
||||
unsigned char baseOffset, ostringstream& output)
|
||||
result_t NumberDataField::readSymbols(SymbolString& input, const unsigned char baseOffset,
|
||||
ostringstream& output,
|
||||
DataFormat dataFormat)
|
||||
{
|
||||
unsigned int value = 0;
|
||||
int signedValue;
|
||||
@@ -953,7 +975,11 @@ result_t NumberDataField::readSymbols(SymbolString& input,
|
||||
output << setw(0) << dec; // initialize output
|
||||
|
||||
if ((m_dataType.flags & REQ) == 0 && value == m_dataType.replacement) {
|
||||
if (dataFormat==df_json)
|
||||
output << '"';
|
||||
output << NULL_VALUE;
|
||||
if (dataFormat==df_json)
|
||||
output << '"';
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
@@ -979,8 +1005,15 @@ result_t NumberDataField::readSymbols(SymbolString& input,
|
||||
if (m_divisor < 0)
|
||||
output << static_cast<float>((float)signedValue * (float)(-m_divisor));
|
||||
else if (m_divisor <= 1) {
|
||||
if ((m_dataType.flags & (FIX|BCD)) == (FIX|BCD))
|
||||
if ((m_dataType.flags & (FIX|BCD)) == (FIX|BCD)) {
|
||||
if (dataFormat==df_json) {
|
||||
output << '"';
|
||||
output << setw(m_length * 2) << setfill('0');
|
||||
output << '"';
|
||||
return RESULT_OK;
|
||||
}
|
||||
output << setw(m_length * 2) << setfill('0');
|
||||
}
|
||||
output << static_cast<int>(signedValue) << setw(0);
|
||||
}
|
||||
else
|
||||
@@ -1098,8 +1131,9 @@ void ValueListDataField::dump(ostream& output)
|
||||
dumpString(output, m_comment);
|
||||
}
|
||||
|
||||
result_t ValueListDataField::readSymbols(SymbolString& input,
|
||||
unsigned char baseOffset, ostringstream& output)
|
||||
result_t ValueListDataField::readSymbols(SymbolString& input, const unsigned char baseOffset,
|
||||
ostringstream& output,
|
||||
DataFormat dataFormat)
|
||||
{
|
||||
unsigned int value = 0;
|
||||
|
||||
@@ -1107,20 +1141,21 @@ result_t ValueListDataField::readSymbols(SymbolString& input,
|
||||
if (result != RESULT_OK)
|
||||
return result;
|
||||
|
||||
output << setw(0) << dec; // initialize output
|
||||
|
||||
map<unsigned int, string>::iterator it = m_values.find(value);
|
||||
if (it == m_values.end() && value != m_dataType.replacement) {
|
||||
return RESULT_ERR_NOTFOUND; // value assignment not found
|
||||
}
|
||||
output << setw(0) << dec; // initialize output
|
||||
if (dataFormat==df_json)
|
||||
output << '"';
|
||||
if (it != m_values.end()) {
|
||||
output << it->second;
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
if (value == m_dataType.replacement) {
|
||||
} else if (value == m_dataType.replacement) {
|
||||
output << NULL_VALUE;
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
return RESULT_ERR_NOTFOUND; // value assignment not found
|
||||
if (dataFormat==df_json)
|
||||
output << '"';
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t ValueListDataField::writeSymbols(istringstream& input,
|
||||
@@ -1238,8 +1273,7 @@ void DataFieldSet::dump(ostream& output)
|
||||
result_t DataFieldSet::read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
ostringstream& output, bool leadingSeparator,
|
||||
bool verbose, const char* fieldName, signed char fieldIndex,
|
||||
char separator)
|
||||
DataFormat dataFormat, 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++) {
|
||||
@@ -1250,7 +1284,7 @@ result_t DataFieldSet::read(const PartType partType,
|
||||
if (!previousFullByteOffset && !field->hasFullByteOffset(false))
|
||||
offset--;
|
||||
|
||||
result_t result = field->read(partType, data, offset, output, leadingSeparator, verbose, fieldName, fieldIndex, separator);
|
||||
result_t result = field->read(partType, data, offset, output, leadingSeparator, dataFormat, fieldName, fieldIndex);
|
||||
|
||||
if (result < RESULT_OK)
|
||||
return result;
|
||||
@@ -1274,9 +1308,11 @@ result_t DataFieldSet::read(const PartType partType,
|
||||
if (!found) {
|
||||
return RESULT_EMPTY;
|
||||
}
|
||||
if (verbose) {
|
||||
if (m_comment.length() > 0)
|
||||
if (m_comment.length() > 0) {
|
||||
if (dataFormat==df_verbose)
|
||||
output << " [" << m_comment << "]";
|
||||
else if (dataFormat==df_json)
|
||||
output << ",\"comment\": \"" << m_comment << '"';
|
||||
}
|
||||
|
||||
return RESULT_OK;
|
||||
|
||||
+23
-13
@@ -46,6 +46,13 @@ using namespace std;
|
||||
/** the separator character used between fields (in UI only). */
|
||||
#define UI_FIELD_SEPARATOR ';'
|
||||
|
||||
/** the data output format. */
|
||||
enum DataFormat {
|
||||
df_standard, //!< standard format (values only)
|
||||
df_verbose, //!< verbose format (names, values, units, and comments)
|
||||
df_json, //!< JSON format (names, values, units, and comments)
|
||||
};
|
||||
|
||||
/** the message part in which a data field is stored. */
|
||||
enum PartType {
|
||||
pt_any, //!< stored in any data (master or slave)
|
||||
@@ -220,11 +227,9 @@ public:
|
||||
* @param offset the additional offset to add for reading binary data.
|
||||
* @param output the @a ostringstream to append the formatted value to.
|
||||
* @param leadingSeparator whether to prepend a separator before the formatted value.
|
||||
* @param verbose whether to prepend the name, append the unit (if present), and append
|
||||
* the comment in square brackets (if present).
|
||||
* @param dataFormat the @a DataFormat to use.
|
||||
* @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 separator the separator character between multiple fields.
|
||||
* @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 an error code.
|
||||
@@ -232,8 +237,7 @@ public:
|
||||
virtual result_t read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
ostringstream& output, bool leadingSeparator=false,
|
||||
bool verbose=false, const char* fieldName=NULL, signed char fieldIndex=-1,
|
||||
char separator=UI_FIELD_SEPARATOR) = 0;
|
||||
DataFormat dataFormat=df_standard, const char* fieldName=NULL, signed char fieldIndex=-1) = 0;
|
||||
|
||||
/**
|
||||
* Writes the value to the master or slave @a SymbolString.
|
||||
@@ -343,8 +347,7 @@ public:
|
||||
virtual result_t read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
ostringstream& output, bool leadingSeparator=false,
|
||||
bool verbose=false, const char* fieldName=NULL, signed char fieldIndex=-1,
|
||||
char separator=UI_FIELD_SEPARATOR);
|
||||
DataFormat dataFormat=df_standard, const char* fieldName=NULL, signed char fieldIndex=-1);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t write(istringstream& input,
|
||||
@@ -360,7 +363,9 @@ protected:
|
||||
* @param output the ostringstream to append the formatted value to.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t readSymbols(SymbolString& input, const unsigned char offset, ostringstream& output) = 0;
|
||||
virtual result_t readSymbols(SymbolString& input, const unsigned char baseOffset,
|
||||
ostringstream& output,
|
||||
DataFormat dataFormat) = 0;
|
||||
|
||||
/**
|
||||
* Internal method for writing the field to a @a SymbolString.
|
||||
@@ -426,7 +431,9 @@ public:
|
||||
protected:
|
||||
|
||||
// @copydoc
|
||||
virtual result_t readSymbols(SymbolString& input, const unsigned char offset, ostringstream& output);
|
||||
virtual result_t readSymbols(SymbolString& input, const unsigned char baseOffset,
|
||||
ostringstream& output,
|
||||
DataFormat dataFormat);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output);
|
||||
@@ -538,7 +545,9 @@ public:
|
||||
protected:
|
||||
|
||||
// @copydoc
|
||||
virtual result_t readSymbols(SymbolString& input, const unsigned char offset, ostringstream& output);
|
||||
virtual result_t readSymbols(SymbolString& input, const unsigned char baseOffset,
|
||||
ostringstream& output,
|
||||
DataFormat dataFormat);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output);
|
||||
@@ -597,7 +606,9 @@ public:
|
||||
protected:
|
||||
|
||||
// @copydoc
|
||||
virtual result_t readSymbols(SymbolString& input, const unsigned char offset, ostringstream& output);
|
||||
virtual result_t readSymbols(SymbolString& input, const unsigned char baseOffset,
|
||||
ostringstream& output,
|
||||
DataFormat dataFormat);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output);
|
||||
@@ -675,8 +686,7 @@ public:
|
||||
virtual result_t read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
ostringstream& output, bool leadingSeparator=false,
|
||||
bool verbose=false, const char* fieldName=NULL, signed char fieldIndex=-1,
|
||||
char separator=UI_FIELD_SEPARATOR);
|
||||
DataFormat dataFormat=df_standard, const char* fieldName=NULL, signed char fieldIndex=-1);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t write(istringstream& input,
|
||||
|
||||
@@ -351,15 +351,14 @@ result_t Message::prepareSlave(SymbolString& slaveData)
|
||||
|
||||
result_t Message::decode(const PartType partType, SymbolString& data,
|
||||
ostringstream& output, bool leadingSeparator,
|
||||
bool verbose, const char* fieldName, signed char fieldIndex,
|
||||
char separator)
|
||||
DataFormat dataFormat, const char* fieldName, signed char fieldIndex)
|
||||
{
|
||||
unsigned char offset;
|
||||
if (partType == pt_masterData)
|
||||
offset = (unsigned char)(m_id.size() - 2);
|
||||
else
|
||||
offset = 0;
|
||||
result_t result = m_data->read(partType, data, offset, output, leadingSeparator, verbose, fieldName, fieldIndex, separator);
|
||||
result_t result = m_data->read(partType, data, offset, output, leadingSeparator, dataFormat, fieldName, fieldIndex);
|
||||
if (result < RESULT_OK)
|
||||
return result;
|
||||
if (result == RESULT_EMPTY && fieldName != NULL)
|
||||
@@ -382,17 +381,17 @@ result_t Message::decode(const PartType partType, SymbolString& data,
|
||||
|
||||
result_t Message::decode(SymbolString& masterData, SymbolString& slaveData,
|
||||
ostringstream& output, bool leadingSeparator,
|
||||
bool verbose, char separator)
|
||||
DataFormat dataFormat)
|
||||
{
|
||||
unsigned char offset = (unsigned char)(m_id.size() - 2);
|
||||
size_t startPos = output.str().length();
|
||||
result_t result = m_data->read(pt_masterData, masterData, offset, output, leadingSeparator, verbose, NULL, -1, separator);
|
||||
result_t result = m_data->read(pt_masterData, masterData, offset, output, leadingSeparator, dataFormat, NULL, -1);
|
||||
if (result < RESULT_OK)
|
||||
return result;
|
||||
bool empty = result == RESULT_EMPTY;
|
||||
offset = 0;
|
||||
leadingSeparator = output.str().length() > startPos;
|
||||
result = m_data->read(pt_slaveData, slaveData, offset, output, leadingSeparator, verbose, NULL, -1, separator);
|
||||
result = m_data->read(pt_slaveData, slaveData, offset, output, leadingSeparator, dataFormat, NULL, -1);
|
||||
if (result < RESULT_OK)
|
||||
return result;
|
||||
if (result == RESULT_EMPTY && !empty)
|
||||
@@ -409,20 +408,18 @@ result_t Message::decode(SymbolString& masterData, SymbolString& slaveData,
|
||||
return result;
|
||||
}
|
||||
|
||||
result_t Message::decodeLastData(ostringstream& output,
|
||||
bool verbose, const char* fieldName, signed char fieldIndex,
|
||||
char separator)
|
||||
result_t Message::decodeLastData(ostringstream& output, bool leadingSeparator,
|
||||
DataFormat dataFormat, const char* fieldName, signed char fieldIndex)
|
||||
{
|
||||
bool leadingSeparator = false;
|
||||
unsigned char offset = (unsigned char)(m_id.size() - 2);
|
||||
size_t startPos = output.str().length();
|
||||
result_t result = m_data->read(pt_masterData, m_lastMasterData, offset, output, leadingSeparator, verbose, fieldName, fieldIndex, separator);
|
||||
result_t result = m_data->read(pt_masterData, m_lastMasterData, offset, output, leadingSeparator, dataFormat, fieldName, fieldIndex);
|
||||
if (result < RESULT_OK)
|
||||
return result;
|
||||
bool empty = result == RESULT_EMPTY;
|
||||
offset = 0;
|
||||
leadingSeparator = output.str().length() > startPos;
|
||||
result = m_data->read(pt_slaveData, m_lastSlaveData, offset, output, leadingSeparator, verbose, fieldName, fieldIndex, separator);
|
||||
result = m_data->read(pt_slaveData, m_lastSlaveData, offset, output, leadingSeparator, dataFormat, fieldName, fieldIndex);
|
||||
if (result < RESULT_OK)
|
||||
return result;
|
||||
if (result == RESULT_EMPTY && !empty)
|
||||
|
||||
+8
-15
@@ -182,17 +182,14 @@ public:
|
||||
* @param data the unescaped data @a SymbolString for reading binary data.
|
||||
* @param output the @a ostringstream to append the formatted value to.
|
||||
* @param leadingSeparator whether to prepend a separator before the formatted value.
|
||||
* @param verbose whether to prepend the name, append the unit (if present), and append
|
||||
* the comment in square brackets (if present).
|
||||
* @param dataFormat the @a DataFormat to use.
|
||||
* @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 separator the separator character between multiple fields.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t decode(const PartType partType, SymbolString& data,
|
||||
ostringstream& output, bool leadingSeparator=false,
|
||||
bool verbose=false, const char* fieldName=NULL, signed char fieldIndex=-1,
|
||||
char separator=UI_FIELD_SEPARATOR);
|
||||
DataFormat dataFormat=df_standard, const char* fieldName=NULL, signed char fieldIndex=-1);
|
||||
|
||||
/**
|
||||
* Decode all parts of a received message.
|
||||
@@ -200,28 +197,24 @@ public:
|
||||
* @param slaveData the unescaped slave data @a SymbolString to decode.
|
||||
* @param output the @a ostringstream to append the formatted value to.
|
||||
* @param leadingSeparator whether to prepend a separator before the formatted value.
|
||||
* @param verbose whether to prepend the name, append the unit (if present), and append
|
||||
* the comment in square brackets (if present).
|
||||
* @param separator the separator character between multiple fields.
|
||||
* @param dataFormat the @a DataFormat to use.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t decode(SymbolString& masterData, SymbolString& slaveData,
|
||||
ostringstream& output, bool leadingSeparator=false,
|
||||
bool verbose=false, char separator=UI_FIELD_SEPARATOR);
|
||||
DataFormat dataFormat=df_standard);
|
||||
|
||||
/**
|
||||
* Decode the value from the last stored data.
|
||||
* @param output the @a ostringstream to append the formatted value to.
|
||||
* @param verbose whether to prepend the name, append the unit (if present), and append
|
||||
* the comment in square brackets (if present).
|
||||
* @param leadingSeparator whether to prepend a separator before the formatted value.
|
||||
* @param dataFormat the @a DataFormat to use.
|
||||
* @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 separator the separator character between multiple fields.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t decodeLastData(ostringstream& output,
|
||||
bool verbose=false, const char* fieldName=NULL, signed char fieldIndex=-1,
|
||||
char separator=UI_FIELD_SEPARATOR);
|
||||
result_t decodeLastData(ostringstream& output, bool leadingSeparator=false,
|
||||
DataFormat dataFormat=df_standard, const char* fieldName=NULL, signed char fieldIndex=-1);
|
||||
|
||||
/**
|
||||
* Get the time when @a m_lastValue was last stored.
|
||||
|
||||
Reference in New Issue
Block a user