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:
John
2021-04-02 10:41:50 +02:00
parent dc1a1ecc56
commit 38bfc7a751
13 changed files with 264 additions and 200 deletions
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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:
+4 -4
View File
@@ -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) {
+3 -5
View File
@@ -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;