new enum type for OutputFormat, add level/pollprio/condition to HTTP GET and extend message key by circuit/direction/condition for OF_ALL_ATTRS, start message dump in JSON format
This commit is contained in:
@@ -178,7 +178,7 @@ int main() {
|
||||
continue;
|
||||
}
|
||||
cout << "\"" << check[0] << "\"=\"";
|
||||
fields->dump(false, false, &cout);
|
||||
fields->dump(false, OF_NONE, &cout);
|
||||
cout << "\": create OK" << endl;
|
||||
|
||||
ostringstream output;
|
||||
@@ -194,9 +194,9 @@ int main() {
|
||||
cout << " parse \"" << sstr.getStr().substr(0, 2) << "\" error: " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
}
|
||||
result = fields->read(mstr, 0, false, nullptr, -1, 0, -1, &output);
|
||||
result = fields->read(mstr, 0, false, nullptr, -1, OF_NONE, -1, &output);
|
||||
if (result >= RESULT_OK) {
|
||||
result = fields->read(sstr, 0, !output.str().empty(), nullptr, -1, 0, -1, &output);
|
||||
result = fields->read(sstr, 0, !output.str().empty(), nullptr, -1, OF_NONE, -1, &output);
|
||||
}
|
||||
if (failedRead) {
|
||||
if (result >= RESULT_OK) {
|
||||
|
||||
+33
-33
@@ -67,6 +67,7 @@ string AttributedItem::pluck(const string& key, map<string, string>* row) {
|
||||
}
|
||||
|
||||
void AttributedItem::dumpString(bool prependFieldSeparator, const string& str, ostream* output) {
|
||||
// not to be used for JSON format
|
||||
if (prependFieldSeparator) {
|
||||
*output << FIELD_SEPARATOR;
|
||||
}
|
||||
@@ -102,7 +103,7 @@ void AttributedItem::appendJson(bool prependFieldSeparator, const string& name,
|
||||
}
|
||||
}
|
||||
if (prependFieldSeparator) {
|
||||
*output << FIELD_SEPARATOR;
|
||||
*output << ",";
|
||||
}
|
||||
*output << " \"" << name << "\": ";
|
||||
if (plain) {
|
||||
@@ -129,9 +130,9 @@ void AttributedItem::mergeAttributes(map<string, string>* attributes) const {
|
||||
}
|
||||
}
|
||||
|
||||
void AttributedItem::dumpAttribute(bool prependFieldSeparator, bool asJson, const string& name, ostream* output)
|
||||
void AttributedItem::dumpAttribute(bool prependFieldSeparator, OutputFormat outputFormat, const string& name, ostream* output)
|
||||
const {
|
||||
if (asJson) {
|
||||
if (outputFormat & OF_JSON) {
|
||||
appendJson(prependFieldSeparator, name, getAttribute(name), false, output);
|
||||
} else {
|
||||
dumpString(prependFieldSeparator, getAttribute(name), output);
|
||||
@@ -171,7 +172,7 @@ bool AttributedItem::appendAttributes(OutputFormat outputFormat, ostream* output
|
||||
result_t result = RESULT_EMPTY;
|
||||
size_t addr = parseInt(entry.second.c_str(), 16, 0, 255, &result);
|
||||
if (result == RESULT_OK) {
|
||||
*output << FIELD_SEPARATOR << " \"" << key << "\": " << addr;
|
||||
*output << ", \"" << key << "\": " << addr;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -469,44 +470,43 @@ result_t SingleDataField::create(const string& name, const map<string, string>&
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void SingleDataField::dumpPrefix(bool prependFieldSeparator, bool asJson, ostream* output) const {
|
||||
void SingleDataField::dumpPrefix(bool prependFieldSeparator, OutputFormat outputFormat, ostream* output) const {
|
||||
*output << setw(0) << dec; // initialize formatting
|
||||
if (asJson) {
|
||||
if (outputFormat & OF_JSON) {
|
||||
if (prependFieldSeparator) {
|
||||
*output << FIELD_SEPARATOR;
|
||||
*output << ",";
|
||||
}
|
||||
*output << "\n {";
|
||||
appendJson(false, "name", m_name, true, output);
|
||||
} else {
|
||||
dumpString(prependFieldSeparator, m_name, output);
|
||||
}
|
||||
*output << FIELD_SEPARATOR;
|
||||
if (asJson) {
|
||||
*output << " \"slave\": " << (m_partType == pt_slaveData ? "true" : "false") << ", ";
|
||||
if (outputFormat & OF_JSON) {
|
||||
*output << ", \"slave\": " << (m_partType == pt_slaveData ? "true" : "false") << ", ";
|
||||
} else {
|
||||
*output << FIELD_SEPARATOR;
|
||||
if (m_partType == pt_masterData) {
|
||||
*output << "m";
|
||||
} else if (m_partType == pt_slaveData) {
|
||||
*output << "s";
|
||||
}
|
||||
}
|
||||
if (!asJson) {
|
||||
*output << FIELD_SEPARATOR;
|
||||
}
|
||||
m_dataType->dump(asJson, m_length, true, output);
|
||||
m_dataType->dump(outputFormat, m_length, true, output);
|
||||
}
|
||||
|
||||
void SingleDataField::dumpSuffix(bool asJson, ostream* output) const {
|
||||
dumpAttribute(true, asJson, "unit", output);
|
||||
dumpAttribute(true, asJson, "comment", output);
|
||||
if (asJson) {
|
||||
void SingleDataField::dumpSuffix(OutputFormat outputFormat, ostream* output) const {
|
||||
dumpAttribute(true, outputFormat, "unit", output);
|
||||
dumpAttribute(true, outputFormat, "comment", output);
|
||||
if (outputFormat & OF_JSON) {
|
||||
appendAttributes(outputFormat & ~(OF_UNITS|OF_COMMENTS), output);
|
||||
*output << "}";
|
||||
}
|
||||
}
|
||||
|
||||
void SingleDataField::dump(bool prependFieldSeparator, bool asJson, ostream* output) const {
|
||||
dumpPrefix(prependFieldSeparator, asJson, output);
|
||||
dumpSuffix(asJson, output);
|
||||
void SingleDataField::dump(bool prependFieldSeparator, OutputFormat outputFormat, ostream* output) const {
|
||||
dumpPrefix(prependFieldSeparator, outputFormat, output);
|
||||
dumpSuffix(outputFormat, output);
|
||||
}
|
||||
|
||||
result_t SingleDataField::read(const SymbolString& data, size_t offset,
|
||||
@@ -557,7 +557,7 @@ result_t SingleDataField::read(const SymbolString& data, size_t offset,
|
||||
*output << "\"" << static_cast<signed int>(outputIndex < 0 ? 0 : outputIndex) << "\":";
|
||||
}
|
||||
if (!shortFormat) {
|
||||
*output << " {\"name\": \"" << m_name << "\"" << ", \"value\": ";
|
||||
*output << " {\"name\": \"" << m_name << "\", \"value\": ";
|
||||
}
|
||||
} else {
|
||||
if (fieldIndex < 0) {
|
||||
@@ -722,11 +722,11 @@ result_t ValueListDataField::derive(const string& name, PartType partType, int d
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void ValueListDataField::dump(bool prependFieldSeparator, bool asJson, ostream* output) const {
|
||||
dumpPrefix(prependFieldSeparator, asJson, output);
|
||||
void ValueListDataField::dump(bool prependFieldSeparator, OutputFormat outputFormat, ostream* output) const {
|
||||
dumpPrefix(prependFieldSeparator, outputFormat, output);
|
||||
// no divisor appended since it is not allowed for ValueListDataField
|
||||
bool first = true;
|
||||
if (asJson) {
|
||||
if (outputFormat & OF_JSON) {
|
||||
*output << ", \"values\": {";
|
||||
for (const auto it : m_values) {
|
||||
appendJson(!first, formatInt(it.first), it.second, true, output); // TODO optimize?
|
||||
@@ -743,7 +743,7 @@ void ValueListDataField::dump(bool prependFieldSeparator, bool asJson, ostream*
|
||||
*output << it.first << "=" << it.second;
|
||||
}
|
||||
}
|
||||
dumpSuffix(asJson, output);
|
||||
dumpSuffix(outputFormat, output);
|
||||
}
|
||||
|
||||
result_t ValueListDataField::readSymbols(const SymbolString& input, size_t offset,
|
||||
@@ -838,22 +838,22 @@ result_t ConstantDataField::derive(const string& name, PartType partType, int di
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void ConstantDataField::dump(bool prependFieldSeparator, bool asJson, ostream* output) const {
|
||||
dumpPrefix(prependFieldSeparator, asJson, output);
|
||||
void ConstantDataField::dump(bool prependFieldSeparator, OutputFormat outputFormat, ostream* output) const {
|
||||
dumpPrefix(prependFieldSeparator, outputFormat, output);
|
||||
// no divisor appended since it is not allowed for ConstantDataField
|
||||
if (asJson) {
|
||||
if (outputFormat & OF_JSON) {
|
||||
appendJson(false, "value", m_value, true, output);
|
||||
*output << ", \"verify\":" << (m_verify ? "true" : "false");
|
||||
*output << ", \"verify\": " << (m_verify ? "true" : "false");
|
||||
} else {
|
||||
*output << (m_verify?"==":"=") << m_value;
|
||||
}
|
||||
dumpSuffix(asJson, output);
|
||||
dumpSuffix(outputFormat, output);
|
||||
}
|
||||
|
||||
result_t ConstantDataField::readSymbols(const SymbolString& input, size_t offset,
|
||||
OutputFormat outputFormat, ostream* output) const {
|
||||
ostringstream coutput;
|
||||
result_t result = SingleDataField::readSymbols(input, offset, 0, &coutput);
|
||||
result_t result = SingleDataField::readSymbols(input, offset, outputFormat, &coutput);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -1024,9 +1024,9 @@ bool DataFieldSet::hasField(const char* fieldName, bool numeric) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void DataFieldSet::dump(bool prependFieldSeparator, bool asJson, ostream* output) const {
|
||||
void DataFieldSet::dump(bool prependFieldSeparator, OutputFormat outputFormat, ostream* output) const {
|
||||
for (const auto field : m_fields) {
|
||||
field->dump(prependFieldSeparator, asJson, output);
|
||||
field->dump(prependFieldSeparator, outputFormat, output);
|
||||
prependFieldSeparator = true;
|
||||
}
|
||||
}
|
||||
|
||||
+12
-12
@@ -122,11 +122,11 @@ class AttributedItem {
|
||||
/**
|
||||
* Dump the attribute optionally embedded in @a TEXT_SEPARATOR to the output.
|
||||
* @param prependFieldSeparator whether to start with a @a FIELD_SEPARATOR.
|
||||
* @param asJson whether to output in JSON format.
|
||||
* @param outputFormat the @a OutputFormat options.
|
||||
* @param name the name of the attribute to dump.
|
||||
* @param output the @a ostream to dump to.
|
||||
*/
|
||||
void dumpAttribute(bool prependFieldSeparator, bool asJson, const string& name, ostream* output) const;
|
||||
void dumpAttribute(bool prependFieldSeparator, OutputFormat outputFormat, const string& name, ostream* output) const;
|
||||
|
||||
/**
|
||||
* Append the attribute value to the output.
|
||||
@@ -273,10 +273,10 @@ class DataField : public AttributedItem {
|
||||
/**
|
||||
* Dump the field settings to the output.
|
||||
* @param prependFieldSeparator whether to start with a @a FIELD_SEPARATOR.
|
||||
* @param asJson whether to output in JSON format.
|
||||
* @param outputFormat the @a OutputFormat options.
|
||||
* @param output the @a ostream to dump to.
|
||||
*/
|
||||
virtual void dump(bool prependFieldSeparator, bool asJson, ostream* output) const = 0;
|
||||
virtual void dump(bool prependFieldSeparator, OutputFormat outputFormat, ostream* output) const = 0;
|
||||
|
||||
/**
|
||||
* Return whether the field is available.
|
||||
@@ -420,20 +420,20 @@ class SingleDataField : public DataField {
|
||||
/**
|
||||
* Dump the common prefix field settings to the output (name and part type).
|
||||
* @param prependFieldSeparator whether to start with a @a FIELD_SEPARATOR.
|
||||
* @param asJson whether to output in JSON format.
|
||||
* @param outputFormat the @a OutputFormat options.
|
||||
* @param output the @a ostream to dump to.
|
||||
*/
|
||||
void dumpPrefix(bool prependFieldSeparator, bool asJson, ostream* output) const;
|
||||
void dumpPrefix(bool prependFieldSeparator, OutputFormat outputFormat, ostream* output) const;
|
||||
|
||||
/**
|
||||
* Dump the common suffix field settings to the output (optional unit and comment).
|
||||
* @param asJson whether to output in JSON format.
|
||||
* @param outputFormat the @a OutputFormat options.
|
||||
* @param output the @a ostream to dump to.
|
||||
*/
|
||||
void dumpSuffix(bool asJson, ostream* output) const;
|
||||
void dumpSuffix(OutputFormat outputFormat, ostream* output) const;
|
||||
|
||||
// @copydoc
|
||||
void dump(bool prependFieldSeparator, bool asJson, ostream* output) const override;
|
||||
void dump(bool prependFieldSeparator, OutputFormat outputFormat, ostream* output) const override;
|
||||
|
||||
// @copydoc
|
||||
bool hasField(const char* fieldName, bool numeric) const override;
|
||||
@@ -519,7 +519,7 @@ class ValueListDataField : public SingleDataField {
|
||||
vector<const SingleDataField*>* fields) const override;
|
||||
|
||||
// @copydoc
|
||||
void dump(bool prependFieldSeparator, bool asJson, ostream* output) const override;
|
||||
void dump(bool prependFieldSeparator, OutputFormat outputFormat, ostream* output) const override;
|
||||
|
||||
|
||||
protected:
|
||||
@@ -572,7 +572,7 @@ class ConstantDataField : public SingleDataField {
|
||||
vector<const SingleDataField*>* fields) const override;
|
||||
|
||||
// @copydoc
|
||||
void dump(bool prependFieldSeparator, bool asJson, ostream* output) const override;
|
||||
void dump(bool prependFieldSeparator, OutputFormat outputFormat, ostream* output) const override;
|
||||
|
||||
|
||||
protected:
|
||||
@@ -685,7 +685,7 @@ class DataFieldSet : public DataField {
|
||||
bool hasField(const char* fieldName, bool numeric) const override;
|
||||
|
||||
// @copydoc
|
||||
void dump(bool prependFieldSeparator, bool asJson, ostream* output) const override;
|
||||
void dump(bool prependFieldSeparator, OutputFormat outputFormat, ostream* output) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t read(const SymbolString& data, size_t offset,
|
||||
|
||||
+12
-12
@@ -42,10 +42,10 @@ using std::setw;
|
||||
using std::endl;
|
||||
|
||||
|
||||
bool DataType::dump(bool asJson, size_t length, bool appendDivisor, ostream* output) const {
|
||||
if (asJson) {
|
||||
*output << "\"type\": \"" << m_id << "\"" << FIELD_SEPARATOR << " \"isbits\": "
|
||||
<< (getBitCount() < 8 ? "true" : "false") << FIELD_SEPARATOR << " \"length\": ";
|
||||
bool DataType::dump(OutputFormat outputFormat, size_t length, bool appendDivisor, ostream* output) const {
|
||||
if (outputFormat & OF_JSON) {
|
||||
*output << "\"type\": \"" << m_id << "\", \"isbits\": "
|
||||
<< (getBitCount() < 8 ? "true" : "false") << ", \"length\": ";
|
||||
if (isAdjustableLength() && length == REMAIN_LEN) {
|
||||
*output << "-1";
|
||||
} else {
|
||||
@@ -297,11 +297,11 @@ result_t DateTimeDataType::readSymbols(size_t offset, size_t length, const Symbo
|
||||
last = symbol;
|
||||
continue;
|
||||
}
|
||||
unsigned int minutes = symbol*256 + last;
|
||||
minutes = symbol*256 + last;
|
||||
if (minutes > 24*60) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid value
|
||||
}
|
||||
unsigned int minutesHour = minutes / 60;
|
||||
unsigned int minutesHour = (unsigned int)(minutes / 60);
|
||||
if (minutesHour > 24) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid hour
|
||||
}
|
||||
@@ -353,7 +353,7 @@ result_t DateTimeDataType::readSymbols(size_t offset, size_t length, const Symbo
|
||||
}
|
||||
*output << dec << setfill('0') << setw(2) << static_cast<unsigned>(d) << "."
|
||||
<< setw(2) << static_cast<unsigned>(m) << "." << static_cast<unsigned>(y + 1900);
|
||||
m = minutes%(24*60);
|
||||
m = (int)(minutes%(24*60));
|
||||
d = m/60;
|
||||
*output << " " << setw(2) << dec << setfill('0') << static_cast<unsigned>(d);
|
||||
m -= d*60;
|
||||
@@ -568,25 +568,25 @@ size_t NumberDataType::calcPrecision(int divisor) {
|
||||
return precision;
|
||||
}
|
||||
|
||||
bool NumberDataType::dump(bool asJson, size_t length, bool appendDivisor, ostream* output) const {
|
||||
bool NumberDataType::dump(OutputFormat outputFormat, size_t length, bool appendDivisor, ostream* output) const {
|
||||
if (m_bitCount < 8) {
|
||||
DataType::dump(asJson, m_bitCount, appendDivisor, output);
|
||||
DataType::dump(outputFormat, m_bitCount, appendDivisor, output);
|
||||
} else {
|
||||
DataType::dump(asJson, length, appendDivisor, output);
|
||||
DataType::dump(outputFormat, length, appendDivisor, output);
|
||||
}
|
||||
if (!appendDivisor) {
|
||||
return false;
|
||||
}
|
||||
if (m_baseType) {
|
||||
if (m_baseType->m_divisor != m_divisor) {
|
||||
if (asJson) {
|
||||
if (outputFormat & OF_JSON) {
|
||||
*output << ", \"divisor\": ";
|
||||
}
|
||||
*output << (m_divisor / m_baseType->m_divisor);
|
||||
return true;
|
||||
}
|
||||
} else if (m_divisor != 1) {
|
||||
if (asJson) {
|
||||
if (outputFormat & OF_JSON) {
|
||||
*output << ", \"divisor\": ";
|
||||
}
|
||||
*output << m_divisor;
|
||||
|
||||
+48
-23
@@ -78,36 +78,61 @@ using std::ostringstream;
|
||||
/** the maximum value for value lists. */
|
||||
#define MAX_VALUE (0xFFFFFFFFu)
|
||||
|
||||
typedef unsigned int OutputFormatBaseType;
|
||||
|
||||
/** the type for data output format options. */
|
||||
typedef int OutputFormat;
|
||||
enum OutputFormat : OutputFormatBaseType {
|
||||
/** no bit set at all. */
|
||||
OF_NONE = 0,
|
||||
|
||||
/** bit flag for @a OutputFormat: include names. */
|
||||
#define OF_NAMES 0x01
|
||||
/** bit flag for @a OutputFormat: include names. */
|
||||
OF_NAMES = 1 << 0,
|
||||
|
||||
/** bit flag for @a OutputFormat: include units. */
|
||||
#define OF_UNITS 0x02
|
||||
/** bit flag for @a OutputFormat: include units. */
|
||||
OF_UNITS = 1 << 1,
|
||||
|
||||
/** bit flag for @a OutputFormat: include comments. */
|
||||
#define OF_COMMENTS 0x04
|
||||
/** bit flag for @a OutputFormat: include comments. */
|
||||
OF_COMMENTS = 1 << 2,
|
||||
|
||||
/** bit flag for @a OutputFormat: numeric format (keep numeric value of value=name pairs). */
|
||||
#define OF_NUMERIC 0x08
|
||||
/** bit flag for @a OutputFormat: numeric format (keep numeric value of value=name pairs). */
|
||||
OF_NUMERIC = 1 << 3,
|
||||
|
||||
/** bit flag for @a OutputFormat: value=name format for such pairs. */
|
||||
#define OF_VALUENAME 0x10
|
||||
/** bit flag for @a OutputFormat: value=name format for such pairs. */
|
||||
OF_VALUENAME = 1 << 4,
|
||||
|
||||
/** bit flag for @a OutputFormat: JSON format. */
|
||||
#define OF_JSON 0x20
|
||||
/** bit flag for @a OutputFormat: JSON format. */
|
||||
OF_JSON = 1 << 5,
|
||||
|
||||
/** bit flag for @a OutputFormat: short format (only name and value, no indentation). */
|
||||
#define OF_SHORT 0x40
|
||||
/** bit flag for @a OutputFormat: short format (only name and value for fields). */
|
||||
OF_SHORT = 1 << 6,
|
||||
|
||||
/** bit flag for @a OutputFormat: include all attributes. */
|
||||
#define OF_ALL_ATTRS 0x80
|
||||
/** bit flag for @a OutputFormat: include all attributes. */
|
||||
OF_ALL_ATTRS = 1 << 7,
|
||||
|
||||
/** bit flag for @a OutputFormat: include message/field definition. */
|
||||
#define OF_DEFINTION 0x100
|
||||
/** bit flag for @a OutputFormat: include message/field definition. */
|
||||
OF_DEFINITION = 1 << 8,
|
||||
};
|
||||
|
||||
constexpr inline enum OutputFormat operator| (enum OutputFormat self, enum OutputFormat other) {
|
||||
return (enum OutputFormat)((OutputFormatBaseType)self | (OutputFormatBaseType)other);
|
||||
}
|
||||
|
||||
inline enum OutputFormat& operator|= (enum OutputFormat& self, enum OutputFormat other) {
|
||||
self = self | other;
|
||||
return self;
|
||||
}
|
||||
|
||||
constexpr inline enum OutputFormat operator& (enum OutputFormat self, enum OutputFormat other) {
|
||||
return (enum OutputFormat)((OutputFormatBaseType)self & (OutputFormatBaseType)other);
|
||||
}
|
||||
|
||||
inline enum OutputFormat& operator&= (enum OutputFormat& self, enum OutputFormat other) {
|
||||
self = self & other;
|
||||
return self;
|
||||
}
|
||||
|
||||
constexpr inline enum OutputFormat operator~ (enum OutputFormat self) {
|
||||
return (enum OutputFormat)(~(OutputFormatBaseType)self);
|
||||
}
|
||||
|
||||
/** the message part in which a data field is stored. */
|
||||
enum PartType {
|
||||
@@ -219,13 +244,13 @@ class DataType {
|
||||
/**
|
||||
* Dump the type identifier with the specified length and optionally the
|
||||
* divisor to the output.
|
||||
* @param asJson whether to output in JSON format.
|
||||
* @param outputFormat the @a OutputFormat options.
|
||||
* @param length the number of symbols to read/write.
|
||||
* @param appendDivisor whether to append the divisor (if available).
|
||||
* @param output the @a ostream to dump to.
|
||||
* @return true when a non-default divisor was written to the output.
|
||||
*/
|
||||
virtual bool dump(bool asJson, size_t length, bool appendDivisor, ostream* output) const;
|
||||
virtual bool dump(OutputFormat outputFormat, size_t length, bool appendDivisor, ostream* output) const;
|
||||
|
||||
/**
|
||||
* Internal method for reading the numeric raw value from a @a SymbolString.
|
||||
@@ -436,7 +461,7 @@ class NumberDataType : public DataType {
|
||||
static size_t calcPrecision(int divisor);
|
||||
|
||||
// @copydoc
|
||||
bool dump(bool asJson, size_t length, bool appendDivisor, ostream* output) const override;
|
||||
bool dump(OutputFormat outputFormat, size_t length, bool appendDivisor, ostream* output) const override;
|
||||
|
||||
/**
|
||||
* Derive a new @a NumberDataType from this.
|
||||
|
||||
+71
-27
@@ -845,7 +845,8 @@ void Message::dumpHeader(const vector<string>* fieldNames, ostream* output) {
|
||||
}
|
||||
}
|
||||
|
||||
void Message::dump(const vector<string>* fieldNames, bool withConditions, ostream* output) const {
|
||||
void Message::dump(const vector<string>* fieldNames, bool withConditions, OutputFormat outputFormat, ostream* output) const {
|
||||
// not to be used together with OF_JSON
|
||||
bool first = true;
|
||||
if (fieldNames == nullptr) {
|
||||
for (const auto& fieldName : knownFieldNamesFull) {
|
||||
@@ -857,7 +858,7 @@ void Message::dump(const vector<string>* fieldNames, bool withConditions, ostrea
|
||||
} else {
|
||||
*output << FIELD_SEPARATOR;
|
||||
}
|
||||
dumpField(fieldName, withConditions, output);
|
||||
dumpField(fieldName, withConditions, outputFormat, output);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -867,11 +868,11 @@ void Message::dump(const vector<string>* fieldNames, bool withConditions, ostrea
|
||||
} else {
|
||||
*output << FIELD_SEPARATOR;
|
||||
}
|
||||
dumpField(fieldName, withConditions, output);
|
||||
dumpField(fieldName, withConditions, outputFormat, output);
|
||||
}
|
||||
}
|
||||
|
||||
void Message::dumpField(const string& fieldName, bool withConditions, ostream* output) const {
|
||||
void Message::dumpField(const string& fieldName, bool withConditions, OutputFormat outputFormat, ostream* output) const {
|
||||
if (fieldName == "type") {
|
||||
if (withConditions && m_condition != nullptr) {
|
||||
m_condition->dump(false, output);
|
||||
@@ -928,10 +929,10 @@ void Message::dumpField(const string& fieldName, bool withConditions, ostream* o
|
||||
return;
|
||||
}
|
||||
if (fieldName == "fields") {
|
||||
m_data->dump(false, false, output);
|
||||
m_data->dump(false, outputFormat, output);
|
||||
return;
|
||||
}
|
||||
dumpAttribute(false, false, fieldName, output);
|
||||
dumpAttribute(false, outputFormat, fieldName, output);
|
||||
}
|
||||
|
||||
void addData(const SymbolString& data, ostringstream* output) {
|
||||
@@ -948,26 +949,44 @@ void addData(const SymbolString& data, ostringstream* output) {
|
||||
*output << "]";
|
||||
}
|
||||
|
||||
void Message::decodeJson(bool leadingSeparator, bool appendDirection, bool addRaw, OutputFormat outputFormat,
|
||||
ostringstream* output) const {
|
||||
void Message::decodeJson(bool leadingSeparator, bool appendDirectionCondition, bool withData, bool addRaw,
|
||||
OutputFormat outputFormat, ostringstream* output) const {
|
||||
outputFormat |= OF_JSON;
|
||||
if (leadingSeparator) {
|
||||
*output << ",";
|
||||
*output << ",\n";
|
||||
}
|
||||
*output << "\n \"" << getName();
|
||||
if (appendDirection) {
|
||||
*output << " \"";
|
||||
*output << getName();
|
||||
if (appendDirectionCondition) {
|
||||
if (isPassive()) {
|
||||
*output << "-u";
|
||||
} else if (isWrite()) {
|
||||
*output << "-w";
|
||||
}
|
||||
if (isConditional()) {
|
||||
m_condition->dump(false, output);
|
||||
}
|
||||
}
|
||||
bool withDefinition = (outputFormat & OF_DEFINTION) != 0;
|
||||
bool withDefinition = outputFormat & OF_DEFINITION;
|
||||
*output << "\": {"
|
||||
<< "\n \"name\": \"" << getName() << "\""
|
||||
<< ",\n \"passive\": " << (isPassive() ? "true" : "false")
|
||||
<< ",\n \"write\": " << (isWrite() ? "true" : "false")
|
||||
<< ",\n \"lastup\": " << setw(0) << dec << m_lastUpdateTime;
|
||||
bool hasData = getLastUpdateTime() != 0;
|
||||
<< ",\n \"write\": " << (isWrite() ? "true" : "false");
|
||||
if (outputFormat & OF_ALL_ATTRS) {
|
||||
*output << ",\n \"level\": \"" << getLevel() << "\"";
|
||||
if (getPollPriority()>0) {
|
||||
*output << ",\n \"pollprio\": " << setw(0) << dec << getPollPriority();
|
||||
}
|
||||
if (isConditional()) {
|
||||
*output << ",\n \"condition\": \"";
|
||||
m_condition->dump(false, output);
|
||||
*output << "\"";
|
||||
}
|
||||
}
|
||||
if (withData) {
|
||||
*output << ",\n \"lastup\": " << setw(0) << dec << getLastUpdateTime();
|
||||
}
|
||||
bool hasData = withData && (getLastUpdateTime() != 0);
|
||||
if (hasData || withDefinition) {
|
||||
if (withDefinition && m_srcAddress != SYN) {
|
||||
*output << ",\n \"qq\": " << dec << static_cast<unsigned>(m_srcAddress);
|
||||
@@ -983,7 +1002,7 @@ void Message::decodeJson(bool leadingSeparator, bool appendDirection, bool addRa
|
||||
}
|
||||
*output << "]";
|
||||
}
|
||||
appendAttributes(OF_JSON | outputFormat, output);
|
||||
appendAttributes(outputFormat, output);
|
||||
if (hasData) {
|
||||
if (addRaw) {
|
||||
addData(m_lastMasterData, output);
|
||||
@@ -1004,7 +1023,7 @@ void Message::decodeJson(bool leadingSeparator, bool appendDirection, bool addRa
|
||||
}
|
||||
if (withDefinition) {
|
||||
*output << ",\n \"fielddefs\": [";
|
||||
m_data->dump(false, true, output);
|
||||
m_data->dump(false, outputFormat, output);
|
||||
*output << "\n ]";
|
||||
}
|
||||
}
|
||||
@@ -1256,9 +1275,9 @@ result_t ChainedMessage::combineLastParts() {
|
||||
return result;
|
||||
}
|
||||
|
||||
void ChainedMessage::dumpField(const string& fieldName, bool withConditions, ostream* output) const {
|
||||
void ChainedMessage::dumpField(const string& fieldName, bool withConditions, OutputFormat outputFormat, ostream* output) const {
|
||||
if (fieldName != "id") {
|
||||
Message::dumpField(fieldName, withConditions, output);
|
||||
Message::dumpField(fieldName, withConditions, outputFormat, output);
|
||||
return;
|
||||
}
|
||||
bool first = true;
|
||||
@@ -1608,7 +1627,7 @@ bool SimpleNumericCondition::checkValue(const Message* message, const string& fi
|
||||
|
||||
bool SimpleStringCondition::checkValue(const Message* message, const string& field) {
|
||||
ostringstream output;
|
||||
result_t result = message->decodeLastData(false, field.length() == 0 ? nullptr : field.c_str(), -1, 0, &output);
|
||||
result_t result = message->decodeLastData(false, field.length() == 0 ? nullptr : field.c_str(), -1, OF_NONE, &output);
|
||||
if (result == RESULT_OK) {
|
||||
string value = output.str();
|
||||
for (size_t i = 0; i < m_values.size(); i++) {
|
||||
@@ -2786,10 +2805,17 @@ Message* MessageMap::getNextPoll() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MessageMap::dump(bool withConditions, ostream* output) const {
|
||||
void MessageMap::dump(bool withConditions, OutputFormat outputFormat, ostream* output) const {
|
||||
bool first = true;
|
||||
Message::dumpHeader(nullptr, output);
|
||||
*output << endl;
|
||||
bool isJson = (outputFormat & OF_JSON) != 0;
|
||||
if (isJson) {
|
||||
*output << "{";
|
||||
} else {
|
||||
Message::dumpHeader(nullptr, output);
|
||||
}
|
||||
if (!(outputFormat & OF_SHORT)) {
|
||||
*output << endl;
|
||||
}
|
||||
for (const auto it : m_messagesByName) {
|
||||
if (it.first[0] == FIELD_SEPARATOR) { // skip instances stored multiple times (key starting with "-")
|
||||
continue;
|
||||
@@ -2799,28 +2825,46 @@ void MessageMap::dump(bool withConditions, ostream* output) const {
|
||||
if (!message) {
|
||||
continue;
|
||||
}
|
||||
bool wasFirst = first;
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
*output << endl;
|
||||
}
|
||||
message->dump(nullptr, withConditions, output);
|
||||
if (isJson) {
|
||||
ostringstream str;
|
||||
message->decodeJson(!wasFirst, true, false, false, outputFormat, &str);
|
||||
*output << str.str();
|
||||
} else {
|
||||
message->dump(nullptr, withConditions, outputFormat, output);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Message* message = getFirstAvailable(it.second);
|
||||
if (!message) {
|
||||
continue;
|
||||
}
|
||||
bool wasFirst = first;
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
*output << endl;
|
||||
}
|
||||
message->dump(nullptr, withConditions, output);
|
||||
if (isJson) {
|
||||
ostringstream str;
|
||||
message->decodeJson(!wasFirst, true, false, false, outputFormat, &str);
|
||||
*output << str.str();
|
||||
} else {
|
||||
message->dump(nullptr, withConditions, outputFormat, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!first) {
|
||||
*output << endl;
|
||||
if (isJson) {
|
||||
*output << "}" << endl;
|
||||
} else {
|
||||
if (!first) {
|
||||
*output << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-7
@@ -543,28 +543,31 @@ class Message : public AttributedItem {
|
||||
* Write the message definition or parts of it to the @a ostream.
|
||||
* @param fieldNames the list of field names to write, or nullptr for all.
|
||||
* @param withConditions whether to include the optional conditions prefix.
|
||||
* @param outputFormat the @a OutputFormat options.
|
||||
* @param output the @a ostream to append the formatted value to.
|
||||
*/
|
||||
void dump(const vector<string>* fieldNames, bool withConditions, ostream* output) const;
|
||||
void dump(const vector<string>* fieldNames, bool withConditions, OutputFormat outputFormat, ostream* output) const;
|
||||
|
||||
/**
|
||||
* Write the specified field to the @a ostream.
|
||||
* @param fieldName the field name to write.
|
||||
* @param withConditions whether to include the optional conditions prefix.
|
||||
* @param outputFormat the @a OutputFormat options.
|
||||
* @param output the @a ostream to append the formatted value to.
|
||||
*/
|
||||
virtual void dumpField(const string& fieldName, bool withConditions, ostream* output) const;
|
||||
virtual void dumpField(const string& fieldName, bool withConditions, OutputFormat outputFormat, ostream* output) const;
|
||||
|
||||
/**
|
||||
* Decode the message from the last stored data in JSON format.
|
||||
* @param leadingSeparator whether to prepend a separator before the first value.
|
||||
* @param appendDirection whether to append the direction to the name key (for passive and write).
|
||||
* @param appendDirectionCondition whether to append the direction and condition to the name key.
|
||||
* @param withData whether to add the last data as well.
|
||||
* @param addRaw whether to add the raw symbols as well.
|
||||
* @param outputFormat the @a OutputFormat options to use.
|
||||
* @param output the @a ostringstream to append the decoded value(s) to.
|
||||
*/
|
||||
virtual void decodeJson(bool leadingSeparator, bool appendDirection, bool addRaw, OutputFormat outputFormat,
|
||||
ostringstream* output) const;
|
||||
virtual void decodeJson(bool leadingSeparator, bool appendDirectionCondition, bool withData, bool addRaw,
|
||||
OutputFormat outputFormat, ostringstream* output) const;
|
||||
|
||||
protected:
|
||||
/** the optional circuit name. */
|
||||
@@ -723,7 +726,7 @@ class ChainedMessage : public Message {
|
||||
|
||||
protected:
|
||||
// @copydoc
|
||||
void dumpField(const string& fieldName, bool withConditions, ostream* output) const override;
|
||||
void dumpField(const string& fieldName, bool withConditions, OutputFormat outputFormat, ostream* output) const override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -1519,9 +1522,10 @@ class MessageMap : public MappedFileReader {
|
||||
/**
|
||||
* Write the message definitions to the @a ostream.
|
||||
* @param withConditions whether to include the optional conditions prefix.
|
||||
* @param outputFormat the @a OutputFormat options.
|
||||
* @param output the @a ostream to append the formatted messages to.
|
||||
*/
|
||||
void dump(bool withConditions, ostream* output) const;
|
||||
void dump(bool withConditions, OutputFormat outputFormat, ostream* output) const;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -568,7 +568,7 @@ int main() {
|
||||
if (flags.find('i') != string::npos) {
|
||||
findIndex = parseSignedInt(flags.substr(flags.find('i')+1).c_str(), 10, 0, 9, &result);
|
||||
}
|
||||
OutputFormat verbosity = 0;
|
||||
OutputFormat verbosity = OF_NONE;
|
||||
if (flags.find("v") != string::npos) {
|
||||
verbosity |= OF_NAMES;
|
||||
}
|
||||
@@ -633,7 +633,7 @@ int main() {
|
||||
continue;
|
||||
}
|
||||
cout << "\"" << check[0] << "\"=\"";
|
||||
fields->dump(false, false, &cout);
|
||||
fields->dump(false, OF_NONE, &cout);
|
||||
cout << "\": create OK" << endl;
|
||||
|
||||
ostringstream output;
|
||||
@@ -650,9 +650,9 @@ int main() {
|
||||
cout << " parse \"" << sstr.getStr().substr(0, 2) << "\" error: " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
}
|
||||
result = fields->read(mstr, 0, false, findName, findIndex, verbosity|(numeric?OF_NUMERIC:0), -1, &output);
|
||||
result = fields->read(mstr, 0, false, findName, findIndex, verbosity|(numeric?OF_NUMERIC:OF_NONE), -1, &output);
|
||||
if (result >= RESULT_OK) {
|
||||
result = fields->read(sstr, 0, !output.str().empty(), findName, findIndex, verbosity|(numeric?OF_NUMERIC:0), -1, &output);
|
||||
result = fields->read(sstr, 0, !output.str().empty(), findName, findIndex, verbosity|(numeric?OF_NUMERIC:OF_NONE), -1, &output);
|
||||
}
|
||||
if (failedRead) {
|
||||
if (result >= RESULT_OK) {
|
||||
|
||||
@@ -183,8 +183,6 @@ int main() {
|
||||
{"*r,cir*cuit#level,na*me,com*ment,ff,75,b509,0d", "", "", "", ""},
|
||||
{"r,CIRCUIT,NAME,COMMENT,,,,0100,field,,UCH", "r,cirCIRCUITcuit,naNAMEme,comCOMMENTment,ff,75,b509,0d0100,field,s,UCH,,,: field=42", "ff75b509030d0100", "012a", "DN"},
|
||||
{"r,CIRCUIT,NAME,COMMENT,,,,0100,field,,UCH",
|
||||
// "\"naNAMEme\": {r,cirCIRCUITcuit,naNAMEme,comCOMMENTment,ff,75,b509,0d0100,field,s,UCH,,,: field=42"
|
||||
"\n"
|
||||
" \"naNAMEme\": {\n"
|
||||
" \"name\": \"naNAMEme\",\n"
|
||||
" \"passive\": false,\n"
|
||||
@@ -407,7 +405,7 @@ int main() {
|
||||
ostringstream output;
|
||||
if (withMessageDump) {
|
||||
if (decodeJson) {
|
||||
message->decodeJson(false, false, false, OF_JSON|OF_DEFINTION, &output);
|
||||
message->decodeJson(false, false, true, false, OF_JSON|OF_DEFINITION, &output);
|
||||
string str = output.str();
|
||||
size_t start = str.find("\"lastup\": ");
|
||||
if (start != string::npos) {
|
||||
@@ -420,12 +418,12 @@ int main() {
|
||||
output.str("");
|
||||
output << str;
|
||||
} else {
|
||||
message->dump(nullptr, true, &output);
|
||||
message->dump(nullptr, true, OF_NONE, &output);
|
||||
}
|
||||
output << ": ";
|
||||
}
|
||||
result = message->decodeLastData(false, nullptr, -1,
|
||||
(decodeVerbose?OF_NAMES|OF_UNITS|OF_COMMENTS:0)|(decodeJson?OF_NAMES|OF_JSON:0), &output);
|
||||
(decodeVerbose?OF_NAMES|OF_UNITS|OF_COMMENTS:OF_NONE)|(decodeJson?OF_NAMES|OF_JSON:OF_NONE), &output);
|
||||
if (result != RESULT_OK) {
|
||||
cout << " \"" << check[2] << "\" / \"" << check[3] << "\": decode error " << (message->isWrite() ? "write: " : "read: ")
|
||||
<< getResultCode(result) << endl;
|
||||
|
||||
Reference in New Issue
Block a user