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
+7 -7
View File
@@ -130,7 +130,7 @@ bool ScanRequest::notify(result_t result, const SlaveSymbolString& slave) {
}
if (result == RESULT_OK) {
ostringstream output;
result = m_message->decodeLastData(true, nullptr, -1, 0, &output); // decode data
result = m_message->decodeLastData(true, nullptr, -1, OF_NONE, &output); // decode data
string str = output.str();
m_busHandler->setScanResult(dstAddress, m_notifyIndex+m_index, str);
}
@@ -216,7 +216,7 @@ bool decodeType(const DataType* type, const SymbolString& input, size_t length,
string in = input.getStr(input.getDataOffset());
for (size_t offset = 0; offset <= offsets; offset++) {
ostringstream out;
result_t result = type->readSymbols(offset, length, input, 0, &out);
result_t result = type->readSymbols(offset, length, input, OF_NONE, &out);
if (result != RESULT_OK) {
continue;
}
@@ -231,7 +231,7 @@ bool decodeType(const DataType* type, const SymbolString& input, size_t length,
first = false;
*output << endl << " ";
ostringstream::pos_type cnt = output->tellp();
type->dump(false, length, false, output);
type->dump(OF_NONE, length, false, output);
cnt = output->tellp() - cnt;
while (cnt < 5) {
*output << " ";
@@ -1156,7 +1156,7 @@ void BusHandler::messageCompleted() {
result = message->storeLastData(0, idData);
if (result == RESULT_OK) {
ostringstream output;
result = message->decodeLastData(true, nullptr, -1, 0, &output);
result = message->decodeLastData(true, nullptr, -1, OF_NONE, &output);
if (result == RESULT_OK) {
string str = output.str();
setScanResult(slaveAddress, 0, str);
@@ -1176,7 +1176,7 @@ void BusHandler::messageCompleted() {
result_t result = message->storeLastData(m_command, m_response);
if (result == RESULT_OK) {
ostringstream output;
result = message->decodeLastData(true, nullptr, -1, 0, &output);
result = message->decodeLastData(true, nullptr, -1, OF_NONE, &output);
if (result == RESULT_OK) {
string str = output.str();
setScanResult(dstAddress, 0, str);
@@ -1216,7 +1216,7 @@ void BusHandler::messageCompleted() {
result_t result = message->storeLastData(m_command, m_response);
ostringstream output;
if (result == RESULT_OK) {
result = message->decodeLastData(false, nullptr, -1, 0, &output);
result = message->decodeLastData(false, nullptr, -1, OF_NONE, &output);
}
if (result < RESULT_OK) {
logError(lf_update, "unable to parse %s %s %s from %s / %s: %s", mode, circuit.c_str(), name.c_str(),
@@ -1380,7 +1380,7 @@ void BusHandler::formatScanResult(ostringstream* output) const {
*output << endl;
}
*output << hex << setw(2) << setfill('0') << static_cast<unsigned>(slave);
message->decodeLastData(true, nullptr, -1, 0, output);
message->decodeLastData(true, nullptr, -1, OF_NONE, output);
}
}
}
+3 -3
View File
@@ -1029,7 +1029,7 @@ result_t loadScanConfigFile(MessageMap* messages, symbol_t address, bool verbose
size_t offset = 0;
size_t field = 0;
bool fromLocal = s_configUriPrefix.empty();
result_t result = (*identFields)[field]->read(data, offset, false, nullptr, -1, 0, -1, &out); // manufacturer name
result_t result = (*identFields)[field]->read(data, offset, false, nullptr, -1, OF_NONE, -1, &out); // manufacturer name
if (result == RESULT_ERR_NOTFOUND && fromLocal) {
result = (*identFields)[field]->read(data, offset, false, nullptr, -1, OF_NUMERIC, -1, &out); // manufacturer name
}
@@ -1042,7 +1042,7 @@ result_t loadScanConfigFile(MessageMap* messages, symbol_t address, bool verbose
out.str("");
out.clear();
offset += (*identFields)[field++]->getLength(pt_slaveData, MAX_LEN);
result = (*identFields)[field]->read(data, offset, false, nullptr, -1, 0, -1, &out); // identification string
result = (*identFields)[field]->read(data, offset, false, nullptr, -1, OF_NONE, -1, &out); // identification string
}
if (result == RESULT_OK) {
ident = out.str();
@@ -1307,7 +1307,7 @@ int main(int argc, char* argv[]) {
}
if (result == RESULT_OK && opt.dumpConfig) {
logNotice(lf_main, "configuration dump:");
s_messageMap->dump(true, &cout);
s_messageMap->dump(true, OF_NONE, &cout);
}
shutdown(overallResult != RESULT_OK);
+56 -63
View File
@@ -98,6 +98,13 @@ result_t UserList::addFromFile(const string& filename, unsigned int lineNo, map<
}
#define VERBOSITY_0 OF_NONE
#define VERBOSITY_1 OF_NAMES
#define VERBOSITY_2 (VERBOSITY_1 | OF_UNITS)
#define VERBOSITY_3 (VERBOSITY_2 | OF_COMMENTS)
#define VERBOSITY_4 (VERBOSITY_3 | OF_ALL_ATTRS)
MainLoop::MainLoop(const struct options& opt, Device *device, MessageMap* messages)
: Thread(), m_device(device), m_reconnectCount(0), m_userList(opt.accessLevel), m_messages(messages),
m_address(opt.address), m_scanConfig(opt.scanConfig), m_initialScan(opt.readOnly ? ESC : opt.initialScan),
@@ -702,7 +709,7 @@ result_t MainLoop::executeAuth(const vector<string>& args, string* user, ostring
result_t MainLoop::executeRead(const vector<string>& args, const string& levels, ostringstream* ostream) {
size_t argPos = 1;
bool hex = false, newDefinition = false;
OutputFormat verbosity = 0;
OutputFormat verbosity = OF_NONE;
time_t maxAge = 5*60;
string circuit, params;
symbol_t srcAddress = SYN, dstAddress = SYN;
@@ -732,21 +739,17 @@ result_t MainLoop::executeRead(const vector<string>& args, const string& levels,
break;
}
} else if (args[argPos] == "-v") {
switch (verbosity) {
case 0:
verbosity = OF_NAMES;
break;
case OF_NAMES:
verbosity |= OF_UNITS;
break;
case OF_NAMES|OF_UNITS:
verbosity |= OF_COMMENTS;
break;
if ((verbosity & VERBOSITY_3) == VERBOSITY_0) {
verbosity |= VERBOSITY_1;
} else if ((verbosity & VERBOSITY_3) == VERBOSITY_1) {
verbosity |= VERBOSITY_2;
} else {
verbosity |= VERBOSITY_3;
}
} else if (args[argPos] == "-vv") {
verbosity |= OF_NAMES|OF_UNITS;
verbosity |= VERBOSITY_2;
} else if (args[argPos] == "-vvv" || args[argPos] == "-V") {
verbosity |= OF_NAMES|OF_UNITS|OF_COMMENTS;
verbosity |= VERBOSITY_3;
} else if (args[argPos] == "-n") {
verbosity = (verbosity & ~OF_VALUENAME) | OF_NUMERIC;
} else if (args[argPos] == "-N") {
@@ -799,7 +802,7 @@ result_t MainLoop::executeRead(const vector<string>& args, const string& levels,
}
argPos++;
}
if ((hex && (newDefinition || verbosity != 0 || !circuit.empty() || !params.empty() || dstAddress != SYN
if ((hex && (newDefinition || verbosity != OF_NONE || !circuit.empty() || !params.empty() || dstAddress != SYN
|| pollPriority > 0 || args.size() < argPos + 1))
|| (newDefinition && (hex || !circuit.empty() || pollPriority > 0 || args.size() != argPos + 1))) {
argPos = 0; // print usage
@@ -882,7 +885,7 @@ result_t MainLoop::executeRead(const vector<string>& args, const string& levels,
ret = message->storeLastData(master, slave);
ostringstream result;
if (ret == RESULT_OK) {
ret = message->decodeLastData(false, nullptr, -1, 0, &result);
ret = message->decodeLastData(false, nullptr, -1, OF_NONE, &result);
}
if (ret >= RESULT_OK) {
logInfo(lf_main, "read hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(),
@@ -1107,7 +1110,7 @@ result_t MainLoop::executeWrite(const vector<string>& args, const string levels,
ret = message->storeLastData(master, slave);
ostringstream result;
if (ret == RESULT_OK) {
ret = message->decodeLastData(false, nullptr, -1, 0, &result);
ret = message->decodeLastData(false, nullptr, -1, OF_NONE, &result);
}
if (ret >= RESULT_OK) {
logInfo(lf_main, "write hex %s %s cache update: %s", message->getCircuit().c_str(),
@@ -1178,7 +1181,7 @@ result_t MainLoop::executeWrite(const vector<string>& args, const string levels,
return RESULT_OK;
}
ret = message->decodeLastData(false, false, nullptr, -1, 0, ostream); // decode data
ret = message->decodeLastData(false, false, nullptr, -1, OF_NONE, ostream); // decode data
if (ret >= RESULT_OK && ostream->str().empty()) {
logNotice(lf_main, "write %s %s: decode %s", message->getCircuit().c_str(), message->getName().c_str(),
getResultCode(ret));
@@ -1325,29 +1328,27 @@ result_t MainLoop::executeFind(const vector<string>& args, const string& levels,
bool configFormat = false, exact = false, withRead = true, withWrite = false, withPassive = true, first = true,
onlyWithData = false, hexFormat = false, userLevel = true, withConditions = false;
string useLevels = levels;
OutputFormat verbosity = 0;
OutputFormat verbosity = OF_NONE;
vector<string> fieldNames;
string circuit;
vector<symbol_t> id;
while (args.size() > argPos && args[argPos][0] == '-') {
if (args[argPos] == "-v") {
switch (verbosity) {
case 0:
verbosity |= OF_NAMES;
break;
case OF_NAMES:
verbosity |= OF_UNITS;
break;
case OF_NAMES|OF_UNITS:
verbosity |= OF_COMMENTS;
break;
if ((verbosity & VERBOSITY_4) == VERBOSITY_0) {
verbosity |= VERBOSITY_1;
} else if ((verbosity & VERBOSITY_4) == VERBOSITY_1) {
verbosity |= VERBOSITY_2;
} else if ((verbosity & VERBOSITY_4) == VERBOSITY_2) {
verbosity |= VERBOSITY_3;
} else {
verbosity |= VERBOSITY_4;
}
} else if (args[argPos] == "-vv") {
verbosity |= OF_NAMES|OF_UNITS;
verbosity |= VERBOSITY_2;
} else if (args[argPos] == "-vvv") {
verbosity |= OF_NAMES|OF_UNITS|OF_COMMENTS;
} else if (args[argPos] == "-V") {
verbosity |= OF_NAMES|OF_UNITS|OF_COMMENTS|OF_ALL_ATTRS;
verbosity |= VERBOSITY_3;
} else if (args[argPos] == "-vvvv" || args[argPos] == "-V") {
verbosity |= VERBOSITY_4;
} else if (args[argPos] == "-f") {
configFormat = true;
if (hexFormat) {
@@ -1470,12 +1471,12 @@ result_t MainLoop::executeFind(const vector<string>& args, const string& levels,
if (found) {
*ostream << endl;
}
message->dump(nullptr, withConditions, ostream);
message->dump(nullptr, withConditions, verbosity, ostream);
} else if (!fieldNames.empty()) {
if (found) {
*ostream << endl;
}
message->dump(&fieldNames, withConditions, ostream);
message->dump(&fieldNames, withConditions, verbosity, ostream);
} else {
if (found) {
*ostream << endl;
@@ -1496,7 +1497,7 @@ result_t MainLoop::executeFind(const vector<string>& args, const string& levels,
<< " / " << message->getLastSlaveData().getStr() << ")";
}
}
if ((verbosity & (OF_NAMES|OF_UNITS|OF_COMMENTS)) == (OF_NAMES|OF_UNITS|OF_COMMENTS)) {
if ((verbosity & VERBOSITY_3) == VERBOSITY_3) {
symbol_t dstAddress = message->getDstAddress();
if (dstAddress != SYN) {
snprintf(str, sizeof(str), "%02x", dstAddress);
@@ -1536,26 +1537,22 @@ result_t MainLoop::executeFind(const vector<string>& args, const string& levels,
result_t MainLoop::executeListen(const vector<string>& args, ClientSettings* settings, ostringstream* ostream) {
size_t argPos = 1;
OutputFormat verbosity = 0;
OutputFormat verbosity = OF_NONE;
bool listenWithUnknown = false;
bool listenOnlyUnknown = false;
while (args.size() > argPos && args[argPos][0] == '-') {
if (args[argPos] == "-v") {
switch (verbosity) {
case 0:
verbosity = OF_NAMES;
break;
case OF_NAMES:
verbosity |= OF_UNITS;
break;
case OF_NAMES|OF_UNITS:
verbosity |= OF_COMMENTS;
break;
if ((verbosity & VERBOSITY_3) == VERBOSITY_0) {
verbosity |= VERBOSITY_1;
} else if ((verbosity & VERBOSITY_3) == VERBOSITY_1) {
verbosity |= VERBOSITY_2;
} else {
verbosity |= VERBOSITY_3;
}
} else if (args[argPos] == "-vv") {
verbosity |= OF_NAMES|OF_UNITS;
verbosity |= VERBOSITY_2;
} else if (args[argPos] == "-vvv" || args[argPos] == "-V") {
verbosity |= OF_NAMES|OF_UNITS|OF_COMMENTS;
verbosity |= VERBOSITY_3;
} else if (args[argPos] == "-n") {
verbosity = (verbosity & ~OF_VALUENAME) | OF_NUMERIC;
} else if (args[argPos] == "-N") {
@@ -1686,24 +1683,20 @@ result_t MainLoop::executeDefine(const vector<string>& args, ostringstream* ostr
result_t MainLoop::executeDecode(const vector<string>& args, ostringstream* ostream) {
size_t argPos = 1;
OutputFormat verbosity = 0;
OutputFormat verbosity = OF_NONE;
while (args.size() > argPos && args[argPos][0] == '-') {
if (args[argPos] == "-v") {
switch (verbosity) {
case 0:
verbosity = OF_NAMES;
break;
case OF_NAMES:
verbosity |= OF_UNITS;
break;
case OF_NAMES|OF_UNITS:
verbosity |= OF_COMMENTS;
break;
if ((verbosity & VERBOSITY_3) == VERBOSITY_0) {
verbosity |= VERBOSITY_1;
} else if ((verbosity & VERBOSITY_3) == VERBOSITY_1) {
verbosity |= VERBOSITY_2;
} else {
verbosity |= VERBOSITY_3;
}
} else if (args[argPos] == "-vv") {
verbosity |= OF_NAMES|OF_UNITS;
verbosity |= VERBOSITY_2;
} else if (args[argPos] == "-vvv" || args[argPos] == "-V") {
verbosity |= OF_NAMES|OF_UNITS|OF_COMMENTS;
verbosity |= VERBOSITY_3;
} else if (args[argPos] == "-n") {
verbosity = (verbosity & ~OF_VALUENAME) | OF_NUMERIC;
} else if (args[argPos] == "-N") {
@@ -2096,7 +2089,7 @@ result_t MainLoop::executeGet(const vector<string>& args, bool* connected, ostri
time_t maxLastUp = 0;
if (ret == RESULT_OK) {
bool first = true;
verbosity |= OF_JSON | (full ? OF_ALL_ATTRS : 0) | (withDefinition ? OF_DEFINTION : 0);
verbosity |= OF_JSON | (full ? OF_ALL_ATTRS : OF_NONE) | (withDefinition ? OF_DEFINITION : OF_NONE);
deque<Message*> messages;
m_messages->findAll(circuit, name, getUserLevels(user), exact, true, withWrite, true, true, true, 0, 0, false,
&messages);
@@ -2147,7 +2140,7 @@ result_t MainLoop::executeGet(const vector<string>& args, bool* connected, ostri
Message* next = *(it+1);
same = next->getCircuit() == lastCircuit && next->getName() == name;
}
message->decodeJson(!first, same, raw, verbosity, ostream);
message->decodeJson(!first, same, true, raw, verbosity, ostream);
lastName = name;
first = false;
}
+1 -1
View File
@@ -67,7 +67,7 @@ class NetMessage {
explicit NetMessage(bool isHttp)
: m_isHttp(isHttp), m_resultSet(false), m_disconnect(false), m_listenSince(0) {
m_settings.mode = cm_normal;
m_settings.format = 0;
m_settings.format = OF_NONE;
m_settings.listenWithUnknown = false;
m_settings.listenOnlyUnknown = false;
pthread_mutex_init(&m_mutex, nullptr);
+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;