added conditional messages to find command with "-a" option and include condition prefix for CSV format
also allow passing scan messages with --checkconfig and --scanconfig (without --inject) be more verbose on errors in configuration files improved code style
This commit is contained in:
+146
-141
@@ -65,16 +65,16 @@ const char* getStateCode(BusState state) {
|
||||
|
||||
result_t PollRequest::prepare(symbol_t ownMasterAddress) {
|
||||
istringstream input;
|
||||
result_t result = m_message->prepareMaster(ownMasterAddress, m_master, input, UI_FIELD_SEPARATOR, SYN, m_index);
|
||||
result_t result = m_message->prepareMaster(m_index, ownMasterAddress, SYN, UI_FIELD_SEPARATOR, &input, &m_master);
|
||||
if (result == RESULT_OK) {
|
||||
logInfo(lf_bus, "poll cmd: %s", m_master.getStr().c_str());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PollRequest::notify(result_t result, SlaveSymbolString& slave) {
|
||||
bool PollRequest::notify(result_t result, const SlaveSymbolString& slave) {
|
||||
if (result == RESULT_OK) {
|
||||
result = m_message->storeLastData(slave, m_index);
|
||||
result = m_message->storeLastData(m_index, slave);
|
||||
if (result >= RESULT_OK && m_index+1 < m_message->getCount()) {
|
||||
m_index++;
|
||||
result = prepare(m_master[0]);
|
||||
@@ -85,7 +85,7 @@ bool PollRequest::notify(result_t result, SlaveSymbolString& slave) {
|
||||
}
|
||||
ostringstream output;
|
||||
if (result == RESULT_OK) {
|
||||
result = m_message->decodeLastData(output); // decode data
|
||||
result = m_message->decodeLastData(false, NULL, -1, 0, &output); // decode data
|
||||
}
|
||||
if (result < RESULT_OK) {
|
||||
logError(lf_bus, "poll %s %s failed: %s", m_message->getCircuit().c_str(), m_message->getName().c_str(),
|
||||
@@ -104,28 +104,28 @@ result_t ScanRequest::prepare(symbol_t ownMasterAddress) {
|
||||
}
|
||||
symbol_t dstAddress = m_slaves.front();
|
||||
istringstream input;
|
||||
m_result = m_message->prepareMaster(ownMasterAddress, m_master, input, UI_FIELD_SEPARATOR, dstAddress, m_index);
|
||||
m_result = m_message->prepareMaster(m_index, ownMasterAddress, dstAddress, UI_FIELD_SEPARATOR, &input, &m_master);
|
||||
if (m_result >= RESULT_OK) {
|
||||
logInfo(lf_bus, "scan %2.2x cmd: %s", dstAddress, m_master.getStr().c_str());
|
||||
}
|
||||
return m_result;
|
||||
}
|
||||
|
||||
bool ScanRequest::notify(result_t result, SlaveSymbolString& slave) {
|
||||
bool ScanRequest::notify(result_t result, const SlaveSymbolString& slave) {
|
||||
symbol_t dstAddress = m_master[1];
|
||||
if (result == RESULT_OK) {
|
||||
if (m_message == m_messageMap->getScanMessage()) {
|
||||
Message* message = m_messageMap->getScanMessage(dstAddress);
|
||||
if (message != NULL) {
|
||||
m_message = message;
|
||||
m_message->storeLastData(m_master, m_index); // expected to work since this is a clone
|
||||
m_message->storeLastData(m_index, m_master); // expected to work since this is a clone
|
||||
}
|
||||
} else if (m_message->getDstAddress() == SYN) {
|
||||
m_message = m_message->derive(dstAddress, true);
|
||||
m_messageMap->add(m_message);
|
||||
m_message->storeLastData(m_master, m_index); // expected to work since this is a clone
|
||||
m_messageMap->add(true, m_message);
|
||||
m_message->storeLastData(m_index, m_master); // expected to work since this is a clone
|
||||
}
|
||||
result = m_message->storeLastData(slave, m_index);
|
||||
result = m_message->storeLastData(m_index, slave);
|
||||
if (result >= RESULT_OK && m_index+1 < m_message->getCount()) {
|
||||
m_index++;
|
||||
result = prepare(m_master[0]);
|
||||
@@ -135,7 +135,7 @@ bool ScanRequest::notify(result_t result, SlaveSymbolString& slave) {
|
||||
}
|
||||
if (result == RESULT_OK) {
|
||||
ostringstream output;
|
||||
result = m_message->decodeLastData(output, 0, true); // decode data
|
||||
result = m_message->decodeLastData(true, NULL, -1, 0, &output); // decode data
|
||||
string str = output.str();
|
||||
m_busHandler->setScanResult(dstAddress, m_notifyIndex+m_index, str);
|
||||
}
|
||||
@@ -186,66 +186,68 @@ bool ScanRequest::notify(result_t result, SlaveSymbolString& slave) {
|
||||
}
|
||||
|
||||
|
||||
bool ActiveBusRequest::notify(result_t result, SlaveSymbolString& slave) {
|
||||
bool ActiveBusRequest::notify(result_t result, const SlaveSymbolString& slave) {
|
||||
if (result == RESULT_OK) {
|
||||
logDebug(lf_bus, "read res: %s", slave.getStr().c_str());
|
||||
}
|
||||
m_result = result;
|
||||
m_slave = slave;
|
||||
*m_slave = slave;
|
||||
return false;
|
||||
}
|
||||
|
||||
void GrabbedMessage::setLastData(MasterSymbolString& master, SlaveSymbolString& slave) {
|
||||
|
||||
void GrabbedMessage::setLastData(const MasterSymbolString& master, const SlaveSymbolString& slave) {
|
||||
m_lastMaster = master;
|
||||
m_lastSlave = slave;
|
||||
m_count++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decode the input @a SymbolString with the specified @a DataType and length.
|
||||
* @param type the @a DataType.
|
||||
* @param input the @a SymbolString to read the binary value from.
|
||||
* @param length the number of symbols to read.
|
||||
* @param offsets the last offset to the baseOffset to read.
|
||||
* @param output the ostringstream to append the formatted value to.
|
||||
* @param firstOnly whether to read only the first non-erroneous offset.
|
||||
* @param output the ostringstream to append the formatted value to.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
bool decodeType(const DataType* type, const SymbolString *input, size_t length,
|
||||
size_t offsets, ostringstream& output, bool firstOnly = false) {
|
||||
bool decodeType(const DataType* type, const SymbolString& input, size_t length,
|
||||
size_t offsets, bool firstOnly, ostringstream* output) {
|
||||
bool first = true;
|
||||
string in = input->getStr(input->getDataOffset());
|
||||
string in = input.getStr(input.getDataOffset());
|
||||
for (size_t offset = 0; offset <= offsets; offset++) {
|
||||
ostringstream out;
|
||||
result_t result = type->readSymbols(*input, offset, length, out, 0);
|
||||
result_t result = type->readSymbols(offset, length, input, 0, &out);
|
||||
if (result != RESULT_OK) {
|
||||
continue;
|
||||
}
|
||||
if (type->isNumeric() && type->hasFlag(DAY)) {
|
||||
unsigned int value = 0;
|
||||
if (type->readRawValue(*input, offset, length, value) == RESULT_OK) {
|
||||
if (type->readRawValue(offset, length, input, &value) == RESULT_OK) {
|
||||
out.str("");
|
||||
out << DataField::getDayName(reinterpret_cast<const NumberDataType*>(type)->getMinValue()+value);
|
||||
}
|
||||
}
|
||||
if (first) {
|
||||
first = false;
|
||||
output << endl << " ";
|
||||
ostringstream::pos_type cnt = output.tellp();
|
||||
type->dump(output, length, false);
|
||||
cnt = output.tellp() - cnt;
|
||||
*output << endl << " ";
|
||||
ostringstream::pos_type cnt = output->tellp();
|
||||
type->dump(length, false, output);
|
||||
cnt = output->tellp() - cnt;
|
||||
while (cnt < 5) {
|
||||
output << " ";
|
||||
*output << " ";
|
||||
cnt += 1;
|
||||
}
|
||||
} else {
|
||||
output << ",";
|
||||
*output << ",";
|
||||
}
|
||||
output << " " << in.substr(offset*2, length*2);
|
||||
*output << " " << in.substr(offset*2, length*2);
|
||||
if (type->isNumeric()) {
|
||||
output << "=" << out.str();
|
||||
*output << "=" << out.str();
|
||||
} else {
|
||||
output << "=\"" << out.str() << "\"";
|
||||
*output << "=\"" << out.str() << "\"";
|
||||
}
|
||||
if (firstOnly) {
|
||||
return true; // only the first offset with maximum length when adjustable maximum size is at least 8 bytes
|
||||
@@ -254,23 +256,22 @@ bool decodeType(const DataType* type, const SymbolString *input, size_t length,
|
||||
return !first;
|
||||
}
|
||||
|
||||
bool GrabbedMessage::dump(const bool unknown, MessageMap* messages, bool first, ostringstream& output,
|
||||
const bool decode) const {
|
||||
bool GrabbedMessage::dump(bool unknown, MessageMap* messages, bool first, bool decode, ostringstream* output) const {
|
||||
Message* message = messages->find(m_lastMaster);
|
||||
if (unknown && message) {
|
||||
return false;
|
||||
}
|
||||
if (!first) {
|
||||
output << endl;
|
||||
*output << endl;
|
||||
}
|
||||
symbol_t dstAddress = m_lastMaster[1];
|
||||
output << m_lastMaster.getStr();
|
||||
*output << m_lastMaster.getStr();
|
||||
if (dstAddress != BROADCAST && !isMaster(dstAddress)) {
|
||||
output << " / " << m_lastSlave.getStr();
|
||||
*output << " / " << m_lastSlave.getStr();
|
||||
}
|
||||
output << " = " << static_cast<unsigned>(m_count);
|
||||
*output << " = " << static_cast<unsigned>(m_count);
|
||||
if (message) {
|
||||
output << ": " << message->getCircuit() << " " << message->getName();
|
||||
*output << ": " << message->getCircuit() << " " << message->getName();
|
||||
}
|
||||
if (decode) {
|
||||
DataTypeList *types = DataTypeList::getInstance();
|
||||
@@ -278,13 +279,7 @@ bool GrabbedMessage::dump(const bool unknown, MessageMap* messages, bool first,
|
||||
return true;
|
||||
}
|
||||
bool master = isMaster(dstAddress) || dstAddress == BROADCAST || m_lastSlave.getDataSize() <= 0;
|
||||
const SymbolString *input;
|
||||
if (master) {
|
||||
input = &m_lastMaster;
|
||||
} else {
|
||||
input = &m_lastSlave;
|
||||
}
|
||||
size_t remain = input->getDataSize();
|
||||
size_t remain = master ? m_lastMaster.getDataSize() : m_lastSlave.getDataSize();
|
||||
if (remain == 0) {
|
||||
return true;
|
||||
}
|
||||
@@ -301,14 +296,22 @@ bool GrabbedMessage::dump(const bool unknown, MessageMap* messages, bool first,
|
||||
if (baseType->isAdjustableLength()) {
|
||||
for (size_t length = maxLength; length >= 1; length--) {
|
||||
const DataType* type = types->get(baseType->getId(), length);
|
||||
if (decodeType(type, input, length, remain-length, output, firstOnly)) {
|
||||
if (firstOnly) {
|
||||
break; // only a single offset with maximum length when adjustable maximum size is at least 8 bytes
|
||||
}
|
||||
bool decoded;
|
||||
if (master) {
|
||||
decoded = decodeType(type, m_lastMaster, length, remain-length, firstOnly, output);
|
||||
} else {
|
||||
decoded = decodeType(type, m_lastSlave, length, remain-length, firstOnly, output);
|
||||
}
|
||||
if (decoded && firstOnly) {
|
||||
break; // only a single offset with maximum length when adjustable maximum size is at least 8 bytes
|
||||
}
|
||||
}
|
||||
} else if (maxLength > 0) {
|
||||
decodeType(baseType, input, maxLength, remain-maxLength, output);
|
||||
if (master) {
|
||||
decodeType(baseType, m_lastMaster, maxLength, remain-maxLength, false, output);
|
||||
} else {
|
||||
decodeType(baseType, m_lastSlave, maxLength, remain-maxLength, false, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -322,9 +325,9 @@ void BusHandler::clear() {
|
||||
m_scanResults.clear();
|
||||
}
|
||||
|
||||
result_t BusHandler::sendAndWait(MasterSymbolString& master, SlaveSymbolString& slave) {
|
||||
result_t BusHandler::sendAndWait(const MasterSymbolString& master, SlaveSymbolString* slave) {
|
||||
result_t result = RESULT_ERR_NO_SIGNAL;
|
||||
slave.clear();
|
||||
slave->clear();
|
||||
ActiveBusRequest request(master, slave);
|
||||
logInfo(lf_bus, "send message: %s", master.getStr().c_str());
|
||||
|
||||
@@ -349,26 +352,26 @@ result_t BusHandler::sendAndWait(MasterSymbolString& master, SlaveSymbolString&
|
||||
return result;
|
||||
}
|
||||
|
||||
result_t BusHandler::readFromBus(Message* message, string inputStr, const symbol_t dstAddress,
|
||||
const symbol_t srcAddress) {
|
||||
result_t BusHandler::readFromBus(Message* message, const string& inputStr, symbol_t dstAddress,
|
||||
symbol_t srcAddress) {
|
||||
symbol_t masterAddress = srcAddress == SYN ? m_ownMasterAddress : srcAddress;
|
||||
result_t ret = RESULT_EMPTY;
|
||||
MasterSymbolString master;
|
||||
SlaveSymbolString slave;
|
||||
for (size_t index = 0; index < message->getCount(); index++) {
|
||||
istringstream input(inputStr);
|
||||
ret = message->prepareMaster(masterAddress, master, input, UI_FIELD_SEPARATOR, dstAddress, index);
|
||||
ret = message->prepareMaster(index, masterAddress, dstAddress, UI_FIELD_SEPARATOR, &input, &master);
|
||||
if (ret != RESULT_OK) {
|
||||
logError(lf_bus, "prepare message part %d: %s", index, getResultCode(ret));
|
||||
break;
|
||||
}
|
||||
// send message
|
||||
ret = sendAndWait(master, slave);
|
||||
ret = sendAndWait(master, &slave);
|
||||
if (ret != RESULT_OK) {
|
||||
logError(lf_bus, "send message part %d: %s", index, getResultCode(ret));
|
||||
break;
|
||||
}
|
||||
ret = message->storeLastData(slave, index);
|
||||
ret = message->storeLastData(index, slave);
|
||||
if (ret < RESULT_OK) {
|
||||
logError(lf_bus, "store message part %d: %s", index, getResultCode(ret));
|
||||
break;
|
||||
@@ -569,14 +572,14 @@ result_t BusHandler::handleSymbol() {
|
||||
|
||||
// receive next symbol (optionally check reception of sent symbol)
|
||||
symbol_t recvSymbol;
|
||||
result = m_device->recv(timeout+m_transferLatency, recvSymbol);
|
||||
result = m_device->recv(timeout+m_transferLatency, &recvSymbol);
|
||||
if (!sending && result == RESULT_ERR_TIMEOUT && m_generateSynInterval > 0
|
||||
&& timeout >= m_generateSynInterval && (m_state == bs_noSignal || m_state == bs_skip)) {
|
||||
// check if acting as AUTO-SYN generator is required
|
||||
result = m_device->send(SYN);
|
||||
if (result == RESULT_OK) {
|
||||
recvSymbol = ESC;
|
||||
result = m_device->recv(SEND_TIMEOUT, recvSymbol);
|
||||
result = m_device->recv(SEND_TIMEOUT, &recvSymbol);
|
||||
if (result == RESULT_ERR_TIMEOUT) {
|
||||
return setState(bs_noSignal, result);
|
||||
}
|
||||
@@ -626,7 +629,7 @@ result_t BusHandler::handleSymbol() {
|
||||
case bs_recvRes:
|
||||
case bs_sendCmd:
|
||||
case bs_sendRes:
|
||||
SymbolString::updateCrc(m_crc, recvSymbol);
|
||||
SymbolString::updateCrc(recvSymbol, &m_crc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -883,7 +886,7 @@ result_t BusHandler::handleSymbol() {
|
||||
}
|
||||
// build response and store in m_response for sending back to requesting master
|
||||
m_response.clear();
|
||||
result = message->prepareSlave(input, m_response);
|
||||
result = message->prepareSlave(&input, &m_response);
|
||||
if (result != RESULT_OK) {
|
||||
return setState(bs_skip, result);
|
||||
}
|
||||
@@ -1060,17 +1063,18 @@ void BusHandler::receiveCompleted() {
|
||||
// e.g. 10fe07040a b5564149303001248901
|
||||
MasterSymbolString dummyMaster;
|
||||
istringstream input;
|
||||
result_t result = message->prepareMaster(m_ownMasterAddress, dummyMaster, input);
|
||||
result_t result = message->prepareMaster(0, m_ownMasterAddress, SYN, UI_FIELD_SEPARATOR, &input,
|
||||
&dummyMaster);
|
||||
if (result == RESULT_OK) {
|
||||
SlaveSymbolString idData;
|
||||
idData.push_back(10);
|
||||
for (size_t i = 0; i < 10; i++) {
|
||||
idData.push_back(m_command.dataAt(i));
|
||||
}
|
||||
result = message->storeLastData(idData, 0);
|
||||
result = message->storeLastData(0, idData);
|
||||
if (result == RESULT_OK) {
|
||||
ostringstream output;
|
||||
result = message->decodeLastData(output, 0, true);
|
||||
result = message->decodeLastData(true, NULL, -1, 0, &output);
|
||||
if (result == RESULT_OK) {
|
||||
string str = output.str();
|
||||
setScanResult(slaveAddress, 0, str);
|
||||
@@ -1108,7 +1112,7 @@ void BusHandler::receiveCompleted() {
|
||||
result_t result = message->storeLastData(m_command, m_response);
|
||||
if (result == RESULT_OK) {
|
||||
ostringstream output;
|
||||
result = message->decodeLastData(output, 0, true);
|
||||
result = message->decodeLastData(true, NULL, -1, 0, &output);
|
||||
if (result == RESULT_OK) {
|
||||
string str = output.str();
|
||||
setScanResult(dstAddress, 0, str);
|
||||
@@ -1125,7 +1129,7 @@ void BusHandler::receiveCompleted() {
|
||||
result_t result = message->storeLastData(m_command, m_response);
|
||||
ostringstream output;
|
||||
if (result == RESULT_OK) {
|
||||
result = message->decodeLastData(output);
|
||||
result = message->decodeLastData(false, NULL, -1, 0, &output);
|
||||
}
|
||||
if (result < RESULT_OK) {
|
||||
logError(lf_update, "unable to parse %s %s from %s / %s: %s", circuit.c_str(), name.c_str(),
|
||||
@@ -1151,7 +1155,8 @@ void BusHandler::receiveCompleted() {
|
||||
}
|
||||
}
|
||||
|
||||
result_t BusHandler::prepareScan(symbol_t slave, bool full, string levels, bool& reload, ScanRequest*& request) {
|
||||
result_t BusHandler::prepareScan(symbol_t slave, bool full, const string& levels, bool* reload,
|
||||
ScanRequest** request) {
|
||||
Message* scanMessage = m_messages->getScanMessage();
|
||||
if (scanMessage == NULL) {
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
@@ -1173,14 +1178,14 @@ result_t BusHandler::prepareScan(symbol_t slave, bool full, string levels, bool&
|
||||
deque<symbol_t> slaves;
|
||||
if (slave != SYN) {
|
||||
slaves.push_back(slave);
|
||||
if (!reload) {
|
||||
if (!*reload) {
|
||||
Message* message = m_messages->getScanMessage(slave);
|
||||
if (message == NULL || message->getLastChangeTime() == 0) {
|
||||
reload = true;
|
||||
*reload = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reload = true;
|
||||
*reload = true;
|
||||
for (slave = 1; slave != 0; slave++) { // 0 is known to be a master
|
||||
if (!isValidAddress(slave, false) || isMaster(slave)) {
|
||||
continue;
|
||||
@@ -1194,29 +1199,29 @@ result_t BusHandler::prepareScan(symbol_t slave, bool full, string levels, bool&
|
||||
slaves.push_back(slave);
|
||||
}
|
||||
}
|
||||
if (reload) {
|
||||
if (*reload) {
|
||||
messages.push_front(scanMessage);
|
||||
}
|
||||
if (messages.empty()) {
|
||||
return RESULT_OK;
|
||||
}
|
||||
request = new ScanRequest(slave == SYN, m_messages, messages, slaves, this, reload ? 0 : 1);
|
||||
result_t result = request->prepare(m_ownMasterAddress);
|
||||
*request = new ScanRequest(slave == SYN, m_messages, messages, slaves, this, *reload ? 0 : 1);
|
||||
result_t result = (*request)->prepare(m_ownMasterAddress);
|
||||
if (result < RESULT_OK) {
|
||||
delete request;
|
||||
request = NULL;
|
||||
delete *request;
|
||||
*request = NULL;
|
||||
return result == RESULT_ERR_EOF ? RESULT_EMPTY : result;
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t BusHandler::startScan(bool full, string levels) {
|
||||
result_t BusHandler::startScan(bool full, const string& levels) {
|
||||
if (m_runningScans > 0) {
|
||||
return RESULT_ERR_DUPLICATE;
|
||||
}
|
||||
ScanRequest* request = NULL;
|
||||
bool reload = true;
|
||||
result_t result = prepareScan(SYN, full, levels, reload, request);
|
||||
result_t result = prepareScan(SYN, full, levels, &reload, &request);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -1229,7 +1234,7 @@ result_t BusHandler::startScan(bool full, string levels) {
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void BusHandler::setScanResult(symbol_t dstAddress, size_t index, string str) {
|
||||
void BusHandler::setScanResult(symbol_t dstAddress, size_t index, const string& str) {
|
||||
m_seenAddresses[dstAddress] |= SCAN_INIT;
|
||||
if (str.length() > 0) {
|
||||
m_seenAddresses[dstAddress] |= SCAN_DONE;
|
||||
@@ -1248,28 +1253,28 @@ void BusHandler::setScanFinished() {
|
||||
}
|
||||
}
|
||||
|
||||
bool BusHandler::formatScanResult(symbol_t slave, ostringstream& output, bool leadingNewline) {
|
||||
bool BusHandler::formatScanResult(symbol_t slave, bool leadingNewline, ostringstream* output) const {
|
||||
const auto it = m_scanResults.find(slave);
|
||||
if (it == m_scanResults.end()) {
|
||||
return false;
|
||||
}
|
||||
if (leadingNewline) {
|
||||
output << endl;
|
||||
*output << endl;
|
||||
}
|
||||
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(slave);
|
||||
*output << hex << setw(2) << setfill('0') << static_cast<unsigned>(slave);
|
||||
for (const auto result : it->second) {
|
||||
output << result;
|
||||
*output << result;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void BusHandler::formatScanResult(ostringstream& output) {
|
||||
void BusHandler::formatScanResult(ostringstream* output) const {
|
||||
if (m_runningScans > 0) {
|
||||
output << m_runningScans << " scan(s) still running" << endl;
|
||||
*output << m_runningScans << " scan(s) still running" << endl;
|
||||
}
|
||||
bool first = true;
|
||||
for (symbol_t slave = 1; slave != 0; slave++) { // 0 is known to be a master
|
||||
if (formatScanResult(slave, output, !first)) {
|
||||
if (formatScanResult(slave, !first, output)) {
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
@@ -1282,55 +1287,55 @@ void BusHandler::formatScanResult(ostringstream& output) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
output << endl;
|
||||
*output << endl;
|
||||
}
|
||||
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(slave);
|
||||
message->decodeLastData(output, 0, true);
|
||||
*output << hex << setw(2) << setfill('0') << static_cast<unsigned>(slave);
|
||||
message->decodeLastData(true, NULL, -1, 0, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BusHandler::formatSeenInfo(ostringstream& output) {
|
||||
void BusHandler::formatSeenInfo(ostringstream* output) const {
|
||||
symbol_t address = 0;
|
||||
for (int index = 0; index < 256; index++, address++) {
|
||||
bool ownAddress = !m_device->isReadOnly() && (address == m_ownMasterAddress || address == m_ownSlaveAddress);
|
||||
if (!isValidAddress(address, false) || ((m_seenAddresses[address]&SEEN) == 0 && !ownAddress)) {
|
||||
continue;
|
||||
}
|
||||
output << endl << "address " << setfill('0') << setw(2) << hex << static_cast<unsigned>(address);
|
||||
*output << endl << "address " << setfill('0') << setw(2) << hex << static_cast<unsigned>(address);
|
||||
symbol_t master;
|
||||
if (isMaster(address)) {
|
||||
output << ": master";
|
||||
*output << ": master";
|
||||
master = address;
|
||||
} else {
|
||||
output << ": slave";
|
||||
*output << ": slave";
|
||||
master = getMasterAddress(address);
|
||||
}
|
||||
if (master != SYN) {
|
||||
output << " #" << setw(0) << dec << static_cast<unsigned>(getMasterNumber(master));
|
||||
*output << " #" << setw(0) << dec << static_cast<unsigned>(getMasterNumber(master));
|
||||
}
|
||||
if (ownAddress) {
|
||||
output << ", ebusd";
|
||||
*output << ", ebusd";
|
||||
if (m_answer) {
|
||||
output << " (answering)";
|
||||
*output << " (answering)";
|
||||
}
|
||||
if (m_addressConflict && (m_seenAddresses[address]&SEEN) != 0) {
|
||||
output << ", conflict";
|
||||
*output << ", conflict";
|
||||
}
|
||||
}
|
||||
if ((m_seenAddresses[address]&SCAN_DONE) != 0) {
|
||||
output << ", scanned";
|
||||
*output << ", scanned";
|
||||
Message* message = m_messages->getScanMessage(address);
|
||||
if (message != NULL && message->getLastUpdateTime() > 0) {
|
||||
// add detailed scan info: Manufacturer ID SW HW
|
||||
output << " \"";
|
||||
result_t result = message->decodeLastData(output, OF_NAMES);
|
||||
*output << " \"";
|
||||
result_t result = message->decodeLastData(false, NULL, -1, OF_NAMES, output);
|
||||
if (result != RESULT_OK) {
|
||||
output << "\" error: " << getResultCode(result);
|
||||
*output << "\" error: " << getResultCode(result);
|
||||
} else {
|
||||
output << "\"";
|
||||
*output << "\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1340,15 +1345,15 @@ void BusHandler::formatSeenInfo(ostringstream& output) {
|
||||
for (const auto& loadedFile : loadedFiles) {
|
||||
if (first) {
|
||||
first = false;
|
||||
output << ", loaded \"";
|
||||
*output << ", loaded \"";
|
||||
} else {
|
||||
output << ", \"";
|
||||
*output << ", \"";
|
||||
}
|
||||
output << loadedFile << "\"";
|
||||
*output << loadedFile << "\"";
|
||||
string comment;
|
||||
if (m_messages->getLoadedFileInfo(loadedFile, comment)) {
|
||||
if (m_messages->getLoadedFileInfo(loadedFile, &comment)) {
|
||||
if (!comment.empty()) {
|
||||
output << " (" << comment << ")";
|
||||
*output << " (" << comment << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1356,15 +1361,15 @@ void BusHandler::formatSeenInfo(ostringstream& output) {
|
||||
}
|
||||
}
|
||||
|
||||
void BusHandler::formatUpdateInfo(ostringstream& output) {
|
||||
void BusHandler::formatUpdateInfo(ostringstream* output) const {
|
||||
if (hasSignal()) {
|
||||
output << ",\"s\":" << m_maxSymPerSec;
|
||||
*output << ",\"s\":" << m_maxSymPerSec;
|
||||
}
|
||||
output << ",\"c\":" << m_masterCount;
|
||||
output << ",\"m\":" << m_messages->size();
|
||||
output << ",\"ro\":" << (m_device->isReadOnly() ? 1 : 0);
|
||||
output << ",\"an\":" << (m_answer ? 1 : 0);
|
||||
output << ",\"co\":" << (m_addressConflict ? 1 : 0);
|
||||
*output << ",\"c\":" << m_masterCount
|
||||
<< ",\"m\":" << m_messages->size()
|
||||
<< ",\"ro\":" << (m_device->isReadOnly() ? 1 : 0)
|
||||
<< ",\"an\":" << (m_answer ? 1 : 0)
|
||||
<< ",\"co\":" << (m_addressConflict ? 1 : 0);
|
||||
if (m_grabMessages) {
|
||||
size_t unknownCnt = 0;
|
||||
for (auto it : m_grabbedMessages) {
|
||||
@@ -1373,7 +1378,7 @@ void BusHandler::formatUpdateInfo(ostringstream& output) {
|
||||
unknownCnt++;
|
||||
}
|
||||
}
|
||||
output << ",\"gu\":" << unknownCnt;
|
||||
*output << ",\"gu\":" << unknownCnt;
|
||||
}
|
||||
unsigned char address = 0;
|
||||
for (int index = 0; index < 256; index++, address++) {
|
||||
@@ -1381,68 +1386,68 @@ void BusHandler::formatUpdateInfo(ostringstream& output) {
|
||||
if (!isValidAddress(address, false) || ((m_seenAddresses[address]&SEEN) == 0 && !ownAddress)) {
|
||||
continue;
|
||||
}
|
||||
output << ",\"" << setfill('0') << setw(2) << hex << static_cast<unsigned>(address) << dec << setw(0);
|
||||
output << "\":{\"o\":" << (ownAddress ? 1 : 0);
|
||||
*output << ",\"" << setfill('0') << setw(2) << hex << static_cast<unsigned>(address) << dec << setw(0)
|
||||
<< "\":{\"o\":" << (ownAddress ? 1 : 0);
|
||||
const auto it = m_scanResults.find(address);
|
||||
if (it != m_scanResults.end()) {
|
||||
output << ",\"s\":\"";
|
||||
*output << ",\"s\":\"";
|
||||
for (const auto result : it->second) {
|
||||
output << result;
|
||||
*output << result;
|
||||
}
|
||||
output << "\"";
|
||||
*output << "\"";
|
||||
}
|
||||
if ((m_seenAddresses[address]&SCAN_DONE) != 0) {
|
||||
Message* message = m_messages->getScanMessage(address);
|
||||
if (message != NULL && message->getLastUpdateTime() > 0) {
|
||||
// add detailed scan info: Manufacturer ID SW HW
|
||||
message->decodeLastData(output, OF_NAMES|OF_NUMERIC|OF_JSON|OF_SHORT, true);
|
||||
message->decodeLastData(true, NULL, -1, OF_NAMES|OF_NUMERIC|OF_JSON|OF_SHORT, output);
|
||||
}
|
||||
}
|
||||
const vector<string>& loadedFiles = m_messages->getLoadedFiles(address);
|
||||
if (!loadedFiles.empty()) {
|
||||
output << ",\"f\":[";
|
||||
*output << ",\"f\":[";
|
||||
bool first = true;
|
||||
for (const auto loadedFile : loadedFiles) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
output << ",";
|
||||
*output << ",";
|
||||
}
|
||||
output << "{\"f\":\"" << loadedFile << "\"";
|
||||
*output << "{\"f\":\"" << loadedFile << "\"";
|
||||
string comment;
|
||||
if (m_messages->getLoadedFileInfo(loadedFile, comment)) {
|
||||
if (m_messages->getLoadedFileInfo(loadedFile, &comment)) {
|
||||
if (!comment.empty()) {
|
||||
output << ",\"c\":\"" << comment << "\"";
|
||||
*output << ",\"c\":\"" << comment << "\"";
|
||||
}
|
||||
}
|
||||
output << "}";
|
||||
*output << "}";
|
||||
}
|
||||
output << "]";
|
||||
*output << "]";
|
||||
}
|
||||
output << "}";
|
||||
*output << "}";
|
||||
}
|
||||
vector<string> loadedFiles = m_messages->getLoadedFiles();
|
||||
if (!loadedFiles.empty()) {
|
||||
output << ",\"l\":{";
|
||||
*output << ",\"l\":{";
|
||||
bool first = true;
|
||||
for (const auto& loadedFile : loadedFiles) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
output << ",";
|
||||
*output << ",";
|
||||
}
|
||||
output << "\"" << loadedFile << "\":{";
|
||||
*output << "\"" << loadedFile << "\":{";
|
||||
string comment;
|
||||
size_t hash, size;
|
||||
time_t time;
|
||||
if (m_messages->getLoadedFileInfo(loadedFile, comment, &hash, &size, &time)) {
|
||||
output << "\"h\":\"";
|
||||
if (m_messages->getLoadedFileInfo(loadedFile, &comment, &hash, &size, &time)) {
|
||||
*output << "\"h\":\"";
|
||||
MappedFileReader::formatHash(hash, output);
|
||||
output << "\",\"s\":" << size << ",\"t\":" << time;
|
||||
*output << "\",\"s\":" << size << ",\"t\":" << time;
|
||||
}
|
||||
output << "}";
|
||||
*output << "}";
|
||||
}
|
||||
output << "}";
|
||||
*output << "}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1452,7 +1457,7 @@ result_t BusHandler::scanAndWait(symbol_t dstAddress, bool loadScanConfig, bool
|
||||
}
|
||||
ScanRequest* request = NULL;
|
||||
bool hasAdditionalScanMessages = m_messages->hasAdditionalScanMessages();
|
||||
result_t result = prepareScan(dstAddress, false, "", reload, request);
|
||||
result_t result = prepareScan(dstAddress, false, "", &reload, &request);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -1473,7 +1478,7 @@ result_t BusHandler::scanAndWait(symbol_t dstAddress, bool loadScanConfig, bool
|
||||
string file;
|
||||
bool timedOut = result == RESULT_ERR_TIMEOUT;
|
||||
if (timedOut || result == RESULT_OK) {
|
||||
result = loadScanConfigFile(m_messages, dstAddress, file); // try to load even if one message timed out
|
||||
result = loadScanConfigFile(m_messages, dstAddress, false, &file); // try to load even if one message timed out
|
||||
if (timedOut && result == RESULT_EMPTY) {
|
||||
result = RESULT_ERR_TIMEOUT; // back to previous result
|
||||
}
|
||||
@@ -1503,20 +1508,20 @@ bool BusHandler::enableGrab(bool enable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void BusHandler::formatGrabResult(const bool unknown, ostringstream& output, const bool decode) {
|
||||
void BusHandler::formatGrabResult(bool unknown, bool decode, ostringstream* output) const {
|
||||
if (!m_grabMessages) {
|
||||
output << "grab disabled";
|
||||
*output << "grab disabled";
|
||||
} else {
|
||||
bool first = true;
|
||||
for (const auto& it : m_grabbedMessages) {
|
||||
if (it.second.dump(unknown, m_messages, first, output, decode)) {
|
||||
if (it.second.dump(unknown, m_messages, first, decode, output)) {
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
symbol_t BusHandler::getNextScanAddress(symbol_t lastAddress) {
|
||||
symbol_t BusHandler::getNextScanAddress(symbol_t lastAddress) const {
|
||||
if (lastAddress == SYN) {
|
||||
return SYN;
|
||||
}
|
||||
@@ -1538,7 +1543,7 @@ symbol_t BusHandler::getNextScanAddress(symbol_t lastAddress) {
|
||||
return SYN;
|
||||
}
|
||||
|
||||
void BusHandler::setScanConfigLoaded(symbol_t address, string file) {
|
||||
void BusHandler::setScanConfigLoaded(symbol_t address, const string& file) {
|
||||
m_seenAddresses[address] |= LOAD_INIT;
|
||||
if (!file.empty()) {
|
||||
m_seenAddresses[address] |= LOAD_DONE;
|
||||
|
||||
+37
-38
@@ -109,7 +109,7 @@ class BusRequest {
|
||||
* @param master the master data @a MasterSymbolString to send.
|
||||
* @param deleteOnFinish whether to automatically delete this @a BusRequest when finished.
|
||||
*/
|
||||
BusRequest(MasterSymbolString& master, const bool deleteOnFinish)
|
||||
BusRequest(const MasterSymbolString& master, bool deleteOnFinish)
|
||||
: m_master(master), m_busLostRetries(0),
|
||||
m_deleteOnFinish(deleteOnFinish) {}
|
||||
|
||||
@@ -124,12 +124,12 @@ class BusRequest {
|
||||
* @param slave the @a SlaveSymbolString received.
|
||||
* @return true if the request needs to be restarted.
|
||||
*/
|
||||
virtual bool notify(result_t result, SlaveSymbolString& slave) = 0;
|
||||
virtual bool notify(result_t result, const SlaveSymbolString& slave) = 0;
|
||||
|
||||
|
||||
protected:
|
||||
/** the master data @a MasterSymbolString to send. */
|
||||
MasterSymbolString& m_master;
|
||||
const MasterSymbolString& m_master;
|
||||
|
||||
/** the number of times a send is repeated due to lost arbitration. */
|
||||
unsigned int m_busLostRetries;
|
||||
@@ -166,7 +166,7 @@ class PollRequest : public BusRequest {
|
||||
result_t prepare(symbol_t masterAddress);
|
||||
|
||||
// @copydoc
|
||||
bool notify(result_t result, SlaveSymbolString& slave) override;
|
||||
bool notify(result_t result, const SlaveSymbolString& slave) override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -197,8 +197,8 @@ class ScanRequest : public BusRequest {
|
||||
* @param busHandler the @a BusHandler instance to notify of final scan result.
|
||||
* @param notifyIndex the offset to the index for notifying the scan result.
|
||||
*/
|
||||
ScanRequest(bool deleteOnFinish, MessageMap* messageMap, deque<Message*> messages, deque<symbol_t> slaves,
|
||||
BusHandler* busHandler, size_t notifyIndex = 0)
|
||||
ScanRequest(bool deleteOnFinish, MessageMap* messageMap, const deque<Message*>& messages,
|
||||
const deque<symbol_t>& slaves, BusHandler* busHandler, size_t notifyIndex = 0)
|
||||
: BusRequest(m_master, deleteOnFinish), m_messageMap(messageMap), m_index(0), m_allMessages(messages),
|
||||
m_messages(messages), m_slaves(slaves), m_busHandler(busHandler), m_notifyIndex(notifyIndex),
|
||||
m_result(RESULT_ERR_NO_SIGNAL) {
|
||||
@@ -219,7 +219,7 @@ class ScanRequest : public BusRequest {
|
||||
result_t prepare(symbol_t masterAddress);
|
||||
|
||||
// @copydoc
|
||||
bool notify(result_t result, SlaveSymbolString& slave) override;
|
||||
bool notify(result_t result, const SlaveSymbolString& slave) override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -267,7 +267,7 @@ class ActiveBusRequest : public BusRequest {
|
||||
* @param master the master data @a MasterSymbolString to send.
|
||||
* @param slave reference to @a SlaveSymbolString for filling in the received slave data.
|
||||
*/
|
||||
ActiveBusRequest(MasterSymbolString& master, SlaveSymbolString& slave)
|
||||
ActiveBusRequest(const MasterSymbolString& master, SlaveSymbolString* slave)
|
||||
: BusRequest(master, false), m_result(RESULT_ERR_NO_SIGNAL), m_slave(slave) {}
|
||||
|
||||
/**
|
||||
@@ -276,7 +276,7 @@ class ActiveBusRequest : public BusRequest {
|
||||
virtual ~ActiveBusRequest() {}
|
||||
|
||||
// @copydoc
|
||||
bool notify(result_t result, SlaveSymbolString& slave) override;
|
||||
bool notify(result_t result, const SlaveSymbolString& slave) override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -284,7 +284,7 @@ class ActiveBusRequest : public BusRequest {
|
||||
result_t m_result;
|
||||
|
||||
/** reference to @a SlaveSymbolString for filling in the received slave data. */
|
||||
SlaveSymbolString& m_slave;
|
||||
SlaveSymbolString* m_slave;
|
||||
};
|
||||
|
||||
|
||||
@@ -312,7 +312,7 @@ class GrabbedMessage {
|
||||
* @param master the last @a MasterSymbolString.
|
||||
* @param slave the last @a SymbolString.
|
||||
*/
|
||||
void setLastData(MasterSymbolString& master, SlaveSymbolString& slave);
|
||||
void setLastData(const MasterSymbolString& master, const SlaveSymbolString& slave);
|
||||
|
||||
/**
|
||||
* Get the last @a MasterSymbolString.
|
||||
@@ -325,12 +325,11 @@ class GrabbedMessage {
|
||||
* @param unknown whether to dump only if this message is unknown.
|
||||
* @param messages the @a MessageMap instance for resolving known @a Message instances.
|
||||
* @param first whether this is the first message to be added to the output.
|
||||
* @param output the @a ostringstream to format the messages to.
|
||||
* @param decode whether to add decoding hints.
|
||||
* @param output the @a ostringstream to format the messages to.
|
||||
* @return whether the message was added to the output.
|
||||
*/
|
||||
bool dump(const bool unknown, MessageMap* messages, bool first, ostringstream& output,
|
||||
const bool decode = false) const;
|
||||
bool dump(bool unknown, MessageMap* messages, bool first, bool decode, ostringstream* output) const;
|
||||
|
||||
|
||||
private:
|
||||
@@ -366,11 +365,11 @@ class BusHandler : public WaitThread {
|
||||
* @param pollInterval the interval in seconds in which poll messages are cycled, or 0 if disabled.
|
||||
*/
|
||||
BusHandler(Device* device, MessageMap* messages,
|
||||
const symbol_t ownAddress, const bool answer,
|
||||
const unsigned int busLostRetries, const unsigned int failedSendRetries,
|
||||
const unsigned int transferLatency, const unsigned int busAcquireTimeout, const unsigned int slaveRecvTimeout,
|
||||
const unsigned int lockCount, const bool generateSyn,
|
||||
const unsigned int pollInterval)
|
||||
symbol_t ownAddress, bool answer,
|
||||
unsigned int busLostRetries, unsigned int failedSendRetries,
|
||||
unsigned int transferLatency, unsigned int busAcquireTimeout, unsigned int slaveRecvTimeout,
|
||||
unsigned int lockCount, bool generateSyn,
|
||||
unsigned int pollInterval)
|
||||
: WaitThread(), m_device(device), m_reconnect(false), m_messages(messages),
|
||||
m_ownMasterAddress(ownAddress), m_ownSlaveAddress(getSlaveAddress(ownAddress)),
|
||||
m_answer(answer), m_addressConflict(false),
|
||||
@@ -418,7 +417,7 @@ class BusHandler : public WaitThread {
|
||||
* @param master the @a MasterSymbolString with the master data.
|
||||
* @param slave the @a SlaveSymbolString with the slave data.
|
||||
*/
|
||||
void injectMessage(MasterSymbolString& master, SlaveSymbolString& slave) {
|
||||
void injectMessage(const MasterSymbolString& master, const SlaveSymbolString& slave) {
|
||||
m_command = master;
|
||||
m_response = slave;
|
||||
m_addressConflict = true; // avoid conflict messages
|
||||
@@ -432,7 +431,7 @@ class BusHandler : public WaitThread {
|
||||
* @param slave the @a SlaveSymbolString that will be filled with retrieved slave data.
|
||||
* @return the result code.
|
||||
*/
|
||||
result_t sendAndWait(MasterSymbolString& master, SlaveSymbolString& slave);
|
||||
result_t sendAndWait(const MasterSymbolString& master, SlaveSymbolString* slave);
|
||||
|
||||
/**
|
||||
* Prepare the master part for the @a Message, send it to the bus and wait for the answer.
|
||||
@@ -442,8 +441,8 @@ class BusHandler : public WaitThread {
|
||||
* @param srcAddress the source address to set, or @a SYN for the own master address.
|
||||
* @return the result code.
|
||||
*/
|
||||
result_t readFromBus(Message* message, string inputStr, const symbol_t dstAddress = SYN,
|
||||
const symbol_t srcAddress = SYN);
|
||||
result_t readFromBus(Message* message, const string& inputStr, symbol_t dstAddress = SYN,
|
||||
symbol_t srcAddress = SYN);
|
||||
|
||||
/**
|
||||
* Main thread entry.
|
||||
@@ -456,7 +455,7 @@ class BusHandler : public WaitThread {
|
||||
* @param levels the current user's access levels.
|
||||
* @return the result code.
|
||||
*/
|
||||
result_t startScan(bool full, string levels);
|
||||
result_t startScan(bool full, const string& levels);
|
||||
|
||||
/**
|
||||
* Set the scan result @a string for a scanned slave address.
|
||||
@@ -464,7 +463,7 @@ class BusHandler : public WaitThread {
|
||||
* @param index the index of the result to set (starting with 0 for the ident message).
|
||||
* @param str the scan result @a string to set, or empty if not a single part of the scan was successful.
|
||||
*/
|
||||
void setScanResult(symbol_t dstAddress, size_t index, string str);
|
||||
void setScanResult(symbol_t dstAddress, size_t index, const string& str);
|
||||
|
||||
/**
|
||||
* Called from @a ScanRequest upon completion.
|
||||
@@ -478,25 +477,25 @@ class BusHandler : public WaitThread {
|
||||
* @param output the @a ostringstream to format the scan result to.
|
||||
* @return true when a scan result was formatted, false otherwise.
|
||||
*/
|
||||
bool formatScanResult(symbol_t slave, ostringstream& output, bool leadingNewline);
|
||||
bool formatScanResult(symbol_t slave, bool leadingNewline, ostringstream* output) const;
|
||||
|
||||
/**
|
||||
* Format the scan result to the @a ostringstream.
|
||||
* @param output the @a ostringstream to format the scan result to.
|
||||
*/
|
||||
void formatScanResult(ostringstream& output);
|
||||
void formatScanResult(ostringstream* output) const;
|
||||
|
||||
/**
|
||||
* Format information about seen participants to the @a ostringstream.
|
||||
* @param output the @a ostringstream to append the info to.
|
||||
*/
|
||||
void formatSeenInfo(ostringstream& output);
|
||||
void formatSeenInfo(ostringstream* output) const;
|
||||
|
||||
/**
|
||||
* Format information for running the update check to the @a ostringstream.
|
||||
* @param output the @a ostringstream to append the info to.
|
||||
*/
|
||||
void formatUpdateInfo(ostringstream& output);
|
||||
void formatUpdateInfo(ostringstream* output) const;
|
||||
|
||||
/**
|
||||
* Send a scan message on the bus and wait for the answer.
|
||||
@@ -517,16 +516,16 @@ class BusHandler : public WaitThread {
|
||||
/**
|
||||
* Format the grabbed messages to the @a ostringstream.
|
||||
* @param unknown whether to dump only unknown messages.
|
||||
* @param output the @a ostringstream to format the messages to.
|
||||
* @param decode whether to add decoding hints.
|
||||
* @param output the @a ostringstream to format the messages to.
|
||||
*/
|
||||
void formatGrabResult(const bool unknown, ostringstream& output, const bool decode = false);
|
||||
void formatGrabResult(bool unknown, bool decode, ostringstream* output) const;
|
||||
|
||||
/**
|
||||
* Return true when a signal on the bus is available.
|
||||
* @return true when a signal on the bus is available.
|
||||
*/
|
||||
bool hasSignal() { return m_state != bs_noSignal; }
|
||||
bool hasSignal() const { return m_state != bs_noSignal; }
|
||||
|
||||
/**
|
||||
* Reconnect the device.
|
||||
@@ -537,33 +536,33 @@ class BusHandler : public WaitThread {
|
||||
* Return the current symbol rate.
|
||||
* @return the number of received symbols in the last second.
|
||||
*/
|
||||
unsigned int getSymbolRate() { return m_symPerSec; }
|
||||
unsigned int getSymbolRate() const { return m_symPerSec; }
|
||||
|
||||
/**
|
||||
* Return the maximum seen symbol rate.
|
||||
* @return the maximum number of received symbols per second ever seen.
|
||||
*/
|
||||
unsigned int getMaxSymbolRate() { return m_maxSymPerSec; }
|
||||
unsigned int getMaxSymbolRate() const { return m_maxSymPerSec; }
|
||||
|
||||
/**
|
||||
* Return the number of masters already seen.
|
||||
* @return the number of masters already seen (including ebusd itself).
|
||||
*/
|
||||
unsigned int getMasterCount() { return m_masterCount; }
|
||||
unsigned int getMasterCount() const { return m_masterCount; }
|
||||
|
||||
/**
|
||||
* Get the next slave address that still needs to be scanned or loaded.
|
||||
* @param lastAddress the last returned slave address, or 0 for returning the first one.
|
||||
* @return the next slave address that still needs to be scanned or loaded, or @a SYN.
|
||||
*/
|
||||
symbol_t getNextScanAddress(symbol_t lastAddress);
|
||||
symbol_t getNextScanAddress(symbol_t lastAddress) const;
|
||||
|
||||
/**
|
||||
* Set the state of the participant to configuration @a LOADED.
|
||||
* @param address the slave address.
|
||||
* @param file the file from which the configuration was loaded, or empty if loading was not possible.
|
||||
*/
|
||||
void setScanConfigLoaded(symbol_t address, string file);
|
||||
void setScanConfigLoaded(symbol_t address, const string& file);
|
||||
|
||||
|
||||
private:
|
||||
@@ -603,7 +602,7 @@ class BusHandler : public WaitThread {
|
||||
* @param request the created @a ScanRequest (may be NULL with positive result if scan is not needed).
|
||||
* @return the result code.
|
||||
*/
|
||||
result_t prepareScan(symbol_t slave, bool full, string levels, bool& reload, ScanRequest*& request);
|
||||
result_t prepareScan(symbol_t slave, bool full, const string& levels, bool* reload, ScanRequest** request);
|
||||
|
||||
/** the @a Device instance for accessing the bus. */
|
||||
Device* m_device;
|
||||
|
||||
@@ -51,12 +51,12 @@ const struct argp_child* datahandler_getargs() {
|
||||
}
|
||||
|
||||
bool datahandler_register(UserInfo* userInfo, BusHandler* busHandler, MessageMap* messages,
|
||||
list<DataHandler*>& handlers) {
|
||||
list<DataHandler*>* handlers) {
|
||||
bool success = true;
|
||||
#ifdef HAVE_MQTT
|
||||
DataHandler* handler = mqtthandler_register(userInfo, busHandler, messages);
|
||||
if (handler) {
|
||||
handlers.push_back(handler);
|
||||
handlers->push_back(handler);
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ const struct argp_child* datahandler_getargs();
|
||||
* @return true if registration was successful.
|
||||
*/
|
||||
bool datahandler_register(UserInfo* userInfo, BusHandler* busHandler, MessageMap* messages,
|
||||
list<DataHandler*>& handlers);
|
||||
list<DataHandler*>* handlers);
|
||||
|
||||
|
||||
/**
|
||||
@@ -73,7 +73,7 @@ class UserInfo {
|
||||
* @param user the user name.
|
||||
* @return whether the user exists.
|
||||
*/
|
||||
virtual bool hasUser(const string user) const = 0; // abstract
|
||||
virtual bool hasUser(const string& user) const = 0; // abstract
|
||||
|
||||
/**
|
||||
* Check whether the secret string matches the one of the specified user.
|
||||
@@ -81,14 +81,14 @@ class UserInfo {
|
||||
* @param secret the secret to check.
|
||||
* @return whether the secret string is valid.
|
||||
*/
|
||||
virtual bool checkSecret(const string user, const string secret) const = 0; // abstract
|
||||
virtual bool checkSecret(const string& user, const string& secret) const = 0; // abstract
|
||||
|
||||
/**
|
||||
* Get the access levels associated with the specified user.
|
||||
* @param user the user name, or empty for default levels.
|
||||
* @return the access levels separated by semicolon.
|
||||
*/
|
||||
virtual string getLevels(const string user) const = 0; // abstract
|
||||
virtual string getLevels(const string& user) const = 0; // abstract
|
||||
};
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ class DataSink : virtual public DataHandler {
|
||||
* @param userInfo the @a UserInfo instance.
|
||||
* @param user the user name for determining the allowed access levels (fall back to default levels).
|
||||
*/
|
||||
DataSink(UserInfo* userInfo, string user) {
|
||||
DataSink(const UserInfo* userInfo, const string& user) {
|
||||
m_levels = userInfo->getLevels(userInfo->hasUser(user) ? user : "");
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ class DataSink : virtual public DataHandler {
|
||||
* Notify the sink of the latest update check result.
|
||||
* @param checkResult a string describing available updates, or empty if no update is available.
|
||||
*/
|
||||
virtual void notifyUpdateCheckResult(string checkResult) {}
|
||||
virtual void notifyUpdateCheckResult(const string& checkResult) {}
|
||||
|
||||
protected:
|
||||
/** the allowed access levels. */
|
||||
|
||||
+71
-59
@@ -178,9 +178,8 @@ static const struct argp_option argpoptions[] = {
|
||||
{"configpath", 'c', "PATH", 0, "Read CSV config files from PATH [" CONFIG_PATH "]", 0 },
|
||||
{"scanconfig", 's', "ADDR", OPTION_ARG_OPTIONAL, "Pick CSV config files matching initial scan (ADDR="
|
||||
"\"none\" or empty for no initial scan message, \"full\" for full scan, or a single hex address to scan, "
|
||||
"default is broadcast ident message). If combined with --checkconfig and --inject, you can add scan message "
|
||||
"data as arguments for checking a particular scan configuration, e.g. \"FF08070400/0AB5454850303003277201\".",
|
||||
0 },
|
||||
"default is broadcast ident message). If combined with --checkconfig, you can add scan message data as "
|
||||
"arguments for checking a particular scan configuration, e.g. \"FF08070400/0AB5454850303003277201\".", 0 },
|
||||
{"configlang", O_CFGLNG, "LANG", 0,
|
||||
"Prefer LANG in multilingual configuration files [system default language]", 0 },
|
||||
{"checkconfig", O_CHKCFG, NULL, 0, "Check CSV config files, then stop", 0 },
|
||||
@@ -280,7 +279,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||
opt->initialSend = true;
|
||||
break;
|
||||
case O_DEVLAT: // --latency=10000
|
||||
opt->latency = parseInt(arg, 10, 0, 200000, result);
|
||||
opt->latency = parseInt(arg, 10, 0, 200000, &result);
|
||||
if (result != RESULT_OK) {
|
||||
argp_error(state, "invalid latency");
|
||||
return EINVAL;
|
||||
@@ -307,7 +306,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||
} else if (strcmp("full", arg) == 0) {
|
||||
opt->initialScan = SYN;
|
||||
} else {
|
||||
opt->initialScan = (symbol_t)parseInt(arg, 16, 0x00, 0xff, result);
|
||||
opt->initialScan = (symbol_t)parseInt(arg, 16, 0x00, 0xff, &result);
|
||||
if (!isValidAddress(opt->initialScan)) {
|
||||
argp_error(state, "invalid initial scan address");
|
||||
return EINVAL;
|
||||
@@ -333,7 +332,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||
opt->dumpConfig = true;
|
||||
break;
|
||||
case O_POLINT: // --pollinterval=5
|
||||
opt->pollInterval = parseInt(arg, 10, 0, 3600, result);
|
||||
opt->pollInterval = parseInt(arg, 10, 0, 3600, &result);
|
||||
if (result != RESULT_OK) {
|
||||
argp_error(state, "invalid pollinterval");
|
||||
return EINVAL;
|
||||
@@ -349,7 +348,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||
|
||||
// eBUS options:
|
||||
case 'a': // --address=31
|
||||
opt->address = (symbol_t)parseInt(arg, 16, 0, 0xff, result);
|
||||
opt->address = (symbol_t)parseInt(arg, 16, 0, 0xff, &result);
|
||||
if (result != RESULT_OK || !isMaster(opt->address)) {
|
||||
argp_error(state, "invalid address");
|
||||
return EINVAL;
|
||||
@@ -363,35 +362,35 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||
opt->answer = true;
|
||||
break;
|
||||
case O_ACQTIM: // --acquiretimeout=9400
|
||||
opt->acquireTimeout = parseInt(arg, 10, 1000, 100000, result);
|
||||
opt->acquireTimeout = parseInt(arg, 10, 1000, 100000, &result);
|
||||
if (result != RESULT_OK) {
|
||||
argp_error(state, "invalid acquiretimeout");
|
||||
return EINVAL;
|
||||
}
|
||||
break;
|
||||
case O_ACQRET: // --acquireretries=3
|
||||
opt->acquireRetries = parseInt(arg, 10, 0, 10, result);
|
||||
opt->acquireRetries = parseInt(arg, 10, 0, 10, &result);
|
||||
if (result != RESULT_OK) {
|
||||
argp_error(state, "invalid acquireretries");
|
||||
return EINVAL;
|
||||
}
|
||||
break;
|
||||
case O_SNDRET: // --sendretries=2
|
||||
opt->sendRetries = parseInt(arg, 10, 0, 10, result);
|
||||
opt->sendRetries = parseInt(arg, 10, 0, 10, &result);
|
||||
if (result != RESULT_OK) {
|
||||
argp_error(state, "invalid sendretries");
|
||||
return EINVAL;
|
||||
}
|
||||
break;
|
||||
case O_RCVTIM: // --receivetimeout=25000
|
||||
opt->receiveTimeout = parseInt(arg, 10, 1000, 100000, result);
|
||||
opt->receiveTimeout = parseInt(arg, 10, 1000, 100000, &result);
|
||||
if (result != RESULT_OK) {
|
||||
argp_error(state, "invalid receivetimeout");
|
||||
return EINVAL;
|
||||
}
|
||||
break;
|
||||
case O_MASCNT: // --numbermasters=0
|
||||
opt->masterCount = parseInt(arg, 10, 0, 25, result);
|
||||
opt->masterCount = parseInt(arg, 10, 0, 25, &result);
|
||||
if (result != RESULT_OK) {
|
||||
argp_error(state, "invalid numbermasters");
|
||||
return EINVAL;
|
||||
@@ -434,7 +433,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||
opt->pidFile = arg;
|
||||
break;
|
||||
case 'p': // --port=8888
|
||||
opt->port = (uint16_t)parseInt(arg, 10, 1, 65535, result);
|
||||
opt->port = (uint16_t)parseInt(arg, 10, 1, 65535, &result);
|
||||
if (result != RESULT_OK) {
|
||||
argp_error(state, "invalid port");
|
||||
return EINVAL;
|
||||
@@ -444,7 +443,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||
opt->localOnly = true;
|
||||
break;
|
||||
case O_HTTPPT: // --httpport=0
|
||||
opt->httpPort = (uint16_t)parseInt(arg, 10, 1, 65535, result);
|
||||
opt->httpPort = (uint16_t)parseInt(arg, 10, 1, 65535, &result);
|
||||
if (result != RESULT_OK) {
|
||||
argp_error(state, "invalid httpport");
|
||||
return EINVAL;
|
||||
@@ -527,7 +526,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||
opt->logRawFile = arg;
|
||||
break;
|
||||
case O_RAWSIZ: // --lograwdatasize=100
|
||||
opt->logRawSize = parseInt(arg, 10, 1, 1000000, result);
|
||||
opt->logRawSize = parseInt(arg, 10, 1, 1000000, &result);
|
||||
if (result != RESULT_OK) {
|
||||
argp_error(state, "invalid lograwdatasize");
|
||||
return EINVAL;
|
||||
@@ -547,7 +546,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||
opt->dumpFile = arg;
|
||||
break;
|
||||
case O_DMPSIZ: // --dumpsize=100
|
||||
opt->dumpSize = parseInt(arg, 10, 1, 1000000, result);
|
||||
opt->dumpSize = parseInt(arg, 10, 1, 1000000, &result);
|
||||
if (result != RESULT_OK) {
|
||||
argp_error(state, "invalid dumpsize");
|
||||
return EINVAL;
|
||||
@@ -555,11 +554,11 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||
break;
|
||||
|
||||
case ARGP_KEY_ARG:
|
||||
if (!opt->injectMessages) {
|
||||
argp_error(state, "invalid arguments starting with \"%s\"", arg);
|
||||
return EINVAL;
|
||||
if (opt->injectMessages || (opt->checkConfig && opt->scanConfig)) {
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
argp_error(state, "invalid arguments starting with \"%s\"", arg);
|
||||
return EINVAL;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
@@ -704,7 +703,7 @@ void signalHandler(int sig) {
|
||||
* @return the result code.
|
||||
*/
|
||||
static result_t collectConfigFiles(const string path, const string prefix, const string extension,
|
||||
vector<string>& files, vector<string>* dirs = NULL, bool* hasTemplates = NULL) {
|
||||
vector<string>* files, vector<string>* dirs = NULL, bool* hasTemplates = NULL) {
|
||||
DIR* dir = opendir(path.c_str());
|
||||
|
||||
if (dir == NULL) {
|
||||
@@ -735,7 +734,7 @@ static result_t collectConfigFiles(const string path, const string prefix, const
|
||||
}
|
||||
} else if (prefix.length() == 0
|
||||
|| (name.length() >= prefix.length() && name.substr(0, prefix.length()) == prefix)) {
|
||||
files.push_back(p);
|
||||
files->push_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -744,7 +743,7 @@ static result_t collectConfigFiles(const string path, const string prefix, const
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
DataFieldTemplates* getTemplates(const string filename) {
|
||||
DataFieldTemplates* getTemplates(const string& filename) {
|
||||
string path;
|
||||
size_t pos = filename.find_last_of('/');
|
||||
if (pos != string::npos) {
|
||||
@@ -783,7 +782,8 @@ static bool readTemplates(const string path, const string extension, bool availa
|
||||
return true;
|
||||
}
|
||||
string errorDescription;
|
||||
result_t result = templates->readFromFile(path+"/_templates"+extension, errorDescription, verbose);
|
||||
result_t result = templates->readFromFile(path+"/_templates"+extension, verbose, NULL, &errorDescription,
|
||||
NULL, NULL, NULL);
|
||||
if (result == RESULT_OK) {
|
||||
logInfo(lf_main, "read templates in %s", path.c_str());
|
||||
return true;
|
||||
@@ -802,18 +802,18 @@ static bool readTemplates(const string path, const string extension, bool availa
|
||||
* @param verbose whether to verbosely log problems.
|
||||
* @return the result code.
|
||||
*/
|
||||
static result_t readConfigFiles(const string path, const string extension, MessageMap* messages, bool recursive,
|
||||
bool verbose, string& errorDescription) {
|
||||
static result_t readConfigFiles(const string& path, const string& extension, const bool recursive,
|
||||
const bool verbose, string* errorDescription, MessageMap* messages) {
|
||||
vector<string> files, dirs;
|
||||
bool hasTemplates = false;
|
||||
result_t result = collectConfigFiles(path, "", extension, files, &dirs, &hasTemplates);
|
||||
result_t result = collectConfigFiles(path, "", extension, &files, &dirs, &hasTemplates);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
readTemplates(path, extension, hasTemplates, verbose);
|
||||
for (const auto& name : files) {
|
||||
logInfo(lf_main, "reading file %s", name.c_str());
|
||||
result = messages->readFromFile(name, errorDescription, verbose);
|
||||
result = messages->readFromFile(name, verbose, NULL, errorDescription, NULL, NULL, NULL);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -821,7 +821,7 @@ static result_t readConfigFiles(const string path, const string extension, Messa
|
||||
if (recursive) {
|
||||
for (const auto& name : dirs) {
|
||||
logInfo(lf_main, "reading dir %s", name.c_str());
|
||||
result = readConfigFiles(name, extension, messages, true, verbose, errorDescription);
|
||||
result = readConfigFiles(name, extension, true, verbose, errorDescription, messages);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -848,13 +848,13 @@ void readMessage(Message* message) {
|
||||
|
||||
void executeInstructions(MessageMap* messages, bool verbose) {
|
||||
string errorDescription;
|
||||
result_t result = messages->resolveConditions(errorDescription, verbose);
|
||||
result_t result = messages->resolveConditions(verbose, &errorDescription);
|
||||
if (result != RESULT_OK) {
|
||||
logError(lf_main, "error resolving conditions: %s, last error: %s", getResultCode(result),
|
||||
errorDescription.c_str());
|
||||
}
|
||||
ostringstream log;
|
||||
result = messages->executeInstructions(log, readMessage);
|
||||
result = messages->executeInstructions(readMessage, &log);
|
||||
if (result != RESULT_OK) {
|
||||
logError(lf_main, "error executing instructions: %s, last error: %s", getResultCode(result),
|
||||
log.str().c_str());
|
||||
@@ -878,8 +878,8 @@ result_t loadConfigFiles(MessageMap* messages, bool verbose, bool denyRecursive)
|
||||
s_templatesByPath.clear();
|
||||
|
||||
string errorDescription;
|
||||
result_t result = readConfigFiles(string(opt.configPath), ".csv", messages,
|
||||
(!opt.scanConfig || opt.checkConfig) && !denyRecursive, verbose, errorDescription);
|
||||
result_t result = readConfigFiles(string(opt.configPath), ".csv",
|
||||
(!opt.scanConfig || opt.checkConfig) && !denyRecursive, verbose, &errorDescription, messages);
|
||||
if (result == RESULT_OK) {
|
||||
logInfo(lf_main, "read config files");
|
||||
} else {
|
||||
@@ -889,7 +889,7 @@ result_t loadConfigFiles(MessageMap* messages, bool verbose, bool denyRecursive)
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& relativeFile, bool verbose) {
|
||||
result_t loadScanConfigFile(MessageMap* messages, symbol_t address, bool verbose, string* relativeFile) {
|
||||
Message* message = messages->getScanMessage(address);
|
||||
if (!message || message->getLastUpdateTime() == 0) {
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
@@ -905,9 +905,9 @@ result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& rela
|
||||
ostringstream out;
|
||||
size_t offset = 0;
|
||||
size_t field = 0;
|
||||
result_t result = (*identFields)[field]->read(data, offset, out, 0); // manufacturer name
|
||||
result_t result = (*identFields)[field]->read(data, offset, false, NULL, -1, 0, -1, &out); // manufacturer name
|
||||
if (result == RESULT_ERR_NOTFOUND) {
|
||||
result = (*identFields)[field]->read(data, offset, out, OF_NUMERIC); // manufacturer name
|
||||
result = (*identFields)[field]->read(data, offset, false, NULL, -1, OF_NUMERIC, -1, &out); // manufacturer name
|
||||
}
|
||||
if (result == RESULT_OK) {
|
||||
path = out.str();
|
||||
@@ -918,22 +918,22 @@ result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& rela
|
||||
prefix = out.str();
|
||||
out.str("");
|
||||
out.clear();
|
||||
offset += (*identFields)[field++]->getLength(pt_slaveData);
|
||||
result = (*identFields)[field]->read(data, offset, out, 0); // identification string
|
||||
offset += (*identFields)[field++]->getLength(pt_slaveData, MAX_LEN);
|
||||
result = (*identFields)[field]->read(data, offset, false, NULL, -1, 0, -1, &out); // identification string
|
||||
}
|
||||
if (result == RESULT_OK) {
|
||||
ident = out.str();
|
||||
out.str("");
|
||||
offset += (*identFields)[field++]->getLength(pt_slaveData);
|
||||
result = (*identFields)[field]->read(data, offset, sw, 0); // software version number
|
||||
offset += (*identFields)[field++]->getLength(pt_slaveData, MAX_LEN);
|
||||
result = (*identFields)[field]->read(data, offset, NULL, -1, &sw); // software version number
|
||||
if (result == RESULT_ERR_OUT_OF_RANGE) {
|
||||
sw = (data.dataAt(offset) << 16) | data.dataAt(offset+1); // use hex value instead
|
||||
result = RESULT_OK;
|
||||
}
|
||||
}
|
||||
if (result == RESULT_OK) {
|
||||
offset += (*identFields)[field++]->getLength(pt_slaveData);
|
||||
result = (*identFields)[field]->read(data, offset, hw, 0); // hardware version number
|
||||
offset += (*identFields)[field++]->getLength(pt_slaveData, MAX_LEN);
|
||||
result = (*identFields)[field]->read(data, offset, NULL, -1, &hw); // hardware version number
|
||||
if (result == RESULT_ERR_OUT_OF_RANGE) {
|
||||
hw = (data.dataAt(offset) << 16) | data.dataAt(offset+1); // use hex value instead
|
||||
result = RESULT_OK;
|
||||
@@ -947,7 +947,7 @@ result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& rela
|
||||
vector<string> files;
|
||||
bool hasTemplates = false;
|
||||
// find files matching MANUFACTURER/ZZ.*csv in cfgpath
|
||||
result = collectConfigFiles(path, prefix, ".csv", files, NULL, &hasTemplates);
|
||||
result = collectConfigFiles(path, prefix, ".csv", &files, NULL, &hasTemplates);
|
||||
if (result != RESULT_OK) {
|
||||
logError(lf_main, "unable to load scan config %2.2x: list files in %s %s", address, path.c_str(),
|
||||
getResultCode(result));
|
||||
@@ -978,7 +978,7 @@ result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& rela
|
||||
unsigned int checkSw, checkHw;
|
||||
map<string, string> defaults;
|
||||
const string filename = name.substr(path.length()+1);
|
||||
if (!messages->extractDefaultsFromFilename(filename, defaults, &checkDest, &checkSw, &checkHw)) {
|
||||
if (!messages->extractDefaultsFromFilename(filename, &defaults, &checkDest, &checkSw, &checkHw)) {
|
||||
continue;
|
||||
}
|
||||
if (address != checkDest || (checkSw != UINT_MAX && sw != checkSw) || (checkHw != UINT_MAX && hw != checkHw)) {
|
||||
@@ -1022,7 +1022,7 @@ result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& rela
|
||||
// found the right file. load the templates if necessary, then load the file itself
|
||||
bool readCommon = readTemplates(path, ".csv", hasTemplates, opt.checkConfig);
|
||||
if (readCommon) {
|
||||
result = collectConfigFiles(path, "", ".csv", files);
|
||||
result = collectConfigFiles(path, "", ".csv", &files);
|
||||
if (result == RESULT_OK && !files.empty()) {
|
||||
for (const auto& name : files) {
|
||||
string baseName = name.substr(path.length()+1, name.length()-path.length()-strlen(".csv")); // *.
|
||||
@@ -1031,7 +1031,7 @@ result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& rela
|
||||
}
|
||||
if (baseName.length() < 3 || baseName.find_first_of('.') != 2) { // different from the scheme "ZZ."
|
||||
string errorDescription;
|
||||
result = messages->readFromFile(name, errorDescription, opt.checkConfig);
|
||||
result = messages->readFromFile(name, opt.checkConfig, NULL, &errorDescription, NULL, NULL, NULL);
|
||||
if (result == RESULT_OK) {
|
||||
logNotice(lf_main, "read common config file %s", name.c_str());
|
||||
} else {
|
||||
@@ -1044,39 +1044,51 @@ result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& rela
|
||||
}
|
||||
string errorDescription;
|
||||
bestDefaults["name"] = ident;
|
||||
result = messages->readFromFile(best, errorDescription, opt.checkConfig, &bestDefaults);
|
||||
result = messages->readFromFile(best, opt.checkConfig, &bestDefaults, &errorDescription, NULL, NULL, NULL);
|
||||
if (result != RESULT_OK) {
|
||||
logError(lf_main, "error reading scan config file %s for ID \"%s\", SW%4.4d, HW%4.4d: %s", best.c_str(),
|
||||
ident.c_str(), sw, hw, getResultCode(result));
|
||||
logError(lf_main, "error reading scan config file %s for ID \"%s\", SW%4.4d, HW%4.4d: %s, %s", best.c_str(),
|
||||
ident.c_str(), sw, hw, getResultCode(result), errorDescription.c_str());
|
||||
return result;
|
||||
}
|
||||
logNotice(lf_main, "read scan config file %s for ID \"%s\", SW%4.4d, HW%4.4d", best.c_str(), ident.c_str(), sw, hw);
|
||||
relativeFile = best.substr(strlen(opt.configPath)+1);
|
||||
*relativeFile = best.substr(strlen(opt.configPath)+1);
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
bool parseMessage(const string& arg, MasterSymbolString& master, SlaveSymbolString& slave, bool onlyMasterSlave) {
|
||||
/**
|
||||
* Helper method for parsing a master/slave message pair from a command line argument.
|
||||
* @param arg the argument to parse.
|
||||
* @param onlyMasterSlave true to parse only a MS message, false to also parse MM and BC message.
|
||||
* @param master the @a MasterSymbolString to parse into.
|
||||
* @param slave the @a SlaveSymbolString to parse into.
|
||||
* @return true when the argument was valid, false otherwise.
|
||||
*/
|
||||
bool parseMessage(const string& arg, bool onlyMasterSlave, MasterSymbolString* master, SlaveSymbolString* slave) {
|
||||
size_t pos = arg.find_first_of('/');
|
||||
if (pos == string::npos) {
|
||||
logError(lf_main, "invalid message %s: missing \"/\"", arg.c_str());
|
||||
return false;
|
||||
}
|
||||
result_t result = master.parseHex(arg.substr(0, pos));
|
||||
result_t result = master->parseHex(arg.substr(0, pos));
|
||||
if (result == RESULT_OK) {
|
||||
result = slave.parseHex(arg.substr(pos+1));
|
||||
result = slave->parseHex(arg.substr(pos+1));
|
||||
}
|
||||
if (result != RESULT_OK) {
|
||||
logError(lf_main, "invalid message %s: %s", arg.c_str(), getResultCode(result));
|
||||
return false;
|
||||
}
|
||||
if (master.size() < 5) { // skip QQ ZZ PB SB NN
|
||||
if (master->size() < 5) { // skip QQ ZZ PB SB NN
|
||||
logError(lf_main, "invalid message %s: master part too short", arg.c_str());
|
||||
return false;
|
||||
}
|
||||
if (!isMaster(master[0])) {
|
||||
if (!isMaster((*master)[0])) {
|
||||
logError(lf_main, "invalid message %s: QQ is no master", arg.c_str());
|
||||
return false;
|
||||
}
|
||||
if (!isValidAddress((*master)[1], !onlyMasterSlave) || (onlyMasterSlave && isMaster((*master)[1]))) {
|
||||
logError(lf_main, "invalid message %s: ZZ is invalid", arg.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1114,7 +1126,7 @@ int main(int argc, char* argv[]) {
|
||||
SlaveSymbolString slave;
|
||||
while (result == RESULT_OK && opt.scanConfig && arg_index < argc) {
|
||||
// check scan config for each passed ident message
|
||||
if (!parseMessage(argv[arg_index++], master, slave, true)) {
|
||||
if (!parseMessage(argv[arg_index++], true, &master, &slave)) {
|
||||
continue;
|
||||
}
|
||||
symbol_t address = master[1];
|
||||
@@ -1124,7 +1136,7 @@ int main(int argc, char* argv[]) {
|
||||
} else {
|
||||
message->storeLastData(master, slave);
|
||||
string file;
|
||||
result_t res = loadScanConfigFile(s_messageMap, address, file, true);
|
||||
result_t res = loadScanConfigFile(s_messageMap, address, true, &file);
|
||||
executeInstructions(s_messageMap, true);
|
||||
if (res == RESULT_OK) {
|
||||
logInfo(lf_main, "scan config %2.2x: file %s loaded", address, file.c_str());
|
||||
@@ -1133,7 +1145,7 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
if (result == RESULT_OK && opt.dumpConfig) {
|
||||
logNotice(lf_main, "configuration dump:");
|
||||
s_messageMap->dump(cout, true);
|
||||
s_messageMap->dump(true, &cout);
|
||||
}
|
||||
shutdown();
|
||||
return 0;
|
||||
@@ -1170,7 +1182,7 @@ int main(int argc, char* argv[]) {
|
||||
SlaveSymbolString slave;
|
||||
while (arg_index < argc) {
|
||||
// add each passed message
|
||||
if (!parseMessage(argv[arg_index++], master, slave, false)) {
|
||||
if (!parseMessage(argv[arg_index++], false, &master, &slave)) {
|
||||
continue;
|
||||
}
|
||||
busHandler->injectMessage(master, slave);
|
||||
|
||||
+3
-3
@@ -89,7 +89,7 @@ struct options {
|
||||
* @param filename the full name of the configuration file.
|
||||
* @return the @a DataFieldTemplates.
|
||||
*/
|
||||
DataFieldTemplates* getTemplates(const string filename);
|
||||
DataFieldTemplates* getTemplates(const string& filename);
|
||||
|
||||
/**
|
||||
* Load the message definitions from configuration files.
|
||||
@@ -106,11 +106,11 @@ result_t loadConfigFiles(MessageMap* messages, bool verbose = false, bool denyRe
|
||||
* @param address the address of the scan participant
|
||||
* (either master for broadcast master data or slave for read slave data).
|
||||
* @param data the scan @a SlaveSymbolString for which to load the configuration file.
|
||||
* @param relativeFile the string in which the name of the configuration file is stored on success.
|
||||
* @param verbose whether to verbosely log problems.
|
||||
* @param relativeFile the string in which the name of the configuration file is stored on success.
|
||||
* @return the result code.
|
||||
*/
|
||||
result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& relativeFile, bool verbose = false);
|
||||
result_t loadScanConfigFile(MessageMap* messages, symbol_t address, bool verbose, string* relativeFile);
|
||||
|
||||
/**
|
||||
* Helper method for executing all loaded and resolvable instructions.
|
||||
|
||||
+136
-132
@@ -41,26 +41,26 @@ using std::ifstream;
|
||||
#define RECONNECT_MISSING_SIGNAL 60
|
||||
|
||||
|
||||
result_t UserList::getFieldMap(vector<string>& row, string& errorDescription, const string preferLanguage) const {
|
||||
result_t UserList::getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const {
|
||||
// name,secret,level[,level]*
|
||||
if (row.empty()) {
|
||||
row.push_back("name");
|
||||
row.push_back("secret");
|
||||
row.push_back("*level");
|
||||
if (row->empty()) {
|
||||
row->push_back("name");
|
||||
row->push_back("secret");
|
||||
row->push_back("*level");
|
||||
return RESULT_OK;
|
||||
}
|
||||
map<string, string> seen;
|
||||
for (auto& name : row) {
|
||||
tolower(name);
|
||||
for (auto& name : *row) {
|
||||
tolower(&name);
|
||||
if (name == "name" || name == "secret") {
|
||||
if (seen.find(name) != seen.end()) {
|
||||
errorDescription = "duplicate field " + name;
|
||||
*errorDescription = "duplicate field " + name;
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
} else if (name == "level") {
|
||||
name = "*level";
|
||||
} else {
|
||||
errorDescription = "unknown field " + name;
|
||||
*errorDescription = "unknown field " + name;
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
seen[name] = name;
|
||||
@@ -71,10 +71,10 @@ result_t UserList::getFieldMap(vector<string>& row, string& errorDescription, co
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t UserList::addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
|
||||
string& errorDescription, const string filename, unsigned int lineNo) {
|
||||
string name = row["name"];
|
||||
string secret = row["secret"];
|
||||
result_t UserList::addFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
|
||||
vector< map<string, string> >* subRows, string* errorDescription) {
|
||||
string name = (*row)["name"];
|
||||
string secret = (*row)["secret"];
|
||||
if (name.empty()) {
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
@@ -82,7 +82,7 @@ result_t UserList::addFromFile(map<string, string>& row, vector< map<string, str
|
||||
name = ""; // default levels
|
||||
}
|
||||
string levels;
|
||||
for (const auto& entry : subRows) {
|
||||
for (const auto& entry : *subRows) {
|
||||
const auto it = entry.find("level");
|
||||
if (it != entry.end() && !it->second.empty()) {
|
||||
if (!levels.empty()) {
|
||||
@@ -97,10 +97,10 @@ result_t UserList::addFromFile(map<string, string>& row, vector< map<string, str
|
||||
}
|
||||
|
||||
|
||||
MainLoop::MainLoop(const struct options opt, Device *device, MessageMap* messages)
|
||||
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),
|
||||
m_polling(opt.pollInterval>0), m_enableHex(opt.enableHex), m_shutdown(false) {
|
||||
m_polling(opt.pollInterval > 0), m_enableHex(opt.enableHex), m_shutdown(false) {
|
||||
// open Device
|
||||
result_t result = m_device->open();
|
||||
if (result != RESULT_OK) {
|
||||
@@ -125,7 +125,7 @@ MainLoop::MainLoop(const struct options opt, Device *device, MessageMap* message
|
||||
m_logRawLastSymbol = SYN;
|
||||
if (opt.aclFile[0]) {
|
||||
string errorDescription;
|
||||
result_t result = m_userList.readFromFile(opt.aclFile, errorDescription);
|
||||
result_t result = m_userList.readFromFile(opt.aclFile, false, NULL, &errorDescription, NULL, NULL, NULL);
|
||||
if (result != RESULT_OK) {
|
||||
logError(lf_main, "error reading ACL file \"%s\": %s", opt.aclFile, getResultCode(result));
|
||||
}
|
||||
@@ -149,7 +149,7 @@ MainLoop::MainLoop(const struct options opt, Device *device, MessageMap* message
|
||||
m_htmlPath = opt.htmlPath;
|
||||
m_network = new Network(opt.localOnly, opt.port, opt.httpPort, &m_netQueue);
|
||||
m_network->start("network");
|
||||
if (!datahandler_register(&m_userList, m_busHandler, messages, m_dataHandlers)) {
|
||||
if (!datahandler_register(&m_userList, m_busHandler, messages, &m_dataHandlers)) {
|
||||
logError(lf_main, "error registering data handlers");
|
||||
}
|
||||
}
|
||||
@@ -247,9 +247,9 @@ void MainLoop::run() {
|
||||
MasterSymbolString master;
|
||||
SlaveSymbolString slave;
|
||||
istringstream input;
|
||||
result = message->prepareMaster(m_address, master, input);
|
||||
result = message->prepareMaster(0, m_address, SYN, UI_FIELD_SEPARATOR, &input, &master);
|
||||
if (result == RESULT_OK) {
|
||||
result = m_busHandler->sendAndWait(master, slave);
|
||||
result = m_busHandler->sendAndWait(master, &slave);
|
||||
}
|
||||
} else {
|
||||
result = RESULT_ERR_NOTFOUND;
|
||||
@@ -259,7 +259,7 @@ void MainLoop::run() {
|
||||
result = m_busHandler->scanAndWait(m_initialScan, true);
|
||||
if (result == RESULT_OK) {
|
||||
ostringstream ret;
|
||||
if (m_busHandler->formatScanResult(m_initialScan, ret, false)) {
|
||||
if (m_busHandler->formatScanResult(m_initialScan, false, &ret)) {
|
||||
logNotice(lf_main, "initial scan result: %s", ret.str().c_str());
|
||||
}
|
||||
}
|
||||
@@ -301,37 +301,37 @@ void MainLoop::run() {
|
||||
if (socket) {
|
||||
socket->setTimeout(5);
|
||||
ostringstream ostr;
|
||||
ostr << "{\"v\":\"" << PACKAGE_VERSION "\"";
|
||||
ostr << ",\"r\":\"" << REVISION << "\"";
|
||||
ostr << "{\"v\":\"" << PACKAGE_VERSION "\""
|
||||
<< ",\"r\":\"" << REVISION << "\""
|
||||
#if defined(__amd64__) || defined(__x86_64__) || defined(__ia64__) || defined(__IA64__)
|
||||
ostr << ",\"a\":\"amd64\"";
|
||||
<< ",\"a\":\"amd64\""
|
||||
#elif defined(__aarch64__)
|
||||
ostr << ",\"a\":\"aarch64\"";
|
||||
<< ",\"a\":\"aarch64\""
|
||||
#elif defined(__arm__)
|
||||
ostr << ",\"a\":\"arm\"";
|
||||
<< ",\"a\":\"arm\""
|
||||
#elif defined(__i386__) || defined(__i686__)
|
||||
ostr << ",\"a\":\"i386\"";
|
||||
<< ",\"a\":\"i386\""
|
||||
#elif defined(__mips__)
|
||||
ostr << ",\"a\":\"mips\"";
|
||||
<< ",\"a\":\"mips\""
|
||||
#else
|
||||
ostr << ",\"a\":\"other\"";
|
||||
<< ",\"a\":\"other\""
|
||||
#endif
|
||||
ostr << ",\"u\":" << (now-start);
|
||||
<< ",\"u\":" << (now-start);
|
||||
if (m_reconnectCount) {
|
||||
ostr << ",\"rc\":" << m_reconnectCount;
|
||||
}
|
||||
m_busHandler->formatUpdateInfo(ostr);
|
||||
m_busHandler->formatUpdateInfo(&ostr);
|
||||
ostr << "}";
|
||||
string str = ostr.str();
|
||||
ostr.clear();
|
||||
ostr.str("");
|
||||
ostr << "POST /updatecheck/ HTTP/1.0\r\n";
|
||||
ostr << "Host: ebusd.eu" << "\r\n";
|
||||
ostr << "User-Agent: " << PACKAGE_NAME << "/" << PACKAGE_VERSION << "\r\n";
|
||||
ostr << "Content-Type: application/json; charset=utf-8\r\n";
|
||||
ostr << "Content-Length: " << dec << str.length() << "\r\n";
|
||||
ostr << "\r\n";
|
||||
ostr << str;
|
||||
ostr << "POST /updatecheck/ HTTP/1.0\r\n"
|
||||
<< "Host: ebusd.eu" << "\r\n"
|
||||
<< "User-Agent: " << PACKAGE_NAME << "/" << PACKAGE_VERSION << "\r\n"
|
||||
<< "Content-Type: application/json; charset=utf-8\r\n"
|
||||
<< "Content-Length: " << dec << str.length() << "\r\n"
|
||||
<< "\r\n"
|
||||
<< str;
|
||||
str = ostr.str();
|
||||
const char* cstr = str.c_str();
|
||||
size_t len = str.size();
|
||||
@@ -417,7 +417,7 @@ void MainLoop::run() {
|
||||
bool connected = true;
|
||||
if (request.length() > 0) {
|
||||
logDebug(lf_main, ">>> %s", request.c_str());
|
||||
ostream << decodeMessage(request, netMessage->isHttp(), connected, listening, user, reload);
|
||||
ostream << decodeMessage(request, netMessage->isHttp(), &connected, &listening, &user, &reload);
|
||||
|
||||
if (ostream.tellp() == 0 && !netMessage->isHttp()) {
|
||||
ostream << getResultCode(RESULT_EMPTY);
|
||||
@@ -438,7 +438,7 @@ void MainLoop::run() {
|
||||
messages = m_messages->findAll("", "", levels, false, true, true, true, true, true, since, now);
|
||||
for (const auto message : messages) {
|
||||
ostream << message->getCircuit() << " " << message->getName() << " = " << dec;
|
||||
message->decodeLastData(ostream);
|
||||
message->decodeLastData(false, NULL, -1, 0, &ostream);
|
||||
ostream << endl;
|
||||
}
|
||||
}
|
||||
@@ -447,7 +447,7 @@ void MainLoop::run() {
|
||||
}
|
||||
}
|
||||
|
||||
void MainLoop::notifyDeviceData(const symbol_t symbol, bool received) {
|
||||
void MainLoop::notifyDeviceData(symbol_t symbol, bool received) {
|
||||
if (received && m_dumpFile) {
|
||||
m_dumpFile->write((unsigned char*)&symbol, 1);
|
||||
}
|
||||
@@ -488,8 +488,8 @@ void MainLoop::notifyDeviceData(const symbol_t symbol, bool received) {
|
||||
}
|
||||
}
|
||||
|
||||
string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& connected, bool& listening,
|
||||
string& user, bool& reload) {
|
||||
string MainLoop::decodeMessage(const string &data, bool isHttp, bool* connected, bool* listening,
|
||||
string* user, bool* reload) {
|
||||
string token, previous;
|
||||
istringstream stream(data);
|
||||
vector<string> args;
|
||||
@@ -528,7 +528,7 @@ string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& conn
|
||||
if (strcmp(str, "GET") == 0) {
|
||||
return executeGet(args, connected);
|
||||
}
|
||||
connected = false;
|
||||
*connected = false;
|
||||
return "HTTP/1.0 405 Method Not Allowed\r\n\r\n";
|
||||
}
|
||||
|
||||
@@ -553,10 +553,10 @@ string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& conn
|
||||
return executeAuth(args, user);
|
||||
}
|
||||
if (cmd == "R" || cmd == "READ") {
|
||||
return executeRead(args, getUserLevels(user));
|
||||
return executeRead(args, getUserLevels(*user));
|
||||
}
|
||||
if (cmd == "W" || cmd == "WRITE") {
|
||||
return executeWrite(args, getUserLevels(user));
|
||||
return executeWrite(args, getUserLevels(*user));
|
||||
}
|
||||
if (cmd == "HEX") {
|
||||
if (m_enableHex) {
|
||||
@@ -565,7 +565,7 @@ string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& conn
|
||||
return "ERR: command not enabled";
|
||||
}
|
||||
if (cmd == "F" || cmd == "FIND") {
|
||||
return executeFind(args, getUserLevels(user));
|
||||
return executeFind(args, getUserLevels(*user));
|
||||
}
|
||||
if (cmd == "L" || cmd == "LISTEN") {
|
||||
return executeListen(args, listening);
|
||||
@@ -577,7 +577,7 @@ string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& conn
|
||||
return executeGrab(args);
|
||||
}
|
||||
if (cmd == "SCAN") {
|
||||
return executeScan(args, getUserLevels(user));
|
||||
return executeScan(args, getUserLevels(*user));
|
||||
}
|
||||
if (cmd == "LOG") {
|
||||
return executeLog(args);
|
||||
@@ -589,14 +589,14 @@ string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& conn
|
||||
return executeDump(args);
|
||||
}
|
||||
if (cmd == "RELOAD") {
|
||||
reload = true;
|
||||
*reload = true;
|
||||
return executeReload(args);
|
||||
}
|
||||
if (cmd == "Q" || cmd == "QUIT") {
|
||||
return executeQuit(args, connected);
|
||||
}
|
||||
if (cmd == "I" || cmd == "INFO") {
|
||||
return executeInfo(args, user);
|
||||
return executeInfo(args, *user);
|
||||
}
|
||||
if (cmd == "?" || cmd == "H" || cmd == "HELP") {
|
||||
return executeHelp();
|
||||
@@ -604,8 +604,8 @@ string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& conn
|
||||
return "ERR: command not found";
|
||||
}
|
||||
|
||||
result_t MainLoop::parseHexMaster(vector<string> &args, size_t argPos, MasterSymbolString& master,
|
||||
symbol_t srcAddress) {
|
||||
result_t MainLoop::parseHexMaster(const vector<string>& args, size_t argPos, symbol_t srcAddress,
|
||||
MasterSymbolString* master) {
|
||||
ostringstream msg;
|
||||
while (argPos < args.size()) {
|
||||
if ((args[argPos].length() % 2) != 0) {
|
||||
@@ -617,22 +617,22 @@ result_t MainLoop::parseHexMaster(vector<string> &args, size_t argPos, MasterSym
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
result_t ret;
|
||||
unsigned int length = parseInt(msg.str().substr(3*2, 2).c_str(), 16, 0, MAX_POS, ret);
|
||||
unsigned int length = parseInt(msg.str().substr(3*2, 2).c_str(), 16, 0, MAX_POS, &ret);
|
||||
if (ret != RESULT_OK) {
|
||||
return ret;
|
||||
}
|
||||
if ((4+length)*2 != msg.str().size()) {
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
master.push_back(srcAddress == SYN ? m_address : srcAddress);
|
||||
ret = master.parseHex(msg.str());
|
||||
if (ret == RESULT_OK && !isValidAddress(master[1])) {
|
||||
master->push_back(srcAddress == SYN ? m_address : srcAddress);
|
||||
ret = master->parseHex(msg.str());
|
||||
if (ret == RESULT_OK && !isValidAddress((*master)[1])) {
|
||||
ret = RESULT_ERR_INVALID_ADDR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
string MainLoop::executeAuth(vector<string> &args, string &user) {
|
||||
string MainLoop::executeAuth(const vector<string>& args, string *user) {
|
||||
if (args.size() != 3) {
|
||||
return "usage: auth USER SECRET\n"
|
||||
" Authenticate with USER name and SECRET.\n"
|
||||
@@ -640,13 +640,13 @@ string MainLoop::executeAuth(vector<string> &args, string &user) {
|
||||
" SECRET the secret string of the user";
|
||||
}
|
||||
if (m_userList.checkSecret(args[1], args[2])) {
|
||||
user = args[1];
|
||||
*user = args[1];
|
||||
return getResultCode(RESULT_OK);
|
||||
}
|
||||
return "ERR: invalid user name or secret";
|
||||
}
|
||||
|
||||
string MainLoop::executeRead(vector<string> &args, const string levels) {
|
||||
string MainLoop::executeRead(const vector<string>& args, const string& levels) {
|
||||
size_t argPos = 1;
|
||||
bool hex = false, numeric = false, valueName = false;
|
||||
OutputFormat verbosity = 0;
|
||||
@@ -684,7 +684,7 @@ string MainLoop::executeRead(vector<string> &args, const string levels) {
|
||||
argPos++;
|
||||
if (args.size() > argPos) {
|
||||
result_t result;
|
||||
maxAge = parseInt(args[argPos].c_str(), 10, 0, 24*60*60, result);
|
||||
maxAge = parseInt(args[argPos].c_str(), 10, 0, 24*60*60, &result);
|
||||
if (result != RESULT_OK) {
|
||||
argPos = 0; // print usage
|
||||
break;
|
||||
@@ -708,7 +708,7 @@ string MainLoop::executeRead(vector<string> &args, const string levels) {
|
||||
}
|
||||
bool dest = args[argPos] == "-d";
|
||||
result_t ret;
|
||||
symbol_t address = (symbol_t)parseInt(args[argPos].c_str(), 16, 0, 0xff, ret);
|
||||
symbol_t address = (symbol_t)parseInt(args[argPos].c_str(), 16, 0, 0xff, &ret);
|
||||
if (ret != RESULT_OK || !isValidAddress(address, dest) || dest == isMaster(address)) {
|
||||
return getResultCode(RESULT_ERR_INVALID_ADDR);
|
||||
}
|
||||
@@ -724,7 +724,7 @@ string MainLoop::executeRead(vector<string> &args, const string levels) {
|
||||
break;
|
||||
}
|
||||
result_t ret;
|
||||
pollPriority = (size_t)parseInt(args[argPos].c_str(), 10, 1, 9, ret);
|
||||
pollPriority = (size_t)parseInt(args[argPos].c_str(), 10, 1, 9, &ret);
|
||||
if (ret != RESULT_OK) {
|
||||
return getResultCode(RESULT_ERR_INVALID_NUM);
|
||||
}
|
||||
@@ -751,7 +751,7 @@ string MainLoop::executeRead(vector<string> &args, const string levels) {
|
||||
|
||||
if (hex && argPos > 0) {
|
||||
MasterSymbolString master;
|
||||
result_t ret = parseHexMaster(args, argPos, master, srcAddress);
|
||||
result_t ret = parseHexMaster(args, argPos, srcAddress, &master);
|
||||
if (ret != RESULT_OK) {
|
||||
return getResultCode(ret);
|
||||
}
|
||||
@@ -785,13 +785,13 @@ string MainLoop::executeRead(vector<string> &args, const string levels) {
|
||||
|
||||
// send message
|
||||
SlaveSymbolString slave;
|
||||
ret = m_busHandler->sendAndWait(master, slave);
|
||||
ret = m_busHandler->sendAndWait(master, &slave);
|
||||
|
||||
if (ret == RESULT_OK) {
|
||||
ret = message->storeLastData(master, slave);
|
||||
ostringstream result;
|
||||
if (ret == RESULT_OK) {
|
||||
ret = message->decodeLastData(result);
|
||||
ret = message->decodeLastData(false, NULL, -1, 0, &result);
|
||||
}
|
||||
if (ret >= RESULT_OK) {
|
||||
logInfo(lf_main, "read hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
@@ -839,7 +839,7 @@ string MainLoop::executeRead(vector<string> &args, const string levels) {
|
||||
size_t pos = fieldName.find_last_of('.');
|
||||
if (pos != string::npos) {
|
||||
result_t result = RESULT_OK;
|
||||
fieldIndex = static_cast<ssize_t>(parseInt(fieldName.substr(pos+1).c_str(), 10, 0, MAX_POS, result));
|
||||
fieldIndex = static_cast<ssize_t>(parseInt(fieldName.substr(pos+1).c_str(), 10, 0, MAX_POS, &result));
|
||||
if (result == RESULT_OK) {
|
||||
fieldName = fieldName.substr(0, pos);
|
||||
}
|
||||
@@ -850,7 +850,7 @@ string MainLoop::executeRead(vector<string> &args, const string levels) {
|
||||
Message* message = m_messages->find(circuit, args[argPos], levels, false);
|
||||
// adjust poll priority
|
||||
if (message != NULL && pollPriority > 0 && message->setPollPriority(pollPriority)) {
|
||||
m_messages->addPollMessage(message);
|
||||
m_messages->addPollMessage(false, message);
|
||||
}
|
||||
verbosity |= valueName ? OF_VALUENAME : numeric ? OF_NUMERIC : 0;
|
||||
result_t ret;
|
||||
@@ -866,8 +866,8 @@ string MainLoop::executeRead(vector<string> &args, const string levels) {
|
||||
if (verbosity & OF_NAMES) {
|
||||
result << cacheMessage->getCircuit() << " " << cacheMessage->getName() << " ";
|
||||
}
|
||||
ret = cacheMessage->decodeLastData(result, verbosity, false, fieldIndex == -2 ? NULL : fieldName.c_str(),
|
||||
fieldIndex);
|
||||
ret = cacheMessage->decodeLastData(false, fieldIndex == -2 ? NULL : fieldName.c_str(), fieldIndex, verbosity,
|
||||
&result);
|
||||
if (ret != RESULT_OK) {
|
||||
if (ret < RESULT_OK) {
|
||||
logError(lf_main, "read %s %s cached: %s", cacheMessage->getCircuit().c_str(),
|
||||
@@ -899,8 +899,8 @@ string MainLoop::executeRead(vector<string> &args, const string levels) {
|
||||
if (verbosity & OF_NAMES) {
|
||||
result << message->getCircuit() << " " << message->getName() << " ";
|
||||
}
|
||||
ret = message->decodeLastSlaveData(result, verbosity, false, fieldIndex == -2 ? NULL : fieldName.c_str(),
|
||||
fieldIndex);
|
||||
ret = message->decodeLastData(false, false, fieldIndex == -2 ? NULL : fieldName.c_str(), fieldIndex, verbosity,
|
||||
&result);
|
||||
if (ret < RESULT_OK) {
|
||||
logError(lf_main, "read %s %s: decode %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
getResultCode(ret));
|
||||
@@ -915,7 +915,7 @@ string MainLoop::executeRead(vector<string> &args, const string levels) {
|
||||
return result.str();
|
||||
}
|
||||
|
||||
string MainLoop::executeWrite(vector<string> &args, const string levels) {
|
||||
string MainLoop::executeWrite(const vector<string>& args, const string levels) {
|
||||
size_t argPos = 1;
|
||||
bool hex = false;
|
||||
string circuit;
|
||||
@@ -931,7 +931,7 @@ string MainLoop::executeWrite(vector<string> &args, const string levels) {
|
||||
}
|
||||
bool dest = args[argPos] == "-d";
|
||||
result_t ret;
|
||||
symbol_t address = (symbol_t)parseInt(args[argPos].c_str(), 16, 0, 0xff, ret);
|
||||
symbol_t address = (symbol_t)parseInt(args[argPos].c_str(), 16, 0, 0xff, &ret);
|
||||
if (ret != RESULT_OK || !isValidAddress(address, dest) || dest == isMaster(address)) {
|
||||
return getResultCode(RESULT_ERR_INVALID_ADDR);
|
||||
}
|
||||
@@ -960,7 +960,7 @@ string MainLoop::executeWrite(vector<string> &args, const string levels) {
|
||||
|
||||
if (hex && argPos > 0) {
|
||||
MasterSymbolString master;
|
||||
result_t ret = parseHexMaster(args, argPos, master, srcAddress);
|
||||
result_t ret = parseHexMaster(args, argPos, srcAddress, &master);
|
||||
if (ret != RESULT_OK) {
|
||||
return getResultCode(ret);
|
||||
}
|
||||
@@ -983,14 +983,14 @@ string MainLoop::executeWrite(vector<string> &args, const string levels) {
|
||||
}
|
||||
// send message
|
||||
SlaveSymbolString slave;
|
||||
ret = m_busHandler->sendAndWait(master, slave);
|
||||
ret = m_busHandler->sendAndWait(master, &slave);
|
||||
|
||||
if (ret == RESULT_OK) {
|
||||
// also update read messages
|
||||
ret = message->storeLastData(master, slave);
|
||||
ostringstream result;
|
||||
if (ret == RESULT_OK) {
|
||||
ret = message->decodeLastData(result);
|
||||
ret = message->decodeLastData(false, NULL, -1, 0, &result);
|
||||
}
|
||||
if (ret >= RESULT_OK) {
|
||||
logInfo(lf_main, "write hex %s %s cache update: %s", message->getCircuit().c_str(),
|
||||
@@ -1054,7 +1054,7 @@ string MainLoop::executeWrite(vector<string> &args, const string levels) {
|
||||
return getResultCode(RESULT_OK);
|
||||
}
|
||||
|
||||
ret = message->decodeLastSlaveData(result); // decode data
|
||||
ret = message->decodeLastData(false, false, NULL, -1, 0, &result); // decode data
|
||||
if (ret >= RESULT_OK && result.str().empty()) {
|
||||
logNotice(lf_main, "write %s %s: decode %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
getResultCode(ret));
|
||||
@@ -1072,7 +1072,7 @@ string MainLoop::executeWrite(vector<string> &args, const string levels) {
|
||||
return result.str();
|
||||
}
|
||||
|
||||
string MainLoop::executeHex(vector<string> &args) {
|
||||
string MainLoop::executeHex(const vector<string>& args) {
|
||||
size_t argPos = 1;
|
||||
symbol_t srcAddress = SYN;
|
||||
if (args.size() > argPos && args[argPos] == "-s") {
|
||||
@@ -1081,7 +1081,7 @@ string MainLoop::executeHex(vector<string> &args) {
|
||||
argPos = 0; // print usage
|
||||
} else {
|
||||
result_t ret;
|
||||
symbol_t address = (symbol_t)parseInt(args[argPos].c_str(), 16, 0, 0xff, ret);
|
||||
symbol_t address = (symbol_t)parseInt(args[argPos].c_str(), 16, 0, 0xff, &ret);
|
||||
if (ret != RESULT_OK || !isValidAddress(address, false) || !isMaster(address)) {
|
||||
return getResultCode(RESULT_ERR_INVALID_ADDR);
|
||||
}
|
||||
@@ -1095,7 +1095,7 @@ string MainLoop::executeHex(vector<string> &args) {
|
||||
|
||||
if (argPos > 0) {
|
||||
MasterSymbolString master;
|
||||
result_t ret = parseHexMaster(args, argPos, master, srcAddress);
|
||||
result_t ret = parseHexMaster(args, argPos, srcAddress, &master);
|
||||
if (ret != RESULT_OK) {
|
||||
return getResultCode(ret);
|
||||
}
|
||||
@@ -1103,7 +1103,7 @@ string MainLoop::executeHex(vector<string> &args) {
|
||||
|
||||
// send message
|
||||
SlaveSymbolString slave;
|
||||
ret = m_busHandler->sendAndWait(master, slave);
|
||||
ret = m_busHandler->sendAndWait(master, &slave);
|
||||
|
||||
if (ret == RESULT_OK) {
|
||||
if (master[1] == BROADCAST) {
|
||||
@@ -1127,10 +1127,11 @@ string MainLoop::executeHex(vector<string> &args) {
|
||||
" Dx data byte(s) to send";
|
||||
}
|
||||
|
||||
string MainLoop::executeFind(vector<string> &args, string levels) {
|
||||
string MainLoop::executeFind(const vector<string>& args, const string& levels) {
|
||||
size_t argPos = 1;
|
||||
bool configFormat = false, exact = false, withRead = true, withWrite = false, withPassive = true, first = true,
|
||||
onlyWithData = false, hexFormat = false, userLevel = true;
|
||||
onlyWithData = false, hexFormat = false, userLevel = true, withConditions = false;
|
||||
string useLevels = levels;
|
||||
OutputFormat verbosity = 0;
|
||||
vector<string> fieldNames;
|
||||
string circuit;
|
||||
@@ -1166,7 +1167,7 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
|
||||
argPos = 0; // print usage
|
||||
break;
|
||||
}
|
||||
if (!Message::extractFieldNames(args[argPos], fieldNames)) {
|
||||
if (!Message::extractFieldNames(args[argPos], true, &fieldNames)) {
|
||||
argPos = 0; // print usage
|
||||
break;
|
||||
}
|
||||
@@ -1191,7 +1192,7 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
|
||||
}
|
||||
withPassive = true;
|
||||
} else if (args[argPos] == "-a") {
|
||||
withRead = withWrite = withPassive = true;
|
||||
withRead = withWrite = withPassive = withConditions = true;
|
||||
} else if (args[argPos] == "-d") {
|
||||
onlyWithData = true;
|
||||
} else if (args[argPos] == "-h") {
|
||||
@@ -1206,7 +1207,7 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
|
||||
argPos = 0; // print usage
|
||||
break;
|
||||
}
|
||||
result_t result = Message::parseId(args[argPos], id);
|
||||
result_t result = Message::parseId(args[argPos], &id);
|
||||
if (result != RESULT_OK) {
|
||||
return getResultCode(result);
|
||||
}
|
||||
@@ -1227,7 +1228,7 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
|
||||
argPos = 0; // print usage
|
||||
break;
|
||||
}
|
||||
levels = args[argPos];
|
||||
useLevels = args[argPos];
|
||||
userLevel = false;
|
||||
} else {
|
||||
argPos = 0; // print usage
|
||||
@@ -1244,7 +1245,7 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
|
||||
" -r limit to active read messages (default: read + passive)\n"
|
||||
" -w limit to active write messages (default: read + passive)\n"
|
||||
" -p limit to passive messages (default: read + passive)\n"
|
||||
" -a include all message types (read, passive, and write)\n"
|
||||
" -a include all message types (read, passive, and write) and all conditional\n"
|
||||
" -d only include messages with actual data\n"
|
||||
" -h show hex data instead of decoded values\n"
|
||||
" -i ID limit to messages with ID (in hex, PB, SB and further ID bytes)\n"
|
||||
@@ -1256,8 +1257,8 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
|
||||
" -l LEVEL limit to messages with access LEVEL (\"*\" for any, default: current level)\n"
|
||||
" NAME NAME of the messages to find (or a part thereof without '-e')";
|
||||
}
|
||||
deque<Message*> messages = m_messages->findAll(
|
||||
circuit, args.size() == argPos ? "" : args[argPos], levels, exact, withRead, withWrite, withPassive, userLevel);
|
||||
deque<Message*> messages = m_messages->findAll(circuit, args.size() == argPos ? "" : args[argPos], useLevels,
|
||||
exact, withRead, withWrite, withPassive, userLevel, !withConditions);
|
||||
|
||||
bool found = false;
|
||||
ostringstream result;
|
||||
@@ -1274,12 +1275,12 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
|
||||
if (found) {
|
||||
result << endl;
|
||||
}
|
||||
message->dump(result);
|
||||
message->dump(NULL, withConditions, &result);
|
||||
} else if (!fieldNames.empty()) {
|
||||
if (found) {
|
||||
result << endl;
|
||||
}
|
||||
message->dump(result, &fieldNames);
|
||||
message->dump(&fieldNames, withConditions, &result);
|
||||
} else {
|
||||
if (found) {
|
||||
result << endl;
|
||||
@@ -1287,10 +1288,13 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
|
||||
result << message->getCircuit() << " " << message->getName() << " = ";
|
||||
if (lastup == 0) {
|
||||
result << "no data stored";
|
||||
if (!message->isAvailable()) {
|
||||
result << " (message not available due to condition)";
|
||||
}
|
||||
} else if (hexFormat) {
|
||||
result << message->getLastMasterData().getStr() << " / " << message->getLastSlaveData().getStr();
|
||||
} else {
|
||||
result_t ret = message->decodeLastData(result, verbosity);
|
||||
result_t ret = message->decodeLastData(false, NULL, -1, verbosity, &result);
|
||||
if (ret != RESULT_OK) {
|
||||
result << " (" << getResultCode(ret)
|
||||
<< " for " << message->getLastMasterData().getStr()
|
||||
@@ -1335,12 +1339,12 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
|
||||
return result.str();
|
||||
}
|
||||
|
||||
string MainLoop::executeListen(vector<string> &args, bool& listening) {
|
||||
string MainLoop::executeListen(const vector<string>& args, bool* listening) {
|
||||
if (args.size() == 1) {
|
||||
if (listening) {
|
||||
return "listen continued";
|
||||
}
|
||||
listening = true;
|
||||
*listening = true;
|
||||
return "listen started";
|
||||
}
|
||||
|
||||
@@ -1348,11 +1352,11 @@ string MainLoop::executeListen(vector<string> &args, bool& listening) {
|
||||
return "usage: listen [stop]\n"
|
||||
" Listen for updates or stop it.";
|
||||
}
|
||||
listening = false;
|
||||
*listening = false;
|
||||
return "listen stopped";
|
||||
}
|
||||
|
||||
string MainLoop::executeState(vector<string> &args) {
|
||||
string MainLoop::executeState(const vector<string>& args) {
|
||||
if (args.size() == 0) {
|
||||
return "usage: state\n"
|
||||
" Report bus state.";
|
||||
@@ -1368,7 +1372,7 @@ string MainLoop::executeState(vector<string> &args) {
|
||||
return "no signal";
|
||||
}
|
||||
|
||||
string MainLoop::executeGrab(vector<string> &args) {
|
||||
string MainLoop::executeGrab(const vector<string>& args) {
|
||||
if (args.size() == 1) {
|
||||
return m_busHandler->enableGrab(true) ? "grab started" : "grab continued";
|
||||
}
|
||||
@@ -1378,12 +1382,12 @@ string MainLoop::executeGrab(vector<string> &args) {
|
||||
if (args.size() >= 2 && args[1] == "result") {
|
||||
if (args.size() == 2 || args[2] == "all") {
|
||||
ostringstream result;
|
||||
m_busHandler->formatGrabResult(args.size() == 2, result);
|
||||
m_busHandler->formatGrabResult(args.size() == 2, false, &result);
|
||||
return result.str();
|
||||
}
|
||||
if (args.size() == 3 || args[2] == "decode") {
|
||||
ostringstream result;
|
||||
m_busHandler->formatGrabResult(true, result, true);
|
||||
m_busHandler->formatGrabResult(true, true, &result);
|
||||
return result.str();
|
||||
}
|
||||
}
|
||||
@@ -1392,7 +1396,7 @@ string MainLoop::executeGrab(vector<string> &args) {
|
||||
" Start or stop grabbing, or report/decode unknown or all grabbed messages.";
|
||||
}
|
||||
|
||||
string MainLoop::executeScan(vector<string> &args, string levels) {
|
||||
string MainLoop::executeScan(const vector<string>& args, string levels) {
|
||||
if (args.size() == 1) {
|
||||
result_t result = m_busHandler->startScan(false, levels);
|
||||
if (result == RESULT_ERR_DUPLICATE) {
|
||||
@@ -1415,12 +1419,12 @@ string MainLoop::executeScan(vector<string> &args, string levels) {
|
||||
|
||||
if (args[1] == "result") {
|
||||
ostringstream ret;
|
||||
m_busHandler->formatScanResult(ret);
|
||||
m_busHandler->formatScanResult(&ret);
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
result_t result;
|
||||
symbol_t dstAddress = (symbol_t)parseInt(args[1].c_str(), 16, 0, 0xff, result);
|
||||
symbol_t dstAddress = (symbol_t)parseInt(args[1].c_str(), 16, 0, 0xff, &result);
|
||||
if (result == RESULT_OK && !isValidAddress(dstAddress, false)) {
|
||||
result = RESULT_ERR_INVALID_ADDR;
|
||||
}
|
||||
@@ -1432,7 +1436,7 @@ string MainLoop::executeScan(vector<string> &args, string levels) {
|
||||
return getResultCode(result);
|
||||
}
|
||||
ostringstream ret;
|
||||
if (!m_busHandler->formatScanResult(dstAddress, ret, false)) {
|
||||
if (!m_busHandler->formatScanResult(dstAddress, false, &ret)) {
|
||||
return getResultCode(RESULT_EMPTY);
|
||||
}
|
||||
return ret.str();
|
||||
@@ -1443,7 +1447,7 @@ string MainLoop::executeScan(vector<string> &args, string levels) {
|
||||
" Scan seen slaves, all slaves (full), a single slave (address ZZ), or report scan result.";
|
||||
}
|
||||
|
||||
string MainLoop::executeLog(vector<string> &args) {
|
||||
string MainLoop::executeLog(const vector<string>& args) {
|
||||
if (args.size() == 1) {
|
||||
ostringstream ret;
|
||||
for (int val = 0; val < lf_COUNT; val++) {
|
||||
@@ -1469,7 +1473,7 @@ string MainLoop::executeLog(vector<string> &args) {
|
||||
return getResultCode(RESULT_ERR_INVALID_ARG);
|
||||
}
|
||||
|
||||
string MainLoop::executeRaw(vector<string> &args) {
|
||||
string MainLoop::executeRaw(const vector<string>& args) {
|
||||
bool bytes = args.size() == 2 && args[1] == "bytes";
|
||||
if (args.size() != 1 && !bytes) {
|
||||
return "usage: raw [bytes]\n"
|
||||
@@ -1487,7 +1491,7 @@ string MainLoop::executeRaw(vector<string> &args) {
|
||||
return enabled ? "raw logging enabled" : "raw logging disabled";
|
||||
}
|
||||
|
||||
string MainLoop::executeDump(vector<string> &args) {
|
||||
string MainLoop::executeDump(const vector<string>& args) {
|
||||
if (args.size() != 1) {
|
||||
return "usage: dump\n"
|
||||
" Toggle binary dump of received bytes.";
|
||||
@@ -1500,7 +1504,7 @@ string MainLoop::executeDump(vector<string> &args) {
|
||||
return enabled ? "dump enabled" : "dump disabled";
|
||||
}
|
||||
|
||||
string MainLoop::executeReload(vector<string> &args) {
|
||||
string MainLoop::executeReload(const vector<string>& args) {
|
||||
if (args.size() != 1) {
|
||||
return "usage: reload\n"
|
||||
" Reload CSV config files.";
|
||||
@@ -1510,7 +1514,7 @@ string MainLoop::executeReload(vector<string> &args) {
|
||||
return getResultCode(result);
|
||||
}
|
||||
|
||||
string MainLoop::executeInfo(vector<string> &args, const string user) {
|
||||
string MainLoop::executeInfo(const vector<string>& args, const string& user) {
|
||||
if (args.size() == 0) {
|
||||
return "usage: info\n"
|
||||
" Report information about the daemon, the configuration, and seen devices.";
|
||||
@@ -1528,25 +1532,25 @@ string MainLoop::executeInfo(vector<string> &args, const string user) {
|
||||
result << "access: " << levels << "\n";
|
||||
}
|
||||
if (m_busHandler->hasSignal()) {
|
||||
result << "signal: acquired\n";
|
||||
result << "symbol rate: " << m_busHandler->getSymbolRate() << "\n";
|
||||
result << "max symbol rate: " << m_busHandler->getMaxSymbolRate() << "\n";
|
||||
result << "signal: acquired\n"
|
||||
<< "symbol rate: " << m_busHandler->getSymbolRate() << "\n"
|
||||
<< "max symbol rate: " << m_busHandler->getMaxSymbolRate() << "\n";
|
||||
} else {
|
||||
result << "signal: no signal\n";
|
||||
}
|
||||
result << "reconnects: " << m_reconnectCount << "\n";
|
||||
result << "masters: " << m_busHandler->getMasterCount() << "\n";
|
||||
result << "messages: " << m_messages->size() << "\n";
|
||||
result << "conditional: " << m_messages->sizeConditional() << "\n";
|
||||
result << "poll: " << m_messages->sizePoll() << "\n";
|
||||
result << "update: " << m_messages->sizePassive();
|
||||
m_busHandler->formatSeenInfo(result);
|
||||
result << "reconnects: " << m_reconnectCount << "\n"
|
||||
<< "masters: " << m_busHandler->getMasterCount() << "\n"
|
||||
<< "messages: " << m_messages->size() << "\n"
|
||||
<< "conditional: " << m_messages->sizeConditional() << "\n"
|
||||
<< "poll: " << m_messages->sizePoll() << "\n"
|
||||
<< "update: " << m_messages->sizePassive();
|
||||
m_busHandler->formatSeenInfo(&result);
|
||||
return result.str();
|
||||
}
|
||||
|
||||
string MainLoop::executeQuit(vector<string> &args, bool& connected) {
|
||||
string MainLoop::executeQuit(const vector<string>& args, bool *connected) {
|
||||
if (args.size() == 1) {
|
||||
connected = false;
|
||||
*connected = false;
|
||||
return "connection closed";
|
||||
}
|
||||
return "usage: quit\n"
|
||||
@@ -1579,7 +1583,7 @@ string MainLoop::executeHelp() {
|
||||
" help|? Print help help [COMMAND], COMMMAND ?";
|
||||
}
|
||||
|
||||
string MainLoop::executeGet(vector<string> &args, bool& connected) {
|
||||
string MainLoop::executeGet(const vector<string>& args, bool* connected) {
|
||||
result_t ret = RESULT_OK;
|
||||
bool numeric = false, valueName = false, required = false, full = false;
|
||||
OutputFormat verbosity = OF_NAMES;
|
||||
@@ -1616,9 +1620,9 @@ string MainLoop::executeGet(vector<string> &args, bool& connected) {
|
||||
qname = token;
|
||||
}
|
||||
if (qname == "since") {
|
||||
since = parseInt(value.c_str(), 10, 0, 0xffffffff, ret);
|
||||
since = parseInt(value.c_str(), 10, 0, 0xffffffff, &ret);
|
||||
} else if (qname == "poll") {
|
||||
pollPriority = (size_t)parseInt(value.c_str(), 10, 1, 9, ret);
|
||||
pollPriority = (size_t)parseInt(value.c_str(), 10, 1, 9, &ret);
|
||||
} else if (qname == "exact") {
|
||||
exact = value.length() == 0 || value == "1" || value == "true";
|
||||
} else if (qname == "verbose") {
|
||||
@@ -1664,7 +1668,7 @@ string MainLoop::executeGet(vector<string> &args, bool& connected) {
|
||||
continue;
|
||||
}
|
||||
if (pollPriority > 0 && message->setPollPriority(pollPriority)) {
|
||||
m_messages->addPollMessage(message);
|
||||
m_messages->addPollMessage(false, message);
|
||||
}
|
||||
time_t lastup = message->getLastUpdateTime();
|
||||
if (lastup == 0 && required) {
|
||||
@@ -1691,11 +1695,11 @@ string MainLoop::executeGet(vector<string> &args, bool& connected) {
|
||||
lastCircuit = message->getCircuit();
|
||||
result << "\n \"" << lastCircuit << "\": {";
|
||||
first = true;
|
||||
if (full && m_messages->decodeCircuit(lastCircuit, result, verbosity)) { // add circuit specific values
|
||||
if (full && m_messages->decodeCircuit(lastCircuit, verbosity, &result)) { // add circuit specific values
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
message->decode(result, verbosity, !first);
|
||||
message->decode(!first, NULL, verbosity, &result);
|
||||
first = false;
|
||||
}
|
||||
|
||||
@@ -1727,8 +1731,8 @@ string MainLoop::executeGet(vector<string> &args, bool& connected) {
|
||||
result << "\n}";
|
||||
type = 6;
|
||||
}
|
||||
connected = false;
|
||||
return formatHttpResult(ret, result, type);
|
||||
*connected = false;
|
||||
return formatHttpResult(ret, type, result);
|
||||
} // request for "/data..."
|
||||
|
||||
if (uri.length() < 1 || uri[0] != '/' || uri.find("//") != string::npos || uri.find("..") != string::npos) {
|
||||
@@ -1770,11 +1774,11 @@ string MainLoop::executeGet(vector<string> &args, bool& connected) {
|
||||
}
|
||||
}
|
||||
}
|
||||
connected = false;
|
||||
return formatHttpResult(ret, result, type);
|
||||
*connected = false;
|
||||
return formatHttpResult(ret, type, result);
|
||||
}
|
||||
|
||||
string MainLoop::formatHttpResult(result_t ret, ostringstream& result, int type) {
|
||||
string MainLoop::formatHttpResult(result_t ret, int type, ostringstream &result) {
|
||||
string data = ret == RESULT_OK ? result.str() : "";
|
||||
result.str("");
|
||||
result.clear();
|
||||
|
||||
+33
-33
@@ -46,7 +46,7 @@ class UserList : public UserInfo, public MappedFileReader {
|
||||
* Constructor.
|
||||
* @param defaultLevels the default access levels.
|
||||
*/
|
||||
explicit UserList(const string defaultLevels) : MappedFileReader::MappedFileReader(false) {
|
||||
explicit UserList(const string& defaultLevels) : MappedFileReader::MappedFileReader(false) {
|
||||
if (!defaultLevels.empty()) {
|
||||
string levels = defaultLevels;
|
||||
transform(levels.begin(), levels.end(), levels.begin(), [](unsigned char c) {
|
||||
@@ -62,25 +62,25 @@ class UserList : public UserInfo, public MappedFileReader {
|
||||
virtual ~UserList() {}
|
||||
|
||||
// @copydoc
|
||||
result_t getFieldMap(vector<string>& row, string& errorDescription, const string preferLanguage) const override;
|
||||
result_t getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
|
||||
string& errorDescription, const string filename, unsigned int lineNo) override;
|
||||
result_t addFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
|
||||
vector< map<string, string> >* subRows, string* errorDescription) override;
|
||||
|
||||
// @copydoc
|
||||
bool hasUser(const string user) const override {
|
||||
bool hasUser(const string& user) const override {
|
||||
return m_userLevels.find(user) != m_userLevels.end();
|
||||
}
|
||||
|
||||
// @copydoc
|
||||
bool checkSecret(const string user, const string secret) const override {
|
||||
bool checkSecret(const string& user, const string& secret) const override {
|
||||
auto it = m_userSecrets.find(user);
|
||||
return it != m_userSecrets.end() && it->second == secret;
|
||||
}
|
||||
|
||||
// @copydoc
|
||||
string getLevels(const string user) const override {
|
||||
string getLevels(const string& user) const override {
|
||||
auto it = m_userLevels.find(user);
|
||||
return it == m_userLevels.end() ? "" : it->second;
|
||||
}
|
||||
@@ -105,7 +105,7 @@ class MainLoop : public Thread, DeviceListener {
|
||||
* @param device the @a Device instance.
|
||||
* @param messages the @a MessageMap instance.
|
||||
*/
|
||||
MainLoop(const struct options opt, Device *device, MessageMap* messages);
|
||||
MainLoop(const struct options& opt, Device *device, MessageMap* messages);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
@@ -130,7 +130,7 @@ class MainLoop : public Thread, DeviceListener {
|
||||
void addMessage(NetMessage* message) { m_netQueue.push(message); }
|
||||
|
||||
// @copydoc
|
||||
void notifyDeviceData(const symbol_t symbol, bool received) override;
|
||||
void notifyDeviceData(symbol_t symbol, bool received) override;
|
||||
|
||||
|
||||
protected:
|
||||
@@ -149,26 +149,26 @@ class MainLoop : public Thread, DeviceListener {
|
||||
* @param reload set to true when the configuration files were reloaded.
|
||||
* @return result string to send back to the client.
|
||||
*/
|
||||
string decodeMessage(const string& data, const bool isHttp, bool& connected, bool& listening,
|
||||
string& user, bool& reload);
|
||||
string decodeMessage(const string& data, bool isHttp, bool* connected, bool* listening,
|
||||
string* user, bool* reload);
|
||||
|
||||
/**
|
||||
* Parse the hex master message from the remaining arguments.
|
||||
* @param args the arguments passed to the command.
|
||||
* @param argPos the index of the first argument to parse.
|
||||
* @param master the @a MasterSymbolString to write the data to.
|
||||
* @param srcAddress the source address to set, or @a SYN for the own master address.
|
||||
* @param master the @a MasterSymbolString to write the data to.
|
||||
* @return the result from parsing the arguments.
|
||||
*/
|
||||
result_t parseHexMaster(vector<string> &args, size_t argPos, MasterSymbolString& master,
|
||||
symbol_t srcAddress = SYN);
|
||||
result_t parseHexMaster(const vector<string>& args, size_t argPos, symbol_t srcAddress,
|
||||
MasterSymbolString* master);
|
||||
|
||||
/**
|
||||
* Get the access levels associated with the specified user name.
|
||||
* @param user the user name, or empty for default levels.
|
||||
* @return the access levels separated by semicolon.
|
||||
*/
|
||||
string getUserLevels(const string user) { return m_userList.getLevels(user); }
|
||||
string getUserLevels(const string& user) { return m_userList.getLevels(user); }
|
||||
|
||||
/**
|
||||
* Execute the auth command.
|
||||
@@ -176,7 +176,7 @@ class MainLoop : public Thread, DeviceListener {
|
||||
* @param user the current user name to set to the new user name on success.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeAuth(vector<string> &args, string &user);
|
||||
string executeAuth(const vector<string>& args, string *user);
|
||||
|
||||
/**
|
||||
* Execute the read command.
|
||||
@@ -184,7 +184,7 @@ class MainLoop : public Thread, DeviceListener {
|
||||
* @param levels the current user's access levels.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeRead(vector<string> &args, const string levels);
|
||||
string executeRead(const vector<string>& args, const string& levels);
|
||||
|
||||
/**
|
||||
* Execute the write command.
|
||||
@@ -192,14 +192,14 @@ class MainLoop : public Thread, DeviceListener {
|
||||
* @param levels the current user's access levels.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeWrite(vector<string> &args, const string levels);
|
||||
string executeWrite(const vector<string>& args, const string levels);
|
||||
|
||||
/**
|
||||
* Execute the hex command.
|
||||
* @param args the arguments passed to the command (starting with the command itself), or empty for help.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeHex(vector<string> &args);
|
||||
string executeHex(const vector<string>& args);
|
||||
|
||||
/**
|
||||
* Execute the find command.
|
||||
@@ -207,7 +207,7 @@ class MainLoop : public Thread, DeviceListener {
|
||||
* @param levels the current user's access levels.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeFind(vector<string> &args, string levels);
|
||||
string executeFind(const vector<string>& args, const string& levels);
|
||||
|
||||
/**
|
||||
* Execute the listen command.
|
||||
@@ -215,21 +215,21 @@ class MainLoop : public Thread, DeviceListener {
|
||||
* @param listening set to true when the client is in listening mode.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeListen(vector<string> &args, bool& listening);
|
||||
string executeListen(const vector<string>& args, bool* listening);
|
||||
|
||||
/**
|
||||
* Execute the state command.
|
||||
* @param args the arguments passed to the command (starting with the command itself), or empty for help.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeState(vector<string> &args);
|
||||
string executeState(const vector<string>& args);
|
||||
|
||||
/**
|
||||
* Execute the grab command.
|
||||
* @param args the arguments passed to the command (starting with the command itself), or empty for help.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeGrab(vector<string> &args);
|
||||
string executeGrab(const vector<string>& args);
|
||||
|
||||
/**
|
||||
* Execute the scan command.
|
||||
@@ -237,35 +237,35 @@ class MainLoop : public Thread, DeviceListener {
|
||||
* @param levels the current user's access levels.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeScan(vector<string> &args, const string levels);
|
||||
string executeScan(const vector<string>& args, const string levels);
|
||||
|
||||
/**
|
||||
* Execute the log command.
|
||||
* @param args the arguments passed to the command (starting with the command itself), or empty for help.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeLog(vector<string> &args);
|
||||
string executeLog(const vector<string>& args);
|
||||
|
||||
/**
|
||||
* Execute the raw command.
|
||||
* @param args the arguments passed to the command (starting with the command itself), or empty for help.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeRaw(vector<string> &args);
|
||||
string executeRaw(const vector<string>& args);
|
||||
|
||||
/**
|
||||
* Execute the dump command.
|
||||
* @param args the arguments passed to the command (starting with the command itself), or empty for help.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeDump(vector<string> &args);
|
||||
string executeDump(const vector<string>& args);
|
||||
|
||||
/**
|
||||
* Execute the reload command.
|
||||
* @param args the arguments passed to the command (starting with the command itself), or empty for help.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeReload(vector<string> &args);
|
||||
string executeReload(const vector<string>& args);
|
||||
|
||||
/**
|
||||
* Execute the info command.
|
||||
@@ -273,7 +273,7 @@ class MainLoop : public Thread, DeviceListener {
|
||||
* @param user the current user name.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeInfo(vector<string> &args, const string user);
|
||||
string executeInfo(const vector<string>& args, const string& user);
|
||||
|
||||
/**
|
||||
* Execute the quit command.
|
||||
@@ -281,7 +281,7 @@ class MainLoop : public Thread, DeviceListener {
|
||||
* @param connected set to false when the client connection shall be closed.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeQuit(vector<string> &args, bool& connected);
|
||||
string executeQuit(const vector<string>& args, bool *connected);
|
||||
|
||||
/**
|
||||
* Execute the help command.
|
||||
@@ -295,16 +295,16 @@ class MainLoop : public Thread, DeviceListener {
|
||||
* @param connected set to false when the client connection shall be closed.
|
||||
* @return the result string.
|
||||
*/
|
||||
string executeGet(vector<string> &args, bool& connected);
|
||||
string executeGet(const vector<string>& args, bool* connected);
|
||||
|
||||
/**
|
||||
* Format the HTTP answer to the result string.
|
||||
* @param ret the result code of handling the request.
|
||||
* @param result the @a ostringstream containing the successful result.
|
||||
* @param type the content type.
|
||||
* @param result the @a ostringstream containing the successful result.
|
||||
* @return the result string.
|
||||
*/
|
||||
string formatHttpResult(result_t ret, ostringstream& result, int type);
|
||||
string formatHttpResult(result_t ret, int type, ostringstream &result);
|
||||
|
||||
/** the @a Device instance. */
|
||||
Device* m_device;
|
||||
|
||||
+18
-18
@@ -81,7 +81,7 @@ static error_t mqtt_parse_opt(int key, char *arg, struct argp_state *state) {
|
||||
break;
|
||||
|
||||
case 2: // --mqttport=1883
|
||||
g_port = (uint16_t)parseInt(arg, 10, 1, 65535, result);
|
||||
g_port = (uint16_t)parseInt(arg, 10, 1, 65535, &result);
|
||||
if (result != RESULT_OK) {
|
||||
argp_error(state, "invalid mqttport");
|
||||
return EINVAL;
|
||||
@@ -187,7 +187,7 @@ static const size_t knownFieldCount = sizeof(knownFieldNames) / sizeof(char*);
|
||||
* @param fields the @a vector to which the field parts shall be added.
|
||||
* @return true on success, false on malformed topic template.
|
||||
*/
|
||||
bool parseTopic(const string topic, vector<string> &strs, vector<string> &fields) {
|
||||
bool parseTopic(const string& topic, vector<string>* strs, vector<string>* fields) {
|
||||
size_t lastpos = 0;
|
||||
size_t end = topic.length();
|
||||
vector<string> columns;
|
||||
@@ -205,18 +205,18 @@ bool parseTopic(const string topic, vector<string> &strs, vector<string> &fields
|
||||
return false;
|
||||
}
|
||||
string fieldName = knownFieldNames[idx];
|
||||
for (const auto& it : fields) {
|
||||
for (const auto& it : *fields) {
|
||||
if (it == fieldName) {
|
||||
return false; // duplicate column
|
||||
}
|
||||
}
|
||||
strs.push_back(topic.substr(lastpos, pos-lastpos));
|
||||
fields.push_back(fieldName);
|
||||
strs->push_back(topic.substr(lastpos, pos-lastpos));
|
||||
fields->push_back(fieldName);
|
||||
lastpos = pos+1+len;
|
||||
pos = topic.find('%', lastpos);
|
||||
}
|
||||
if (lastpos < end) {
|
||||
strs.push_back(topic.substr(lastpos, end-lastpos));
|
||||
strs->push_back(topic.substr(lastpos, end-lastpos));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -259,7 +259,7 @@ MqttHandler::MqttHandler(UserInfo* userInfo, BusHandler* busHandler, MessageMap*
|
||||
bool enabled = g_port != 0;
|
||||
m_publishByField = false;
|
||||
m_mosquitto = NULL;
|
||||
if (enabled && !parseTopic(g_topic, m_topicStrs, m_topicFields)) {
|
||||
if (enabled && !parseTopic(g_topic, &m_topicStrs, &m_topicFields)) {
|
||||
logOtherError("mqtt", "malformed topic %s", g_topic);
|
||||
return;
|
||||
}
|
||||
@@ -386,7 +386,7 @@ void on_message(
|
||||
handler->notifyTopic(topic, data);
|
||||
}
|
||||
|
||||
void MqttHandler::notifyTopic(string topic, string data) {
|
||||
void MqttHandler::notifyTopic(const string& topic, const string& data) {
|
||||
size_t pos = topic.rfind('/');
|
||||
if (pos == string::npos) {
|
||||
return;
|
||||
@@ -466,10 +466,10 @@ void MqttHandler::notifyTopic(string topic, string data) {
|
||||
logOtherNotice("mqtt", "%s %s %s: %s", isWrite?"write":"read", circuit.c_str(), name.c_str(), data.c_str());
|
||||
}
|
||||
ostringstream ostream;
|
||||
publishMessage(message, ostream);
|
||||
publishMessage(message, &ostream);
|
||||
}
|
||||
|
||||
void MqttHandler::notifyUpdateCheckResult(string checkResult) {
|
||||
void MqttHandler::notifyUpdateCheckResult(const string& checkResult) {
|
||||
if (checkResult != m_lastUpdateCheckResult) {
|
||||
m_lastUpdateCheckResult = checkResult;
|
||||
publishTopic(m_globalTopic+"updatecheck", checkResult.empty() ? "OK" : checkResult);
|
||||
@@ -525,7 +525,7 @@ void MqttHandler::run() {
|
||||
updates.str("");
|
||||
updates.clear();
|
||||
updates << dec;
|
||||
publishMessage(it.first, updates);
|
||||
publishMessage(it.first, &updates);
|
||||
}
|
||||
}
|
||||
m_updatedMessages.clear();
|
||||
@@ -557,7 +557,7 @@ void MqttHandler::handleTraffic() {
|
||||
}
|
||||
}
|
||||
|
||||
string MqttHandler::getTopic(Message* message, ssize_t fieldIndex) {
|
||||
string MqttHandler::getTopic(const Message* message, ssize_t fieldIndex) {
|
||||
ostringstream ret;
|
||||
for (size_t i = 0; i < m_topicStrs.size(); i++) {
|
||||
ret << m_topicStrs[i];
|
||||
@@ -568,15 +568,15 @@ string MqttHandler::getTopic(Message* message, ssize_t fieldIndex) {
|
||||
if (m_topicFields[i] == "fields" && fieldIndex >= 0) {
|
||||
ret << message->getFieldName(fieldIndex); // TODO skip ignored fields
|
||||
} else {
|
||||
message->dumpField(ret, m_topicFields[i]);
|
||||
message->dumpField(m_topicFields[i], false, &ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
void MqttHandler::publishMessage(Message* message, ostringstream& updates) {
|
||||
result_t result = message->decodeLastData(updates);
|
||||
void MqttHandler::publishMessage(const Message* message, ostringstream* updates) {
|
||||
result_t result = message->decodeLastData(false, NULL, -1, 0, updates);
|
||||
if (result != RESULT_OK) {
|
||||
logOtherError("mqtt", "decode %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
getResultCode(result));
|
||||
@@ -584,7 +584,7 @@ void MqttHandler::publishMessage(Message* message, ostringstream& updates) {
|
||||
}
|
||||
if (m_publishByField) {
|
||||
ssize_t index = 0;
|
||||
istringstream input(updates.str());
|
||||
istringstream input(updates->str());
|
||||
string token;
|
||||
while (getline(input, token, UI_FIELD_SEPARATOR)) {
|
||||
string topic = getTopic(message, index);
|
||||
@@ -592,11 +592,11 @@ void MqttHandler::publishMessage(Message* message, ostringstream& updates) {
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
publishTopic(getTopic(message), updates.str());
|
||||
publishTopic(getTopic(message), updates->str());
|
||||
}
|
||||
}
|
||||
|
||||
void MqttHandler::publishTopic(string topic, string data, bool retain) {
|
||||
void MqttHandler::publishTopic(const string& topic, const string& data, bool retain) {
|
||||
logOtherDebug("mqtt", "publish %s %s", topic.c_str(), data.c_str());
|
||||
mosquitto_publish(m_mosquitto, NULL, topic.c_str(), (uint32_t)data.size(),
|
||||
reinterpret_cast<const uint8_t*>(data.c_str()), 0, retain);
|
||||
|
||||
@@ -78,10 +78,10 @@ class MqttHandler : public DataSink, public DataSource, public Thread {
|
||||
* @param topic the topic string.
|
||||
* @param data the data string.
|
||||
*/
|
||||
void notifyTopic(string topic, string data);
|
||||
void notifyTopic(const string& topic, const string& data);
|
||||
|
||||
// @copydoc
|
||||
void notifyUpdateCheckResult(string checkResult) override;
|
||||
void notifyUpdateCheckResult(const string& checkResult) override;
|
||||
|
||||
protected:
|
||||
// @copydoc
|
||||
@@ -100,14 +100,14 @@ class MqttHandler : public DataSink, public DataSource, public Thread {
|
||||
* @param fieldIndex the optional field index for the field column, or -1.
|
||||
* @return the topic string.
|
||||
*/
|
||||
string getTopic(Message* message, ssize_t fieldIndex = -1);
|
||||
string getTopic(const Message* message, ssize_t fieldIndex = -1);
|
||||
|
||||
/**
|
||||
* Prepare a @a Message and publish as topic.
|
||||
* @param message the @a Message to publish.
|
||||
* @param updates the @a ostringstream for preparation.
|
||||
*/
|
||||
void publishMessage(Message* message, ostringstream& updates);
|
||||
void publishMessage(const Message* message, ostringstream* updates);
|
||||
|
||||
/**
|
||||
* Publish a topic update to MQTT.
|
||||
@@ -115,7 +115,7 @@ class MqttHandler : public DataSink, public DataSource, public Thread {
|
||||
* @param data the data string.
|
||||
* @param retain whether the topic shall be retained.
|
||||
*/
|
||||
void publishTopic(string topic, string data, bool retain = true);
|
||||
void publishTopic(const string& topic, const string& data, bool retain = true);
|
||||
|
||||
/** the @a MessageMap instance. */
|
||||
MessageMap* m_messages;
|
||||
|
||||
@@ -35,6 +35,40 @@ int Connection::m_ids = 0;
|
||||
#define POLLRDHUP 0
|
||||
#endif
|
||||
|
||||
bool NetMessage::add(const char* request) {
|
||||
if (request && request[0]) {
|
||||
string add = request;
|
||||
add.erase(remove(add.begin(), add.end(), '\r'), add.end());
|
||||
m_request.append(add);
|
||||
}
|
||||
size_t pos = m_request.find(m_isHttp ? "\n\n" : "\n");
|
||||
if (pos != string::npos) {
|
||||
if (m_isHttp) {
|
||||
pos = m_request.find("\n");
|
||||
m_request.resize(pos); // reduce to first line
|
||||
// typical first line: GET /ehp/outsidetemp HTTP/1.1
|
||||
pos = m_request.rfind(" HTTP/");
|
||||
if (pos != string::npos) {
|
||||
m_request.resize(pos); // remove "HTTP/x.x" suffix
|
||||
}
|
||||
pos = 0;
|
||||
while ((pos=m_request.find('%', pos)) != string::npos && pos+2 <= m_request.length()) {
|
||||
unsigned int value1, value2;
|
||||
if (sscanf("%1x%1x", m_request.c_str()+pos+1, &value1, &value2) < 2) {
|
||||
break;
|
||||
}
|
||||
m_request[pos] = static_cast<char>(((value1&0x0f) << 4) | (value2&0x0f));
|
||||
m_request.erase(pos+1, 2);
|
||||
}
|
||||
} else if (pos+1 == m_request.length()) {
|
||||
m_request.resize(pos); // reduce to complete lines
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return m_request.length() == 0 && m_listening;
|
||||
}
|
||||
|
||||
|
||||
void Connection::run() {
|
||||
int ret;
|
||||
struct timespec tdiff;
|
||||
|
||||
+1
-31
@@ -76,37 +76,7 @@ class NetMessage {
|
||||
* @param request the request data from the client.
|
||||
* @return true when the request is complete and the response shall be prepared.
|
||||
*/
|
||||
bool add(string request) {
|
||||
if (request.length() > 0) {
|
||||
request.erase(remove(request.begin(), request.end(), '\r'), request.end());
|
||||
m_request.append(request);
|
||||
}
|
||||
size_t pos = m_request.find(m_isHttp ? "\n\n" : "\n");
|
||||
if (pos != string::npos) {
|
||||
if (m_isHttp) {
|
||||
pos = m_request.find("\n");
|
||||
m_request.resize(pos); // reduce to first line
|
||||
// typical first line: GET /ehp/outsidetemp HTTP/1.1
|
||||
pos = m_request.rfind(" HTTP/");
|
||||
if (pos != string::npos) {
|
||||
m_request.resize(pos); // remove "HTTP/x.x" suffix
|
||||
}
|
||||
pos = 0;
|
||||
while ((pos=m_request.find('%', pos)) != string::npos && pos+2 <= m_request.length()) {
|
||||
unsigned int value1, value2;
|
||||
if (sscanf("%1x%1x", m_request.c_str()+pos+1, &value1, &value2) < 2) {
|
||||
break;
|
||||
}
|
||||
m_request[pos] = static_cast<char>(((value1&0x0f) << 4) | (value2&0x0f));
|
||||
m_request.erase(pos+1, 2);
|
||||
}
|
||||
} else if (pos+1 == m_request.length()) {
|
||||
m_request.resize(pos); // reduce to complete lines
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return m_request.length() == 0 && m_listening;
|
||||
}
|
||||
bool add(const char* request);
|
||||
|
||||
/**
|
||||
* Return whether this is a HTTP message.
|
||||
|
||||
@@ -39,7 +39,7 @@ void contrib_tem_register() {
|
||||
DataTypeList::getInstance()->add(new TemParamDataType("TEM_P"));
|
||||
}
|
||||
|
||||
result_t TemParamDataType::derive(int divisor, size_t bitCount, const NumberDataType* &derived) const {
|
||||
result_t TemParamDataType::derive(int divisor, size_t bitCount, const NumberDataType** derived) const {
|
||||
if (divisor == 0) {
|
||||
divisor = 1;
|
||||
}
|
||||
@@ -47,27 +47,26 @@ result_t TemParamDataType::derive(int divisor, size_t bitCount, const NumberData
|
||||
bitCount = m_bitCount;
|
||||
}
|
||||
if (divisor == 1 && bitCount == 16) {
|
||||
derived = this;
|
||||
*derived = this;
|
||||
return RESULT_OK;
|
||||
}
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
result_t TemParamDataType::readSymbols(const SymbolString& input,
|
||||
const size_t offset, const size_t length,
|
||||
ostringstream& output, OutputFormat outputFormat) const {
|
||||
result_t TemParamDataType::readSymbols(size_t offset, size_t length, const SymbolString& input,
|
||||
OutputFormat outputFormat, ostream* output) const {
|
||||
unsigned int value = 0;
|
||||
|
||||
result_t result = readRawValue(input, offset, length, value);
|
||||
result_t result = readRawValue(offset, length, input, &value);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (value == m_replacement) {
|
||||
if (outputFormat & OF_JSON) {
|
||||
output << "null";
|
||||
*output << "null";
|
||||
} else {
|
||||
output << NULL_VALUE;
|
||||
*output << NULL_VALUE;
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
@@ -80,31 +79,29 @@ result_t TemParamDataType::readSymbols(const SymbolString& input,
|
||||
num = (value & 0x7f); // num in bits 0...6
|
||||
}
|
||||
if (outputFormat & OF_JSON) {
|
||||
output << '"';
|
||||
*output << '"';
|
||||
}
|
||||
output << setfill('0') << setw(2) << dec << static_cast<int>(grp) << '-' << setw(3) << static_cast<int>(num);
|
||||
*output << setfill('0') << setw(2) << dec << static_cast<int>(grp) << '-' << setw(3) << static_cast<int>(num);
|
||||
if (outputFormat & OF_JSON) {
|
||||
output << '"';
|
||||
*output << '"';
|
||||
}
|
||||
output << setfill(' ') << setw(0); // reset
|
||||
*output << setfill(' ') << setw(0); // reset
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t TemParamDataType::writeSymbols(istringstream& input,
|
||||
const size_t offset, const size_t length,
|
||||
SymbolString& output, size_t* usedLength) const {
|
||||
result_t TemParamDataType::writeSymbols(const size_t offset, const size_t length, istringstream* input,
|
||||
SymbolString* output, size_t* usedLength) const {
|
||||
unsigned int value;
|
||||
int grp, num;
|
||||
string token;
|
||||
|
||||
const char* str = input.str().c_str();
|
||||
if (strcmp(str, NULL_VALUE) == 0) {
|
||||
if (input->str() == NULL_VALUE) {
|
||||
value = m_replacement; // replacement value
|
||||
} else {
|
||||
if (input.eof() || !getline(input, token, '-')) {
|
||||
string token;
|
||||
if (input->eof() || !getline(*input, token, '-')) {
|
||||
return RESULT_ERR_EOF; // incomplete
|
||||
}
|
||||
str = token.c_str();
|
||||
const char* str = token.c_str();
|
||||
if (str == NULL || *str == 0) {
|
||||
return RESULT_ERR_EOF; // input too short
|
||||
}
|
||||
@@ -113,7 +110,7 @@ result_t TemParamDataType::writeSymbols(istringstream& input,
|
||||
if (strEnd == NULL || strEnd == str || *strEnd != 0) {
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
}
|
||||
if (input.eof() || !getline(input, token, '-')) {
|
||||
if (input->eof() || !getline(*input, token, '-')) {
|
||||
return RESULT_ERR_EOF; // incomplete
|
||||
}
|
||||
str = token.c_str();
|
||||
@@ -128,7 +125,7 @@ result_t TemParamDataType::writeSymbols(istringstream& input,
|
||||
if (grp < 0 || grp > 0x1f || num < 0 || num > 0x7f) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
}
|
||||
if (output.isMaster()) {
|
||||
if (output->isMaster()) {
|
||||
value = grp | (num << 8); // grp in bits 0...5, num in bits 8...13
|
||||
} else {
|
||||
value = (grp << 7) | num; // grp in bits 7...11, num in bits 0...6
|
||||
|
||||
@@ -46,21 +46,19 @@ class TemParamDataType : public NumberDataType {
|
||||
* Constructs a new instance.
|
||||
* @param id the type identifier.
|
||||
*/
|
||||
explicit TemParamDataType(const string id)
|
||||
explicit TemParamDataType(const string& id)
|
||||
: NumberDataType(id, 16, 0, 0xffff, 0, 0xffff, 0, NULL) {}
|
||||
|
||||
// @copydoc
|
||||
result_t derive(int divisor, size_t bitCount, const NumberDataType* &derived) const override;
|
||||
result_t derive(int divisor, size_t bitCount, const NumberDataType** derived) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t readSymbols(const SymbolString& input,
|
||||
const size_t offset, const size_t length,
|
||||
ostringstream& output, OutputFormat outputFormat) const override;
|
||||
result_t readSymbols(size_t offset, size_t length, const SymbolString& input,
|
||||
const OutputFormat outputFormat, ostream* output) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t writeSymbols(istringstream& input,
|
||||
const size_t offset, const size_t length,
|
||||
SymbolString& output, size_t* usedLength) const override;
|
||||
result_t writeSymbols(size_t offset, size_t length, istringstream* input,
|
||||
SymbolString* output, size_t* usedLength) const override;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -54,31 +54,31 @@ class TestReader : public MappedFileReader {
|
||||
TestReader(DataFieldTemplates* templates, bool isSet, bool isMasterDest)
|
||||
: MappedFileReader::MappedFileReader(true), m_templates(templates), m_isSet(isSet), m_isMasterDest(isMasterDest),
|
||||
m_fields(NULL) {}
|
||||
result_t getFieldMap(vector<string>& row, string& errorDescription, const string preferLanguage) const override {
|
||||
if (row.empty()) {
|
||||
row.push_back("*name");
|
||||
row.push_back("part");
|
||||
row.push_back("type");
|
||||
row.push_back("divisor/values");
|
||||
row.push_back("unit");
|
||||
row.push_back("comment");
|
||||
result_t getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const override {
|
||||
if (row->empty()) {
|
||||
row->push_back("*name");
|
||||
row->push_back("part");
|
||||
row->push_back("type");
|
||||
row->push_back("divisor/values");
|
||||
row->push_back("unit");
|
||||
row->push_back("comment");
|
||||
return RESULT_OK;
|
||||
}
|
||||
if (row[0][0] != '*') {
|
||||
if ((*row)[0][0] != '*') {
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
return RESULT_OK; // leave it to DataField::create
|
||||
}
|
||||
result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
|
||||
string& errorDescription, const string filename, unsigned int lineNo) override {
|
||||
if (!row.empty() || subRows.empty()) {
|
||||
result_t addFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
|
||||
vector< map<string, string> >* subRows, string* errorDescription) override {
|
||||
if (!row->empty() || subRows->empty()) {
|
||||
cout << "read line " << static_cast<unsigned>(lineNo) << ": read error: got "
|
||||
<< static_cast<unsigned>(row.size()) << "/0 main, " << static_cast<unsigned>(subRows.size())
|
||||
<< static_cast<unsigned>(row->size()) << "/0 main, " << static_cast<unsigned>(subRows->size())
|
||||
<< "/>=3 sub" << endl;
|
||||
return RESULT_ERR_EOF;
|
||||
}
|
||||
cout << "read line " << static_cast<unsigned>(lineNo) << ": read OK" << endl;
|
||||
return DataField::create(subRows, errorDescription, m_templates, m_fields, m_isSet, false, m_isMasterDest);
|
||||
return DataField::create(m_isSet, false, m_isMasterDest, MAX_POS, m_templates, subRows, errorDescription, &m_fields);
|
||||
}
|
||||
private:
|
||||
DataFieldTemplates* m_templates;
|
||||
@@ -118,7 +118,7 @@ int main() {
|
||||
istringstream dummystr("#");
|
||||
string errorDescription;
|
||||
vector<string> row;
|
||||
templates->readLineFromStream(dummystr, errorDescription, "inline", lineNo, row);
|
||||
templates->readLineFromStream("inline", false, &dummystr, &lineNo, &row, &errorDescription, NULL, NULL);
|
||||
const DataField* fields = NULL;
|
||||
for (size_t i = 0; i < sizeof(checks) / sizeof(checks[0]); i++) {
|
||||
string check[5] = checks[i];
|
||||
@@ -156,7 +156,7 @@ int main() {
|
||||
lineNo = 0;
|
||||
dummystr.clear();
|
||||
dummystr.str("#");
|
||||
result = reader.readLineFromStream(dummystr, errorDescription, "inline", lineNo, row);
|
||||
result = reader.readLineFromStream("inline", false, &dummystr, &lineNo, &row, &errorDescription, NULL, NULL);
|
||||
if (result != RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": reader header error: " << getResultCode(result) << ", " << errorDescription
|
||||
<< endl;
|
||||
@@ -164,7 +164,7 @@ int main() {
|
||||
continue;
|
||||
}
|
||||
lineNo = baseLine + i;
|
||||
result = reader.readLineFromStream(isstr, errorDescription, "", lineNo, row);
|
||||
result = reader.readLineFromStream(__FILE__, false, &isstr, &lineNo, &row, &errorDescription, NULL, NULL);
|
||||
fields = reader.m_fields;
|
||||
|
||||
if (result != RESULT_OK) {
|
||||
@@ -178,7 +178,7 @@ int main() {
|
||||
continue;
|
||||
}
|
||||
cout << "\"" << check[0] << "\"=\"";
|
||||
fields->dump(cout);
|
||||
fields->dump(&cout);
|
||||
cout << "\": create OK" << endl;
|
||||
|
||||
ostringstream output;
|
||||
@@ -194,21 +194,21 @@ int main() {
|
||||
cout << " parse \"" << sstr.getStr().substr(0, 2) << "\" error: " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
}
|
||||
result = fields->read(mstr, 0, output, 0, -1, false);
|
||||
result = fields->read(mstr, 0, false, NULL, -1, 0, -1, &output);
|
||||
if (result >= RESULT_OK) {
|
||||
result = fields->read(sstr, 0, output, 0, -1, !output.str().empty());
|
||||
result = fields->read(sstr, 0, !output.str().empty(), NULL, -1, 0, -1, &output);
|
||||
}
|
||||
if (failedRead) {
|
||||
if (result >= RESULT_OK) {
|
||||
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
|
||||
cout << " failed read " << fields->getName(-1) << " >" << check[2] << " " << check[3]
|
||||
<< "< error: unexpectedly succeeded" << endl;
|
||||
error = true;
|
||||
} else {
|
||||
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
|
||||
cout << " failed read " << fields->getName(-1) << " >" << check[2] << " " << check[3]
|
||||
<< "< OK" << endl;
|
||||
}
|
||||
} else if (result < RESULT_OK) {
|
||||
cout << " read " << fields->getName() << " >" << check[2] << " " << check[3]
|
||||
cout << " read " << fields->getName(-1) << " >" << check[2] << " " << check[3]
|
||||
<< "< error: " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
} else {
|
||||
@@ -217,21 +217,21 @@ int main() {
|
||||
}
|
||||
|
||||
istringstream input(expectStr);
|
||||
result = fields->write(input, writeMstr, 0);
|
||||
result = fields->write(UI_FIELD_SEPARATOR, 0, &input, &writeMstr, NULL);
|
||||
if (result >= RESULT_OK) {
|
||||
result = fields->write(input, writeSstr, 0);
|
||||
result = fields->write(UI_FIELD_SEPARATOR, 0, &input, &writeSstr, NULL);
|
||||
}
|
||||
if (failedWrite) {
|
||||
if (result >= RESULT_OK) {
|
||||
cout << " failed write " << fields->getName() << " >"
|
||||
cout << " failed write " << fields->getName(-1) << " >"
|
||||
<< expectStr << "< error: unexpectedly succeeded" << endl;
|
||||
error = true;
|
||||
} else {
|
||||
cout << " failed write " << fields->getName() << " >"
|
||||
cout << " failed write " << fields->getName(-1) << " >"
|
||||
<< expectStr << "< OK" << endl;
|
||||
}
|
||||
} else if (result < RESULT_OK) {
|
||||
cout << " write " << fields->getName() << " >" << expectStr
|
||||
cout << " write " << fields->getName(-1) << " >" << expectStr
|
||||
<< "< error: " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
} else {
|
||||
|
||||
+244
-262
File diff suppressed because it is too large
Load Diff
+126
-124
@@ -56,7 +56,7 @@ namespace ebusd {
|
||||
* @param supportsLanguage set to true when the field supports multiple language.
|
||||
* @return the normalized data field name, or empty if unknown.
|
||||
*/
|
||||
string getDataFieldName(const string name, bool& supportsLanguage);
|
||||
string getDataFieldName(const string& name, bool* supportsLanguage);
|
||||
|
||||
class DataFieldTemplates;
|
||||
class SingleDataField;
|
||||
@@ -71,14 +71,14 @@ class AttributedItem {
|
||||
* @param name the item name.
|
||||
* @param attributes the additional named attributes.
|
||||
*/
|
||||
AttributedItem(const string name, const map<string, string>& attributes)
|
||||
AttributedItem(const string& name, const map<string, string>& attributes)
|
||||
: m_name(name), m_attributes(attributes) {}
|
||||
|
||||
/**
|
||||
* Constructs a new instance (without additional attributes).
|
||||
* @param name the field name.
|
||||
*/
|
||||
explicit AttributedItem(const string name)
|
||||
explicit AttributedItem(const string& name)
|
||||
: m_name(name) {}
|
||||
|
||||
/**
|
||||
@@ -92,69 +92,69 @@ class AttributedItem {
|
||||
* @param value the int value.
|
||||
* @return the formatted string.
|
||||
*/
|
||||
static const string formatInt(size_t value);
|
||||
static string formatInt(size_t value);
|
||||
|
||||
/**
|
||||
* Remove and return a certain value from a map.
|
||||
* @param row the map to remove the value from.
|
||||
* @param key the name of the value to remove.
|
||||
* @param row the map to remove the value from.
|
||||
* @return the named value from the map, or empty if not available.
|
||||
*/
|
||||
static const string pluck(map<string, string>& row, const string key);
|
||||
static string pluck(const string& key, map<string, string>* row);
|
||||
|
||||
/**
|
||||
* Dump the @a string optionally embedded in @a TEXT_SEPARATOR to the output.
|
||||
* @param output the @a ostream to dump to.
|
||||
* @param str the @a string to dump.
|
||||
* @param prependFieldSeparator whether to start with a @a FIELD_SEPARATOR.
|
||||
* @param str the @a string to dump.
|
||||
* @param output the @a ostream to dump to.
|
||||
*/
|
||||
static void dumpString(ostream& output, const string str, const bool prependFieldSeparator = true);
|
||||
static void dumpString(bool prependFieldSeparator, const string& str, ostream* output);
|
||||
|
||||
/**
|
||||
* Append a named attribute as JSON to the output.
|
||||
* @param output the @a ostream to append to.
|
||||
* @param prependFieldSeparator whether to start with a @a FIELD_SEPARATOR.
|
||||
* @param name the name of the attribute.
|
||||
* @param value the value of the attribute.
|
||||
* @param prependFieldSeparator whether to start with a @a FIELD_SEPARATOR.
|
||||
* @param asString true to force writing as string, false to detect the type from the value.
|
||||
* @param output the @a ostream to append to.
|
||||
*/
|
||||
static void appendJson(ostream& output, const string name, const string value,
|
||||
const bool prependFieldSeparator = true, bool asString = false);
|
||||
static void appendJson(bool prependFieldSeparator, const string& name, const string& value,
|
||||
bool asString, ostream* output);
|
||||
|
||||
/**
|
||||
* Merge this instance's additional named attributes into the specified attributes.
|
||||
* @param attributes the additional named attributes to merge in this instance's additional named attributes.
|
||||
*/
|
||||
void mergeAttributes(map<string, string>& attributes) const;
|
||||
void mergeAttributes(map<string, string>* attributes) const;
|
||||
|
||||
/**
|
||||
* Dump the attribute optionally embedded in @a TEXT_SEPARATOR to the output.
|
||||
* @param output the @a ostream to dump to.
|
||||
* @param name the name of the attribute to dump.
|
||||
* @param prependFieldSeparator whether to start with a @a FIELD_SEPARATOR.
|
||||
* @param name the name of the attribute to dump.
|
||||
* @param output the @a ostream to dump to.
|
||||
*/
|
||||
void dumpAttribute(ostream& output, const string name, const bool prependFieldSeparator = true) const;
|
||||
void dumpAttribute(bool prependFieldSeparator, const string& name, ostream* output) const;
|
||||
|
||||
/**
|
||||
* Append the attribute value to the output.
|
||||
* @param output the @a ostringstream to append the formatted value to.
|
||||
* @param outputFormat the @a OutputFormat options to use.
|
||||
* @param name the name of the attribute to append.
|
||||
* @param onlyIfNonEmpty true to append only if the value is not empty.
|
||||
* @param prefix optional prefix to use (only for non-JSON output).
|
||||
* @param suffix optional suffix to use (only for non-JSON output).
|
||||
* @param output the @a ostream to append the formatted value to.
|
||||
* @return true if data was added, false otherwise.
|
||||
*/
|
||||
bool appendAttribute(ostringstream& output, OutputFormat outputFormat, const string name,
|
||||
const bool onlyIfNonEmpty = true, const string prefix = "", const string suffix = "") const;
|
||||
bool appendAttribute(OutputFormat outputFormat, const string& name, bool onlyIfNonEmpty,
|
||||
const string& prefix, const string& suffix, ostream* output) const;
|
||||
|
||||
/**
|
||||
* Append the attributes to the output.
|
||||
* @param output the @a ostringstream to append the formatted values to.
|
||||
* @param outputFormat the @a OutputFormat options to use.
|
||||
* @param output the @a ostream to append the formatted values to.
|
||||
* @return true if data was added, false otherwise.
|
||||
*/
|
||||
bool appendAttributes(ostringstream& output, OutputFormat outputFormat) const;
|
||||
bool appendAttributes(OutputFormat outputFormat, ostream* output) const;
|
||||
|
||||
/**
|
||||
* Get the item name.
|
||||
@@ -167,7 +167,7 @@ class AttributedItem {
|
||||
* @param name the name of the attribute.
|
||||
* @return the named attribute value, or empty.
|
||||
*/
|
||||
string getAttribute(const string name) const;
|
||||
string getAttribute(const string& name) const;
|
||||
|
||||
|
||||
protected:
|
||||
@@ -178,6 +178,7 @@ class AttributedItem {
|
||||
const map<string, string> m_attributes;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Base class for all kinds of data fields.
|
||||
*/
|
||||
@@ -188,14 +189,14 @@ class DataField : public AttributedItem {
|
||||
* @param name the field name.
|
||||
* @param attributes the additional named attributes.
|
||||
*/
|
||||
DataField(const string name, const map<string, string>& attributes)
|
||||
DataField(const string& name, const map<string, string>& attributes)
|
||||
: AttributedItem(name, attributes) {}
|
||||
|
||||
/**
|
||||
* Constructs a new instance (without additional attributes).
|
||||
* @param name the field name.
|
||||
*/
|
||||
explicit DataField(const string name)
|
||||
explicit DataField(const string& name)
|
||||
: AttributedItem(name) {}
|
||||
|
||||
/**
|
||||
@@ -211,63 +212,62 @@ class DataField : public AttributedItem {
|
||||
|
||||
/**
|
||||
* Factory method for creating new instances.
|
||||
* @param rows the mapped field definition rows.
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @param templates the @a DataFieldTemplates to be referenced by name, or NULL.
|
||||
* @param returnField the variable in which to store the created instance.
|
||||
* @param isWriteMessage whether the field is part of a write message (default false).
|
||||
* @param isTemplate true for creating a template @a DataField.
|
||||
* @param isBroadcastOrMasterDestination true if the destination bus address is @a BRODCAST or a master address.
|
||||
* @param maxFieldLength the maximum allowed length of a single field (default @a MAX_POS).
|
||||
* @param maxFieldLength the maximum allowed length of a single field (e.g. @a MAX_POS).
|
||||
* @param templates the @a DataFieldTemplates to be referenced by name, or NULL.
|
||||
* @param rows the mapped field definition rows (may be modified).
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @param returnField the variable in which to store the created instance.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
* Note: the caller needs to free the created instance.
|
||||
*/
|
||||
static result_t create(vector< map<string, string> >& rows, string& errorDescription,
|
||||
DataFieldTemplates* templates, const DataField*& returnField,
|
||||
const bool isWriteMessage,
|
||||
const bool isTemplate, const bool isBroadcastOrMasterDestination,
|
||||
const size_t maxFieldLength = MAX_POS);
|
||||
static result_t create(bool isWriteMessage, bool isTemplate, bool isBroadcastOrMasterDestination,
|
||||
size_t maxFieldLength, const DataFieldTemplates* templates, vector< map<string, string> >* rows,
|
||||
string* errorDescription, const DataField** returnField);
|
||||
|
||||
/**
|
||||
* Return the name of the specified day.
|
||||
* @param day the day (between 0 and 6).
|
||||
* @return the name of the specified day.
|
||||
*/
|
||||
static string getDayName(int day);
|
||||
static const char* getDayName(int day);
|
||||
|
||||
/**
|
||||
* Returns the length of this field (or contained fields) in bytes.
|
||||
* @param partType the message part of the contained fields to limit the length calculation to.
|
||||
* @param maxLength the maximum length for calculating remainder of input.
|
||||
* @param maxLength the maximum length for calculating remainder of input (e.g. @a MAX_LEN).
|
||||
* @return the length of this field (or contained fields) in bytes.
|
||||
*/
|
||||
virtual size_t getLength(PartType partType, size_t maxLength = MAX_LEN) const = 0;
|
||||
virtual size_t getLength(PartType partType, size_t maxLength) const = 0;
|
||||
|
||||
/**
|
||||
* Derive a new @a DataField from this field.
|
||||
* @param name the field name, or empty to use this fields name.
|
||||
* @param attributes the additional named attributes to override.
|
||||
* @param partType the message part in which the field is stored.
|
||||
* @param divisor the extra divisor (negative for reciprocal) to apply on the value, or 1 for none (if applicable).
|
||||
* @param attributes the additional named attributes to override (may be modified).
|
||||
* @param values the value=text assignments, or empty to use this fields assignments (if applicable).
|
||||
* @param fields the @a vector to which created @a SingleDataField instances shall be added.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t derive(const string name, map<string, string> attributes, const PartType partType,
|
||||
int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const = 0;
|
||||
virtual result_t derive(const string& name, PartType partType, int divisor,
|
||||
const map<unsigned int, string>& values, map<string, string>* attributes,
|
||||
vector<const SingleDataField*>* fields) const = 0;
|
||||
|
||||
/**
|
||||
* Get the specified field name.
|
||||
* @param fieldIndex the index of the field, or -1 for this.
|
||||
* @return the field name, or the index as string if not unique or not available.
|
||||
*/
|
||||
virtual string getName(const ssize_t fieldIndex = -1) const { return m_name; }
|
||||
virtual string getName(ssize_t fieldIndex) const { return m_name; }
|
||||
|
||||
/**
|
||||
* Dump the field settings to the output.
|
||||
* @param output the @a ostream to dump to.
|
||||
*/
|
||||
virtual void dump(ostream& output) const = 0;
|
||||
virtual void dump(ostream* output) const = 0;
|
||||
|
||||
/**
|
||||
* Return whether the field is available.
|
||||
@@ -281,46 +281,46 @@ class DataField : public AttributedItem {
|
||||
* Reads the numeric value from the @a SymbolString.
|
||||
* @param data the data @a SymbolString for reading binary data.
|
||||
* @param offset the additional offset to add for reading binary data.
|
||||
* @param output the variable in which to store the numeric value.
|
||||
* @param fieldName the name of the field to read, or NULL for the first field.
|
||||
* @param fieldIndex the optional index of the named field, or -1.
|
||||
* @param output the variable in which to store the numeric value.
|
||||
* @return @a RESULT_OK on success,
|
||||
* or @a RESULT_EMPTY if the field was skipped (either if the partType does
|
||||
* not match or ignored, or due to @a fieldName or @a fieldIndex),
|
||||
* or an error code.
|
||||
*/
|
||||
virtual result_t read(const SymbolString& data, size_t offset,
|
||||
unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) const = 0;
|
||||
const char* fieldName, ssize_t fieldIndex, unsigned int* output) const = 0;
|
||||
|
||||
/**
|
||||
* Reads the value from the @a SymbolString.
|
||||
* @param data the data @a SymbolString for reading binary data.
|
||||
* @param offset the additional offset to add for reading binary data.
|
||||
* @param output the @a ostringstream to append the formatted value to.
|
||||
* @param outputFormat the @a OutputFormat options to use.
|
||||
* @param outputIndex the optional index of the field when using an indexed output format, or -1.
|
||||
* @param leadingSeparator whether to prepend a separator before the formatted value.
|
||||
* @param fieldName the optional name of a field to limit the output to.
|
||||
* @param fieldIndex the optional index of the named field to limit the output to, or -1.
|
||||
* @param outputFormat the @a OutputFormat options to use.
|
||||
* @param outputIndex the optional index of the field when using an indexed output format, or -1.
|
||||
* @param output the @a ostream to append the formatted value to.
|
||||
* @return @a RESULT_OK on success (or if the partType does not match),
|
||||
* or @a RESULT_EMPTY if the field was skipped (either ignored or due to @a fieldName or @a fieldIndex),
|
||||
* or an error code.
|
||||
*/
|
||||
virtual result_t read(const SymbolString& data, size_t offset,
|
||||
ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1,
|
||||
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const = 0;
|
||||
bool leadingSeparator, const char* fieldName, ssize_t fieldIndex,
|
||||
OutputFormat outputFormat, ssize_t outputIndex, ostream* output) const = 0;
|
||||
|
||||
/**
|
||||
* Writes the value to the master or slave @a SymbolString.
|
||||
* @param input the @a istringstream to parse the formatted value from.
|
||||
* @param data the unescaped data @a SymbolString for writing binary data.
|
||||
* @param offset the additional offset to add for writing binary data.
|
||||
* @param separator the separator character between multiple fields.
|
||||
* @param length the variable in which to store the used length in bytes, or NULL.
|
||||
* @param offset the additional offset to add for writing binary data.
|
||||
* @param data the data @a SymbolString to write binary data to.
|
||||
* @param usedLength the variable in which to store the used length in bytes, or NULL.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t write(istringstream& input, SymbolString& data,
|
||||
size_t offset, char separator = UI_FIELD_SEPARATOR, size_t* length = NULL) const = 0;
|
||||
virtual result_t write(char separator, size_t offset, istringstream* input,
|
||||
SymbolString* data, size_t* usedLength) const = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -337,8 +337,8 @@ class SingleDataField : public DataField {
|
||||
* @param partType the message part in which the field is stored.
|
||||
* @param length the number of symbols in the message part in which the field is stored.
|
||||
*/
|
||||
SingleDataField(const string name, const map<string, string>& attributes, const DataType* dataType,
|
||||
const PartType partType, const size_t length)
|
||||
SingleDataField(const string& name, const map<string, string>& attributes, const DataType* dataType,
|
||||
PartType partType, size_t length)
|
||||
: DataField(name, attributes),
|
||||
m_partType(partType), m_dataType(dataType), m_length(length) {}
|
||||
|
||||
@@ -365,9 +365,9 @@ class SingleDataField : public DataField {
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
* Note: the caller needs to free the created instance.
|
||||
*/
|
||||
static result_t create(const string name, const map<string, string>& attributes, const DataType* dataType,
|
||||
const PartType partType, const size_t length, int divisor, map<unsigned int, string> values,
|
||||
const string constantValue, const bool verifyValue, SingleDataField* &returnField);
|
||||
static result_t create(const string& name, const map<string, string>& attributes, const DataType* dataType,
|
||||
PartType partType, size_t length, int divisor, const string& constantValue,
|
||||
bool verifyValue, map<unsigned int, string>* values, SingleDataField** returnField);
|
||||
|
||||
/**
|
||||
* Get whether this field is ignored.
|
||||
@@ -382,11 +382,12 @@ class SingleDataField : public DataField {
|
||||
PartType getPartType() const { return m_partType; }
|
||||
|
||||
// @copydoc
|
||||
size_t getLength(PartType partType, size_t maxLength = MAX_LEN) const override;
|
||||
size_t getLength(PartType partType, size_t maxLength) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t derive(const string name, map<string, string> attributes, const PartType partType,
|
||||
int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
|
||||
result_t derive(const string& name, PartType partType, int divisor,
|
||||
const map<unsigned int, string>& values, map<string, string>* attributes,
|
||||
vector<const SingleDataField*>* fields) const override;
|
||||
|
||||
/**
|
||||
* Get whether this field uses a full byte offset.
|
||||
@@ -396,24 +397,36 @@ class SingleDataField : public DataField {
|
||||
*/
|
||||
bool hasFullByteOffset(bool after) const;
|
||||
|
||||
/**
|
||||
* Dump the common prefix field settings to the output (name and part type).
|
||||
* @param output the @a ostream to dump to.
|
||||
*/
|
||||
void dumpPrefix(ostream* output) const;
|
||||
|
||||
/**
|
||||
* Dump the common suffix field settings to the output (optiona unit and comment).
|
||||
* @param output the @a ostream to dump to.
|
||||
*/
|
||||
void dumpSuffix(ostream* output) const;
|
||||
|
||||
// @copydoc
|
||||
void dump(ostream& output) const override;
|
||||
void dump(ostream* output) const override;
|
||||
|
||||
// @copydoc
|
||||
bool hasField(const char* fieldName, bool numeric) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t read(const SymbolString& data, size_t offset,
|
||||
unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
|
||||
const char* fieldName, ssize_t fieldIndex, unsigned int* output) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t read(const SymbolString& data, size_t offset,
|
||||
ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1,
|
||||
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
|
||||
bool leadingSeparator, const char* fieldName, ssize_t fieldIndex,
|
||||
OutputFormat outputFormat, ssize_t outputIndex, ostream* output) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t write(istringstream& input, SymbolString& data,
|
||||
size_t offset, char separator = UI_FIELD_SEPARATOR, size_t* length = NULL) const override;
|
||||
result_t write(char separator, size_t offset, istringstream* input,
|
||||
SymbolString* data, size_t* usedLength) const override;
|
||||
|
||||
|
||||
protected:
|
||||
@@ -421,13 +434,12 @@ class SingleDataField : public DataField {
|
||||
* Internal method for reading the field from a @a SymbolString.
|
||||
* @param input the @a SymbolString to read the binary value from.
|
||||
* @param offset the offset in the @a SymbolString.
|
||||
* @param output the ostringstream to append the formatted value to.
|
||||
* @param outputFormat the @a OutputFormat options to use.
|
||||
* @param output the ostream to append the formatted value to.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t readSymbols(const SymbolString& input,
|
||||
const size_t offset,
|
||||
ostringstream& output, OutputFormat outputFormat) const;
|
||||
virtual result_t readSymbols(const SymbolString& input, size_t offset,
|
||||
OutputFormat outputFormat, ostream* output) const;
|
||||
|
||||
/**
|
||||
* Internal method for writing the field to a @a SymbolString.
|
||||
@@ -437,9 +449,8 @@ class SingleDataField : public DataField {
|
||||
* @param usedLength the variable in which to store the used length in bytes, or NULL.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t writeSymbols(istringstream& input,
|
||||
const size_t offset,
|
||||
SymbolString& output, size_t* usedLength) const;
|
||||
virtual result_t writeSymbols(size_t offset, istringstream* input,
|
||||
SymbolString* output, size_t* usedLength) const;
|
||||
|
||||
/** the message part in which the field is stored. */
|
||||
const PartType m_partType;
|
||||
@@ -466,8 +477,8 @@ class ValueListDataField : public SingleDataField {
|
||||
* @param length the number of symbols in the message part in which the field is stored.
|
||||
* @param values the value=text assignments.
|
||||
*/
|
||||
ValueListDataField(const string name, const map<string, string>& attributes, const DataType* dataType,
|
||||
const PartType partType, const size_t length, const map<unsigned int, string> values)
|
||||
ValueListDataField(const string& name, const map<string, string>& attributes, const DataType* dataType,
|
||||
PartType partType, size_t length, const map<unsigned int, string>& values)
|
||||
: SingleDataField(name, attributes, dataType, partType, length),
|
||||
m_values(values) {}
|
||||
|
||||
@@ -480,21 +491,22 @@ class ValueListDataField : public SingleDataField {
|
||||
const ValueListDataField* clone() const override;
|
||||
|
||||
// @copydoc
|
||||
result_t derive(const string name, map<string, string> attributes, const PartType partType,
|
||||
int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
|
||||
result_t derive(const string& name, PartType partType, int divisor,
|
||||
const map<unsigned int, string>& values, map<string, string>* attributes,
|
||||
vector<const SingleDataField*>* fields) const override;
|
||||
|
||||
// @copydoc
|
||||
void dump(ostream& output) const override;
|
||||
void dump(ostream* output) const override;
|
||||
|
||||
|
||||
protected:
|
||||
// @copydoc
|
||||
result_t readSymbols(const SymbolString& input, const size_t offset,
|
||||
ostringstream& output, OutputFormat outputFormat) const override;
|
||||
result_t readSymbols(const SymbolString& input, size_t offset,
|
||||
const OutputFormat outputFormat, ostream* output) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t writeSymbols(istringstream& input, const size_t offset,
|
||||
SymbolString& output, size_t* usedLength) const override;
|
||||
result_t writeSymbols(size_t offset, istringstream* input,
|
||||
SymbolString* output, size_t* usedLength) const override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -518,8 +530,8 @@ class ConstantDataField : public SingleDataField {
|
||||
* @param value the constant value.
|
||||
* @param verify whether to verify the read value against the constant value.
|
||||
*/
|
||||
ConstantDataField(const string name, const map<string, string>& attributes, const DataType* dataType,
|
||||
const PartType partType, const size_t length, const string value, const bool verify)
|
||||
ConstantDataField(const string& name, const map<string, string>& attributes, const DataType* dataType,
|
||||
PartType partType, size_t length, const string& value, bool verify)
|
||||
: SingleDataField(name, attributes, dataType, partType, length),
|
||||
m_value(value), m_verify(verify) {}
|
||||
|
||||
@@ -532,21 +544,22 @@ class ConstantDataField : public SingleDataField {
|
||||
const ConstantDataField* clone() const override;
|
||||
|
||||
// @copydoc
|
||||
result_t derive(const string name, map<string, string> attributes, const PartType partType,
|
||||
int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
|
||||
result_t derive(const string& name, PartType partType, int divisor,
|
||||
const map<unsigned int, string>& values, map<string, string>* attributes,
|
||||
vector<const SingleDataField*>* fields) const override;
|
||||
|
||||
// @copydoc
|
||||
void dump(ostream& output) const override;
|
||||
void dump(ostream* output) const override;
|
||||
|
||||
|
||||
protected:
|
||||
// @copydoc
|
||||
result_t readSymbols(const SymbolString& input, const size_t offset,
|
||||
ostringstream& output, OutputFormat outputFormat) const override;
|
||||
result_t readSymbols(const SymbolString& input, size_t offset,
|
||||
const OutputFormat outputFormat, ostream* output) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t writeSymbols(istringstream& input, const size_t offset,
|
||||
SymbolString& output, size_t* usedLength) const override;
|
||||
result_t writeSymbols(size_t offset, istringstream* input,
|
||||
SymbolString* output, size_t* usedLength) const override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -580,7 +593,7 @@ class DataFieldSet : public DataField {
|
||||
* @param name the field name.
|
||||
* @param fields the @a vector of @a SingleDataField instances part of this set.
|
||||
*/
|
||||
DataFieldSet(const string name, const vector<const SingleDataField*> fields)
|
||||
DataFieldSet(const string& name, const vector<const SingleDataField*> fields)
|
||||
: DataField(name), m_fields(fields) {
|
||||
bool uniqueNames = true;
|
||||
map<string, string> names;
|
||||
@@ -588,7 +601,7 @@ class DataFieldSet : public DataField {
|
||||
if (field->isIgnored()) {
|
||||
continue;
|
||||
}
|
||||
string name = field->getName();
|
||||
string name = field->getName(-1);
|
||||
if (name.empty() || names.find(name) != names.end()) {
|
||||
uniqueNames = false;
|
||||
break;
|
||||
@@ -607,33 +620,22 @@ class DataFieldSet : public DataField {
|
||||
const DataFieldSet* clone() const override;
|
||||
|
||||
// @copydoc
|
||||
size_t getLength(PartType partType, size_t maxLength = MAX_LEN) const override;
|
||||
size_t getLength(PartType partType, size_t maxLength) const override;
|
||||
|
||||
// @copydoc
|
||||
string getName(const ssize_t fieldIndex = -1) const override;
|
||||
string getName(ssize_t fieldIndex) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t derive(const string name, map<string, string> attributes, const PartType partType,
|
||||
int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
|
||||
result_t derive(const string& name, PartType partType, int divisor,
|
||||
const map<unsigned int, string>& values, map<string, string>* attributes,
|
||||
vector<const SingleDataField*>* fields) const override;
|
||||
|
||||
/**
|
||||
* Returns the @a SingleDataField at the specified index.
|
||||
* @param index the index of the @a SingleDataField to return.
|
||||
* @return the @a SingleDataField at the specified index, or NULL.
|
||||
*/
|
||||
/*SingleDataField* operator[](const size_t index) {
|
||||
if (index >= m_fields.size()) {
|
||||
return NULL;
|
||||
}
|
||||
return m_fields[index];
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Returns the @a SingleDataField at the specified index.
|
||||
* @param index the index of the @a SingleDataField to return.
|
||||
* @return the @a SingleDataField at the specified index, or NULL.
|
||||
*/
|
||||
const SingleDataField* operator[](const size_t index) const {
|
||||
const SingleDataField* operator[](size_t index) const {
|
||||
if (index >= m_fields.size()) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -650,20 +652,20 @@ class DataFieldSet : public DataField {
|
||||
bool hasField(const char* fieldName, bool numeric) const override;
|
||||
|
||||
// @copydoc
|
||||
void dump(ostream& output) const override;
|
||||
void dump(ostream* output) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t read(const SymbolString& data, size_t offset,
|
||||
unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
|
||||
const char* fieldName, ssize_t fieldIndex, unsigned int* output) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t read(const SymbolString& data, size_t offset,
|
||||
ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1,
|
||||
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
|
||||
bool leadingSeparator, const char* fieldName, ssize_t fieldIndex,
|
||||
OutputFormat outputFormat, ssize_t outputIndex, ostream* output) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t write(istringstream& input, SymbolString& data,
|
||||
size_t offset, char separator = UI_FIELD_SEPARATOR, size_t* length = NULL) const override;
|
||||
result_t write(char separator, size_t offset, istringstream* input,
|
||||
SymbolString* data, size_t* usedLength) const override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -692,7 +694,7 @@ class DataFieldTemplates : public MappedFileReader {
|
||||
* Constructs a new copied instance.
|
||||
* @param other the @a DataFieldTemplates to copy from.
|
||||
*/
|
||||
DataFieldTemplates(DataFieldTemplates& other);
|
||||
DataFieldTemplates(const DataFieldTemplates& other);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
@@ -717,11 +719,11 @@ class DataFieldTemplates : public MappedFileReader {
|
||||
result_t add(const DataField* field, string name = "", bool replace = false);
|
||||
|
||||
// @copydoc
|
||||
result_t getFieldMap(vector<string>& row, string& errorDescription, const string preferLanguage) const override;
|
||||
result_t getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
|
||||
string& errorDescription, const string filename, unsigned int lineNo) override;
|
||||
result_t addFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
|
||||
vector< map<string, string> >* subRows, string* errorDescription) override;
|
||||
|
||||
/**
|
||||
* Gets the template @a DataField instance with the specified name.
|
||||
@@ -729,7 +731,7 @@ class DataFieldTemplates : public MappedFileReader {
|
||||
* @return the template @a DataField instance, or NULL.
|
||||
* Note: the caller may not free the returned instance.
|
||||
*/
|
||||
const DataField* get(string name) const;
|
||||
const DataField* get(const string& name) const;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
+117
-126
@@ -42,30 +42,29 @@ using std::setw;
|
||||
using std::endl;
|
||||
|
||||
|
||||
bool DataType::dump(ostream& output, const size_t length, const bool appendSeparatorDivisor) const {
|
||||
output << m_id;
|
||||
bool DataType::dump(size_t length, bool appendSeparatorDivisor, ostream* output) const {
|
||||
*output << m_id;
|
||||
if (isAdjustableLength()) {
|
||||
if (length == REMAIN_LEN) {
|
||||
output << ":*";
|
||||
*output << ":*";
|
||||
} else {
|
||||
output << ":" << static_cast<unsigned>(length);
|
||||
*output << ":" << static_cast<unsigned>(length);
|
||||
}
|
||||
}
|
||||
if (appendSeparatorDivisor) {
|
||||
output << FIELD_SEPARATOR;
|
||||
*output << FIELD_SEPARATOR;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
result_t StringDataType::readRawValue(const SymbolString& input, const size_t offset,
|
||||
const size_t length, unsigned int& value) const {
|
||||
result_t StringDataType::readRawValue(size_t offset, size_t length, const SymbolString& input,
|
||||
unsigned int* value) const {
|
||||
return RESULT_EMPTY;
|
||||
}
|
||||
|
||||
result_t StringDataType::readSymbols(const SymbolString& input,
|
||||
const size_t offset, const size_t length,
|
||||
ostringstream& output, OutputFormat outputFormat) const {
|
||||
result_t StringDataType::readSymbols(size_t offset, size_t length, const SymbolString& input,
|
||||
OutputFormat outputFormat, ostream* output) const {
|
||||
size_t start = 0, count = length;
|
||||
int incr = 1;
|
||||
symbol_t symbol;
|
||||
@@ -81,16 +80,16 @@ result_t StringDataType::readSymbols(const SymbolString& input,
|
||||
}
|
||||
|
||||
if (outputFormat & OF_JSON) {
|
||||
output << '"';
|
||||
*output << '"';
|
||||
}
|
||||
output << setfill('0') << (m_isHex ? hex : dec);
|
||||
*output << setfill('0') << (m_isHex ? hex : dec);
|
||||
for (size_t index = start, i = 0; i < count; index += incr, i++) {
|
||||
symbol = input.dataAt(offset + index);
|
||||
if (m_isHex) {
|
||||
if (i > 0) {
|
||||
output << ' ';
|
||||
*output << ' ';
|
||||
}
|
||||
output << setw(2) << static_cast<unsigned>(symbol);
|
||||
*output << setw(2) << static_cast<unsigned>(symbol);
|
||||
} else {
|
||||
if (symbol == 0x00) {
|
||||
terminated = true;
|
||||
@@ -101,22 +100,21 @@ result_t StringDataType::readSymbols(const SymbolString& input,
|
||||
symbol = '?';
|
||||
} else if (outputFormat & OF_JSON) {
|
||||
if (symbol == '"' || symbol == '\\') {
|
||||
output << '\\'; // escape
|
||||
*output << '\\'; // escape
|
||||
}
|
||||
}
|
||||
output << static_cast<char>(symbol);
|
||||
*output << static_cast<char>(symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (outputFormat & OF_JSON) {
|
||||
output << '"';
|
||||
*output << '"';
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t StringDataType::writeSymbols(istringstream& input,
|
||||
size_t offset, const size_t length,
|
||||
SymbolString& output, size_t* usedLength) const {
|
||||
result_t StringDataType::writeSymbols(size_t offset, size_t length, istringstream* input,
|
||||
SymbolString* output, size_t* usedLength) const {
|
||||
size_t start = 0, count = length;
|
||||
bool remainder = count == REMAIN_LEN && hasFlag(ADJ);
|
||||
int incr = 1;
|
||||
@@ -132,7 +130,7 @@ result_t StringDataType::writeSymbols(istringstream& input,
|
||||
count = 1;
|
||||
}
|
||||
for (size_t index = start, i = 0; i < count; index += incr, i++) {
|
||||
output.dataAt(offset + index) = (symbol_t)m_replacement; // fill up with replacement
|
||||
output->dataAt(offset + index) = (symbol_t)m_replacement; // fill up with replacement
|
||||
}
|
||||
if (usedLength != NULL) {
|
||||
*usedLength = count;
|
||||
@@ -143,39 +141,39 @@ result_t StringDataType::writeSymbols(istringstream& input,
|
||||
size_t i = 0, index;
|
||||
for (index = start; i < count; index += incr, i++) {
|
||||
if (m_isHex) {
|
||||
while (!input.eof() && input.peek() == ' ') {
|
||||
input.get();
|
||||
while (!input->eof() && input->peek() == ' ') {
|
||||
input->get();
|
||||
}
|
||||
if (input.eof()) { // no more digits
|
||||
if (input->eof()) { // no more digits
|
||||
value = m_replacement; // fill up with replacement
|
||||
} else {
|
||||
token.clear();
|
||||
token.push_back((symbol_t)input.get());
|
||||
if (input.eof()) {
|
||||
token.push_back((symbol_t)input->get());
|
||||
if (input->eof()) {
|
||||
return RESULT_ERR_INVALID_NUM; // too short hex value
|
||||
}
|
||||
token.push_back((symbol_t)input.get());
|
||||
if (input.eof()) {
|
||||
token.push_back((symbol_t)input->get());
|
||||
if (input->eof()) {
|
||||
return RESULT_ERR_INVALID_NUM; // too short hex value
|
||||
}
|
||||
value = parseInt(token.c_str(), 16, 0, 0xff, result);
|
||||
value = parseInt(token.c_str(), 16, 0, 0xff, &result);
|
||||
if (result != RESULT_OK) {
|
||||
return result; // invalid hex value
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (input.eof()) {
|
||||
if (input->eof()) {
|
||||
value = m_replacement;
|
||||
} else {
|
||||
value = input.get();
|
||||
if (input.eof() || value < 0x20) {
|
||||
value = input->get();
|
||||
if (input->eof() || value < 0x20) {
|
||||
value = m_replacement;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (remainder && input.eof() && i > 0) {
|
||||
if (remainder && input->eof() && i > 0) {
|
||||
if (value == 0x00 && !m_isHex) {
|
||||
output.dataAt(offset + index) = 0;
|
||||
output->dataAt(offset + index) = 0;
|
||||
index += incr;
|
||||
}
|
||||
break;
|
||||
@@ -183,7 +181,7 @@ result_t StringDataType::writeSymbols(istringstream& input,
|
||||
if (value > 0xff) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
}
|
||||
output.dataAt(offset + index) = (symbol_t)value;
|
||||
output->dataAt(offset + index) = (symbol_t)value;
|
||||
}
|
||||
|
||||
if (!remainder && i < count) {
|
||||
@@ -196,14 +194,13 @@ result_t StringDataType::writeSymbols(istringstream& input,
|
||||
}
|
||||
|
||||
|
||||
result_t DateTimeDataType::readRawValue(const SymbolString& input, const size_t offset,
|
||||
const size_t length, unsigned int& value) const {
|
||||
result_t DateTimeDataType::readRawValue(size_t offset, size_t length, const SymbolString& input,
|
||||
unsigned int* value) const {
|
||||
return RESULT_EMPTY;
|
||||
}
|
||||
|
||||
result_t DateTimeDataType::readSymbols(const SymbolString& input,
|
||||
const size_t offset, const size_t length,
|
||||
ostringstream& output, OutputFormat outputFormat) const {
|
||||
result_t DateTimeDataType::readSymbols(size_t offset, size_t length, const SymbolString& input,
|
||||
OutputFormat outputFormat, ostream* output) const {
|
||||
size_t start = 0, count = length;
|
||||
int incr = 1;
|
||||
symbol_t symbol, last = 0, hour = 0;
|
||||
@@ -218,7 +215,7 @@ result_t DateTimeDataType::readSymbols(const SymbolString& input,
|
||||
}
|
||||
|
||||
if (outputFormat & OF_JSON) {
|
||||
output << '"';
|
||||
*output << '"';
|
||||
}
|
||||
int type = (m_hasDate?2:0) | (m_hasTime?1:0);
|
||||
for (size_t index = start, i = 0; i < count; index += incr, i++) {
|
||||
@@ -236,13 +233,13 @@ result_t DateTimeDataType::readSymbols(const SymbolString& input,
|
||||
case 2: // date only
|
||||
if (!hasFlag(REQ) && symbol == m_replacement) {
|
||||
if (i + 1 != length) {
|
||||
output << NULL_VALUE << ".";
|
||||
*output << NULL_VALUE << ".";
|
||||
break;
|
||||
} else if (last == m_replacement) {
|
||||
if (length == 2) { // number of days since 01.01.1900
|
||||
output << NULL_VALUE << ".";
|
||||
*output << NULL_VALUE << ".";
|
||||
}
|
||||
output << NULL_VALUE;
|
||||
*output << NULL_VALUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -259,29 +256,29 @@ result_t DateTimeDataType::readSymbols(const SymbolString& input,
|
||||
y++;
|
||||
m -= 12;
|
||||
}
|
||||
output << dec << setfill('0') << setw(2) << static_cast<unsigned>(d) << "."
|
||||
<< setw(2) << static_cast<unsigned>(m) << "." << static_cast<unsigned>(y + 1900);
|
||||
*output << dec << setfill('0') << setw(2) << static_cast<unsigned>(d) << "."
|
||||
<< setw(2) << static_cast<unsigned>(m) << "." << static_cast<unsigned>(y + 1900);
|
||||
break;
|
||||
}
|
||||
if (i + 1 == length) {
|
||||
output << (2000 + symbol);
|
||||
*output << (2000 + symbol);
|
||||
} else if (symbol < 1 || (i == 0 && symbol > 31) || (i == 1 && symbol > 12)) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid date
|
||||
} else {
|
||||
output << setw(2) << dec << setfill('0') << static_cast<unsigned>(symbol) << ".";
|
||||
*output << setw(2) << dec << setfill('0') << static_cast<unsigned>(symbol) << ".";
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // time only
|
||||
if (!hasFlag(REQ) && symbol == m_replacement) {
|
||||
if (length == 1) { // truncated time
|
||||
output << NULL_VALUE << ":" << NULL_VALUE;
|
||||
*output << NULL_VALUE << ":" << NULL_VALUE;
|
||||
break;
|
||||
}
|
||||
if (i > 0) {
|
||||
output << ":";
|
||||
*output << ":";
|
||||
}
|
||||
output << NULL_VALUE;
|
||||
*output << NULL_VALUE;
|
||||
break;
|
||||
}
|
||||
if (hasFlag(SPE)) { // minutes since midnight
|
||||
@@ -297,7 +294,7 @@ result_t DateTimeDataType::readSymbols(const SymbolString& input,
|
||||
if (hour > 24) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid hour
|
||||
}
|
||||
output << setw(2) << dec << setfill('0') << static_cast<unsigned>(hour);
|
||||
*output << setw(2) << dec << setfill('0') << static_cast<unsigned>(hour);
|
||||
symbol = (symbol_t)(minutes % 60);
|
||||
} else if (length == 1) { // truncated time
|
||||
if (m_bitCount < 8) {
|
||||
@@ -320,22 +317,21 @@ result_t DateTimeDataType::readSymbols(const SymbolString& input,
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid time
|
||||
}
|
||||
if (i > 0) {
|
||||
output << ":";
|
||||
*output << ":";
|
||||
}
|
||||
output << setw(2) << dec << setfill('0') << static_cast<unsigned>(symbol);
|
||||
*output << setw(2) << dec << setfill('0') << static_cast<unsigned>(symbol);
|
||||
break;
|
||||
}
|
||||
last = symbol;
|
||||
}
|
||||
if (outputFormat & OF_JSON) {
|
||||
output << '"';
|
||||
*output << '"';
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
size_t offset, const size_t length,
|
||||
SymbolString& output, size_t* usedLength) const {
|
||||
result_t DateTimeDataType::writeSymbols(size_t offset, size_t length, istringstream* input,
|
||||
SymbolString* output, size_t* usedLength) const {
|
||||
size_t start = 0, count = length;
|
||||
bool remainder = count == REMAIN_LEN && hasFlag(ADJ);
|
||||
int incr = 1;
|
||||
@@ -351,7 +347,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
count = 1;
|
||||
}
|
||||
for (size_t index = start, i = 0; i < count; index += incr, i++) {
|
||||
output.dataAt(offset + index) = (symbol_t)m_replacement; // fill up with replacement
|
||||
output->dataAt(offset + index) = (symbol_t)m_replacement; // fill up with replacement
|
||||
}
|
||||
if (usedLength != NULL) {
|
||||
*usedLength = count;
|
||||
@@ -369,14 +365,14 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
if (length == 4 && i == 2) {
|
||||
continue; // skip weekday in between
|
||||
}
|
||||
if (input.eof() || !getline(input, token, '.')) {
|
||||
if (input->eof() || !getline(*input, token, '.')) {
|
||||
return RESULT_ERR_EOF; // incomplete
|
||||
}
|
||||
if (!hasFlag(REQ) && strcmp(token.c_str(), NULL_VALUE) == 0) {
|
||||
if (!hasFlag(REQ) && token == NULL_VALUE) {
|
||||
value = m_replacement;
|
||||
break;
|
||||
}
|
||||
value = parseInt(token.c_str(), 10, 0, 2099, result);
|
||||
value = parseInt(token.c_str(), 10, 0, 2099, &result);
|
||||
if (result != RESULT_OK) {
|
||||
return result; // invalid date part
|
||||
}
|
||||
@@ -389,7 +385,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
int l = last <= 2 ? 1 : 0;
|
||||
int mjd = 14956 + lastLast + static_cast<int>((y-l)*365.25) + static_cast<int>((last+1+l*12)*30.6001);
|
||||
value = mjd - 15020; // 01.01.1900
|
||||
output.dataAt(offset + index) = (symbol_t)(value&0xff);
|
||||
output->dataAt(offset + index) = (symbol_t)(value&0xff);
|
||||
value >>= 8;
|
||||
index += incr;
|
||||
skip = false;
|
||||
@@ -404,10 +400,10 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
int mjd = 14956 + lastLast + static_cast<int>((y-l)*365.25) + static_cast<int>((last+1+l*12)*30.6001);
|
||||
int daysSinceSunday = (mjd+3) % 7; // Sun=0
|
||||
if (hasFlag(BCD)) {
|
||||
output.dataAt(offset + index - incr) = (symbol_t)((6+daysSinceSunday) % 7); // Sun=0x06
|
||||
output->dataAt(offset + index - incr) = (symbol_t)((6+daysSinceSunday) % 7); // Sun=0x06
|
||||
} else {
|
||||
// Sun=0x07
|
||||
output.dataAt(offset + index - incr) = (symbol_t)(daysSinceSunday == 0 ? 7 : daysSinceSunday);
|
||||
output->dataAt(offset + index - incr) = (symbol_t)(daysSinceSunday == 0 ? 7 : daysSinceSunday);
|
||||
}
|
||||
}
|
||||
if (value >= 2000) {
|
||||
@@ -422,10 +418,10 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
break;
|
||||
|
||||
case 1: // time only
|
||||
if (input.eof() || !getline(input, token, LENGTH_SEPARATOR)) {
|
||||
if (input->eof() || !getline(*input, token, LENGTH_SEPARATOR)) {
|
||||
return RESULT_ERR_EOF; // incomplete
|
||||
}
|
||||
if (!hasFlag(REQ) && strcmp(token.c_str(), NULL_VALUE) == 0) {
|
||||
if (!hasFlag(REQ) && token == NULL_VALUE) {
|
||||
value = m_replacement;
|
||||
if (length == 1) { // truncated time
|
||||
if (i == 0) {
|
||||
@@ -439,7 +435,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
}
|
||||
break;
|
||||
}
|
||||
value = parseInt(token.c_str(), 10, 0, 59, result);
|
||||
value = parseInt(token.c_str(), 10, 0, 59, &result);
|
||||
if (result != RESULT_OK) {
|
||||
return result; // invalid time part
|
||||
}
|
||||
@@ -452,7 +448,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
break;
|
||||
}
|
||||
value += last*60;
|
||||
output.dataAt(offset + index) = (symbol_t)(value&0xff);
|
||||
output->dataAt(offset + index) = (symbol_t)(value&0xff);
|
||||
value >>= 8;
|
||||
index += incr;
|
||||
} else if (length == 1) { // truncated time
|
||||
@@ -480,7 +476,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
if (value > 0xff) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
}
|
||||
output.dataAt(offset + index) = (symbol_t)value;
|
||||
output->dataAt(offset + index) = (symbol_t)value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,7 +490,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
}
|
||||
|
||||
|
||||
size_t NumberDataType::calcPrecision(const int divisor) {
|
||||
size_t NumberDataType::calcPrecision(int divisor) {
|
||||
size_t precision = 0;
|
||||
if (divisor > 1) {
|
||||
for (unsigned int exp = 1; exp < MAX_DIVISOR; exp *= 10, precision++) {
|
||||
@@ -506,28 +502,28 @@ size_t NumberDataType::calcPrecision(const int divisor) {
|
||||
return precision;
|
||||
}
|
||||
|
||||
bool NumberDataType::dump(ostream& output, size_t length, const bool appendSeparatorDivisor) const {
|
||||
bool NumberDataType::dump(size_t length, bool appendSeparatorDivisor, ostream* output) const {
|
||||
if (m_bitCount < 8) {
|
||||
DataType::dump(output, m_bitCount, appendSeparatorDivisor);
|
||||
DataType::dump(m_bitCount, appendSeparatorDivisor, output);
|
||||
} else {
|
||||
DataType::dump(output, length, appendSeparatorDivisor);
|
||||
DataType::dump(length, appendSeparatorDivisor, output);
|
||||
}
|
||||
if (!appendSeparatorDivisor) {
|
||||
return false;
|
||||
}
|
||||
if (m_baseType) {
|
||||
if (m_baseType->m_divisor != m_divisor) {
|
||||
output << static_cast<int>(m_divisor / m_baseType->m_divisor);
|
||||
*output << static_cast<int>(m_divisor / m_baseType->m_divisor);
|
||||
return true;
|
||||
}
|
||||
} else if (m_divisor != 1) {
|
||||
output << static_cast<int>(m_divisor);
|
||||
*output << static_cast<int>(m_divisor);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
result_t NumberDataType::derive(int divisor, size_t bitCount, const NumberDataType* &derived) const {
|
||||
result_t NumberDataType::derive(int divisor, size_t bitCount, const NumberDataType** derived) const {
|
||||
if (divisor == 0) {
|
||||
divisor = 1;
|
||||
}
|
||||
@@ -549,7 +545,7 @@ result_t NumberDataType::derive(int divisor, size_t bitCount, const NumberDataTy
|
||||
}
|
||||
}
|
||||
if (divisor == m_divisor && bitCount == m_bitCount) {
|
||||
derived = this;
|
||||
*derived = this;
|
||||
return RESULT_OK;
|
||||
}
|
||||
if (-MAX_DIVISOR > divisor || divisor > MAX_DIVISOR) {
|
||||
@@ -569,19 +565,18 @@ result_t NumberDataType::derive(int divisor, size_t bitCount, const NumberDataTy
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
if (m_bitCount < 8) {
|
||||
derived = new NumberDataType(m_id, bitCount, m_flags, m_replacement,
|
||||
*derived = new NumberDataType(m_id, bitCount, m_flags, m_replacement,
|
||||
m_firstBit, divisor, m_baseType ? m_baseType : this);
|
||||
} else {
|
||||
derived = new NumberDataType(m_id, bitCount, m_flags, m_replacement,
|
||||
*derived = new NumberDataType(m_id, bitCount, m_flags, m_replacement,
|
||||
m_minValue, m_maxValue, divisor, m_baseType ? m_baseType : this);
|
||||
}
|
||||
DataTypeList::getInstance()->addCleanup(derived);
|
||||
DataTypeList::getInstance()->addCleanup(*derived);
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t NumberDataType::readRawValue(const SymbolString& input,
|
||||
size_t offset, const size_t length,
|
||||
unsigned int& value) const {
|
||||
result_t NumberDataType::readRawValue(size_t offset, size_t length, const SymbolString& input,
|
||||
unsigned int* value) const {
|
||||
size_t start = 0, count = length;
|
||||
int incr = 1;
|
||||
symbol_t symbol;
|
||||
@@ -594,13 +589,13 @@ result_t NumberDataType::readRawValue(const SymbolString& input,
|
||||
incr = -1;
|
||||
}
|
||||
|
||||
value = 0;
|
||||
*value = 0;
|
||||
unsigned int exp = 1;
|
||||
for (size_t index = start, i = 0; i < count; index += incr, i++) {
|
||||
symbol = input.dataAt(offset + index);
|
||||
if (hasFlag(BCD)) {
|
||||
if (!hasFlag(REQ) && symbol == (m_replacement & 0xff)) {
|
||||
value = m_replacement;
|
||||
*value = m_replacement;
|
||||
return RESULT_OK;
|
||||
}
|
||||
if (!hasFlag(HCD)) {
|
||||
@@ -611,40 +606,39 @@ result_t NumberDataType::readRawValue(const SymbolString& input,
|
||||
} else if (symbol > 0x63) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid HCD
|
||||
}
|
||||
value += symbol * exp;
|
||||
*value += symbol * exp;
|
||||
exp *= 100;
|
||||
} else {
|
||||
value |= symbol * exp;
|
||||
*value |= symbol * exp;
|
||||
exp <<= 8;
|
||||
}
|
||||
}
|
||||
if (m_firstBit > 0) {
|
||||
value >>= m_firstBit;
|
||||
*value >>= m_firstBit;
|
||||
}
|
||||
if (m_bitCount < 8) {
|
||||
value &= (1 << m_bitCount) - 1;
|
||||
*value &= (1 << m_bitCount) - 1;
|
||||
}
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t NumberDataType::readSymbols(const SymbolString& input,
|
||||
const size_t offset, const size_t length,
|
||||
ostringstream& output, OutputFormat outputFormat) const {
|
||||
result_t NumberDataType::readSymbols(size_t offset, size_t length, const SymbolString& input,
|
||||
OutputFormat outputFormat, ostream* output) const {
|
||||
unsigned int value = 0;
|
||||
int signedValue;
|
||||
|
||||
result_t result = readRawValue(input, offset, length, value);
|
||||
result_t result = readRawValue(offset, length, input, &value);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
output << setw(0) << dec; // initialize output
|
||||
*output << setw(0) << dec; // initialize output
|
||||
|
||||
if (!hasFlag(REQ) && value == m_replacement) {
|
||||
if (outputFormat & OF_JSON) {
|
||||
output << "null";
|
||||
*output << "null";
|
||||
} else {
|
||||
output << NULL_VALUE;
|
||||
*output << NULL_VALUE;
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
@@ -694,21 +688,21 @@ result_t NumberDataType::readSymbols(const SymbolString& input,
|
||||
}
|
||||
}
|
||||
if (m_precision != 0) {
|
||||
output << fixed << setprecision(static_cast<int>(m_precision+6));
|
||||
*output << fixed << setprecision(static_cast<int>(m_precision+6));
|
||||
} else if (val == 0) {
|
||||
output << fixed << setprecision(1);
|
||||
*output << fixed << setprecision(1);
|
||||
}
|
||||
output << static_cast<double>(val);
|
||||
*output << static_cast<double>(val);
|
||||
return RESULT_OK;
|
||||
}
|
||||
if (!negative) {
|
||||
if (m_divisor < 0) {
|
||||
output << (static_cast<float>(value) * static_cast<float>(-m_divisor));
|
||||
*output << (static_cast<float>(value) * static_cast<float>(-m_divisor));
|
||||
} else if (m_divisor <= 1) {
|
||||
output << static_cast<unsigned>(value);
|
||||
*output << static_cast<unsigned>(value);
|
||||
} else {
|
||||
output << setprecision(static_cast<int>(m_precision))
|
||||
<< fixed << (static_cast<float>(value) / static_cast<float>(m_divisor));
|
||||
*output << setprecision(static_cast<int>(m_precision))
|
||||
<< fixed << (static_cast<float>(value) / static_cast<float>(m_divisor));
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
@@ -719,30 +713,27 @@ result_t NumberDataType::readSymbols(const SymbolString& input,
|
||||
signedValue = static_cast<int>(value);
|
||||
}
|
||||
if (m_divisor < 0) {
|
||||
output << fixed << setprecision(0)
|
||||
*output << fixed << setprecision(0)
|
||||
<< (static_cast<float>(signedValue) * static_cast<float>(-m_divisor));
|
||||
} else if (m_divisor <= 1) {
|
||||
if (hasFlag(FIX) && hasFlag(BCD)) {
|
||||
if (outputFormat & OF_JSON) {
|
||||
output << '"';
|
||||
output << setw(static_cast<int>(length * 2)) << setfill('0');
|
||||
output << static_cast<signed>(signedValue) << setw(0);
|
||||
output << '"';
|
||||
*output << '"' << setw(static_cast<int>(length * 2))
|
||||
<< setfill('0') << static_cast<signed>(signedValue) << setw(0) << '"';
|
||||
return RESULT_OK;
|
||||
}
|
||||
output << setw(static_cast<int>(length * 2)) << setfill('0');
|
||||
*output << setw(static_cast<int>(length * 2)) << setfill('0');
|
||||
}
|
||||
output << static_cast<signed>(signedValue) << setw(0);
|
||||
*output << static_cast<signed>(signedValue) << setw(0);
|
||||
} else {
|
||||
output << setprecision(static_cast<int>(m_precision))
|
||||
<< fixed << (static_cast<float>(signedValue) / static_cast<float>(m_divisor));
|
||||
*output << setprecision(static_cast<int>(m_precision))
|
||||
<< fixed << (static_cast<float>(signedValue) / static_cast<float>(m_divisor));
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t NumberDataType::writeRawValue(unsigned int value,
|
||||
const size_t offset, const size_t length,
|
||||
SymbolString& output, size_t* usedLength) const {
|
||||
result_t NumberDataType::writeRawValue(unsigned int value, size_t offset, size_t length,
|
||||
SymbolString* output, size_t* usedLength) const {
|
||||
size_t start = 0, count = length;
|
||||
int incr = 1;
|
||||
symbol_t symbol;
|
||||
@@ -774,10 +765,10 @@ result_t NumberDataType::writeRawValue(unsigned int value,
|
||||
symbol = (value / exp) & 0xff;
|
||||
exp <<= 8;
|
||||
}
|
||||
if (index == start && (m_bitCount % 8) != 0 && offset + index < output.getDataSize()) {
|
||||
output.dataAt(offset + index) |= symbol;
|
||||
if (index == start && (m_bitCount % 8) != 0 && offset + index < output->getDataSize()) {
|
||||
output->dataAt(offset + index) |= symbol;
|
||||
} else {
|
||||
output.dataAt(offset + index) = symbol;
|
||||
output->dataAt(offset + index) = symbol;
|
||||
}
|
||||
}
|
||||
if (usedLength != NULL) {
|
||||
@@ -786,17 +777,16 @@ result_t NumberDataType::writeRawValue(unsigned int value,
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t NumberDataType::writeSymbols(istringstream& input,
|
||||
const size_t offset, const size_t length,
|
||||
SymbolString& output, size_t* usedLength) const {
|
||||
result_t NumberDataType::writeSymbols(size_t offset, size_t length, istringstream* input,
|
||||
SymbolString* output, size_t* usedLength) const {
|
||||
unsigned int value;
|
||||
|
||||
const char* str = input.str().c_str();
|
||||
if (!hasFlag(REQ) && (isIgnored() || strcmp(str, NULL_VALUE) == 0)) {
|
||||
if (!hasFlag(REQ) && (isIgnored() || input->str() == NULL_VALUE)) {
|
||||
value = m_replacement; // replacement value
|
||||
} else if (str == NULL || *str == 0) {
|
||||
} else if (input->str().empty()) {
|
||||
return RESULT_ERR_EOF; // input too short
|
||||
} else if (hasFlag(EXP)) { // IEEE 754 binary32
|
||||
const char* str = input->str().c_str();
|
||||
char* strEnd = NULL;
|
||||
double dvalue = strtod(str, &strEnd);
|
||||
if (strEnd == NULL || strEnd == str || *strEnd != 0) {
|
||||
@@ -835,6 +825,7 @@ result_t NumberDataType::writeSymbols(istringstream& input,
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
const char* str = input->str().c_str();
|
||||
char* strEnd = NULL;
|
||||
if (m_divisor == 1) {
|
||||
if (hasFlag(SIG)) {
|
||||
@@ -1038,7 +1029,7 @@ result_t DataTypeList::add(const DataType* dataType) {
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
const DataType* DataTypeList::get(const string id, const size_t length) const {
|
||||
const DataType* DataTypeList::get(const string& id, size_t length) const {
|
||||
if (length > 0) {
|
||||
ostringstream str;
|
||||
str << id << LENGTH_SEPARATOR << static_cast<unsigned>(length);
|
||||
|
||||
+46
-59
@@ -167,7 +167,7 @@ class DataType {
|
||||
* @param replacement the replacement value (fill-up value for @a StringDataType, no replacement if equal to
|
||||
* @a NumberDataType#minValue).
|
||||
*/
|
||||
DataType(const string id, const size_t bitCount, const uint16_t flags, const unsigned int replacement)
|
||||
DataType(const string& id, size_t bitCount, uint16_t flags, unsigned int replacement)
|
||||
: m_id(id), m_bitCount(bitCount), m_flags(flags), m_replacement(replacement) {}
|
||||
|
||||
/**
|
||||
@@ -190,7 +190,7 @@ class DataType {
|
||||
* @param flag the flag to check (like #BCD).
|
||||
* @return whether the flag is set.
|
||||
*/
|
||||
bool hasFlag(const unsigned int flag) const { return (m_flags & flag) != 0; }
|
||||
bool hasFlag(unsigned int flag) const { return (m_flags & flag) != 0; }
|
||||
|
||||
/**
|
||||
* @return whether this type is ignored.
|
||||
@@ -216,50 +216,47 @@ class DataType {
|
||||
/**
|
||||
* Dump the type identifier with the specified length and optionally the
|
||||
* divisor to the output.
|
||||
* @param output the @a ostream to dump to.
|
||||
* @param length the number of symbols to read/write.
|
||||
* @param appendSeparatorDivisor whether to append a @a FIELD_SEPARATOR followed by 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(ostream& output, const size_t length, const bool appendSeparatorDivisor = true) const;
|
||||
virtual bool dump(size_t length, bool appendSeparatorDivisor, ostream* output) const;
|
||||
|
||||
/**
|
||||
* Internal method for reading the numeric raw value from a @a SymbolString.
|
||||
* @param input the @a SymbolString to read the binary value from.
|
||||
* @param offset the offset in the @a SymbolString.
|
||||
* @param length the number of symbols to read.
|
||||
* @param input the @a SymbolString to read the binary value from.
|
||||
* @param value the variable in which to store the numeric raw value.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t readRawValue(const SymbolString& input,
|
||||
const size_t offset, const size_t length,
|
||||
unsigned int& value) const = 0;
|
||||
virtual result_t readRawValue(size_t offset, size_t length, const SymbolString& input,
|
||||
unsigned int* value) const = 0;
|
||||
|
||||
/**
|
||||
* Internal method for reading the field from a @a SymbolString.
|
||||
* @param input the @a SymbolString to read the binary value from.
|
||||
* @param offset the offset in the data of the @a SymbolString.
|
||||
* @param length the number of symbols to read.
|
||||
* @param output the ostringstream to append the formatted value to.
|
||||
* @param input the @a SymbolString to read the binary value from.
|
||||
* @param outputFormat the @a OutputFormat options to use.
|
||||
* @param output the ostream to append the formatted value to.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t readSymbols(const SymbolString& input,
|
||||
const size_t offset, const size_t length,
|
||||
ostringstream& output, OutputFormat outputFormat) const = 0;
|
||||
virtual result_t readSymbols(size_t offset, size_t length, const SymbolString& input,
|
||||
OutputFormat outputFormat, ostream* output) const = 0;
|
||||
|
||||
/**
|
||||
* Internal method for writing the field to a @a SymbolString.
|
||||
* @param input the @a istringstream to parse the formatted value from.
|
||||
* @param offset the offset in the @a SymbolString.
|
||||
* @param length the number of symbols to write, or @a REMAIN_LEN.
|
||||
* @param input the @a istringstream to parse the formatted value from.
|
||||
* @param output the @a SymbolString to write the binary value to.
|
||||
* @param usedLength the variable in which to store the used length in bytes, or NULL.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t writeSymbols(istringstream& input,
|
||||
const size_t offset, const size_t length,
|
||||
SymbolString& output, size_t* usedLength) const = 0;
|
||||
virtual result_t writeSymbols(size_t offset, size_t length, istringstream* input,
|
||||
SymbolString* output, size_t* usedLength) const = 0;
|
||||
|
||||
|
||||
protected:
|
||||
@@ -291,8 +288,8 @@ class StringDataType : public DataType {
|
||||
* @param replacement the replacement value (fill-up value).
|
||||
* @param isHex true for hex digits instead of characters.
|
||||
*/
|
||||
StringDataType(const string id, const size_t bitCount, const uint16_t flags,
|
||||
const unsigned int replacement, bool isHex = false)
|
||||
StringDataType(const string& id, size_t bitCount, uint16_t flags,
|
||||
unsigned int replacement, bool isHex = false)
|
||||
: DataType(id, bitCount, flags, replacement), m_isHex(isHex) {}
|
||||
|
||||
/**
|
||||
@@ -301,19 +298,16 @@ class StringDataType : public DataType {
|
||||
virtual ~StringDataType() {}
|
||||
|
||||
// @copydoc
|
||||
result_t readRawValue(const SymbolString& input,
|
||||
const size_t offset, const size_t length,
|
||||
unsigned int& value) const override;
|
||||
result_t readRawValue(size_t offset, size_t length, const SymbolString& input,
|
||||
unsigned int* value) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t readSymbols(const SymbolString& input,
|
||||
const size_t offset, const size_t length,
|
||||
ostringstream& output, OutputFormat outputFormat) const override;
|
||||
result_t readSymbols(size_t offset, size_t length, const SymbolString& input,
|
||||
OutputFormat outputFormat, ostream* output) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t writeSymbols(istringstream& input,
|
||||
const size_t offset, const size_t length,
|
||||
SymbolString& output, size_t* usedLength) const override;
|
||||
result_t writeSymbols(size_t offset, size_t length, istringstream* input,
|
||||
SymbolString* output, size_t* usedLength) const override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -337,8 +331,8 @@ class DateTimeDataType : public DataType {
|
||||
* @param hasTime true if time part is present.
|
||||
* @param resolution the the resolution in minutes for time types, or 1.
|
||||
*/
|
||||
DateTimeDataType(const string id, const size_t bitCount, const uint16_t flags, const unsigned int replacement,
|
||||
const bool hasDate, const bool hasTime, const int16_t resolution)
|
||||
DateTimeDataType(const string& id, size_t bitCount, uint16_t flags, unsigned int replacement,
|
||||
bool hasDate, bool hasTime, int16_t resolution)
|
||||
: DataType(id, bitCount, flags, replacement), m_hasDate(hasDate), m_hasTime(hasTime),
|
||||
m_resolution(resolution == 0 ? 1 : resolution) {}
|
||||
|
||||
@@ -363,19 +357,16 @@ class DateTimeDataType : public DataType {
|
||||
int16_t getResolution() const { return m_resolution; }
|
||||
|
||||
// @copydoc
|
||||
result_t readRawValue(const SymbolString& input,
|
||||
const size_t offset, const size_t length,
|
||||
unsigned int& value) const override;
|
||||
result_t readRawValue(size_t offset, size_t length, const SymbolString& input,
|
||||
unsigned int* value) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t readSymbols(const SymbolString& input,
|
||||
const size_t offset, const size_t length,
|
||||
ostringstream& output, OutputFormat outputFormat) const override;
|
||||
result_t readSymbols(size_t offset, size_t length, const SymbolString& input,
|
||||
OutputFormat outputFormat, ostream* output) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t writeSymbols(istringstream& input,
|
||||
const size_t offset, const size_t length,
|
||||
SymbolString& output, size_t* usedLength) const override;
|
||||
result_t writeSymbols(const size_t offset, size_t length, istringstream* input,
|
||||
SymbolString* output, size_t* usedLength) const override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -406,8 +397,8 @@ class NumberDataType : public DataType {
|
||||
* @param divisor the divisor (negative for reciprocal).
|
||||
* @param baseType the base @a NumberDataType for derived instances, or NULL.
|
||||
*/
|
||||
NumberDataType(const string id, const size_t bitCount, const uint16_t flags, const unsigned int replacement,
|
||||
const unsigned int minValue, const unsigned int maxValue, const int divisor,
|
||||
NumberDataType(const string& id, size_t bitCount, uint16_t flags, unsigned int replacement,
|
||||
unsigned int minValue, unsigned int maxValue, int divisor,
|
||||
const NumberDataType* baseType)
|
||||
: DataType(id, bitCount, flags|NUM, replacement), m_minValue(minValue), m_maxValue(maxValue), m_divisor(divisor),
|
||||
m_precision(calcPrecision(divisor)), m_firstBit(0), m_baseType(baseType) {}
|
||||
@@ -422,8 +413,8 @@ class NumberDataType : public DataType {
|
||||
* @param divisor the divisor (negative for reciprocal).
|
||||
* @param baseType the base @a NumberDataType for derived instances, or NULL.
|
||||
*/
|
||||
NumberDataType(const string id, const size_t bitCount, const uint16_t flags, const unsigned int replacement,
|
||||
const int16_t firstBit, const int divisor, const NumberDataType* baseType = NULL)
|
||||
NumberDataType(const string& id, size_t bitCount, uint16_t flags, unsigned int replacement,
|
||||
int16_t firstBit, int divisor, const NumberDataType* baseType = NULL)
|
||||
: DataType(id, bitCount, flags|NUM, replacement), m_minValue(0), m_maxValue((1 << bitCount)-1), m_divisor(divisor),
|
||||
m_precision(0), m_firstBit(firstBit), m_baseType(baseType) {}
|
||||
|
||||
@@ -438,10 +429,10 @@ class NumberDataType : public DataType {
|
||||
* @param divisor the divisor (negative for reciprocal).
|
||||
* @return the precision for formatting the value.
|
||||
*/
|
||||
static size_t calcPrecision(const int divisor);
|
||||
static size_t calcPrecision(int divisor);
|
||||
|
||||
// @copydoc
|
||||
bool dump(ostream& output, const size_t length, const bool appendSeparatorDivisor = true) const override;
|
||||
bool dump(size_t length, bool appendSeparatorDivisor, ostream* output) const override;
|
||||
|
||||
/**
|
||||
* Derive a new @a NumberDataType from this.
|
||||
@@ -453,7 +444,7 @@ class NumberDataType : public DataType {
|
||||
* not necessary.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t derive(int divisor, size_t bitCount, const NumberDataType* &derived) const;
|
||||
virtual result_t derive(int divisor, size_t bitCount, const NumberDataType** derived) const;
|
||||
|
||||
/**
|
||||
* @return the minimum raw value.
|
||||
@@ -481,14 +472,12 @@ class NumberDataType : public DataType {
|
||||
int16_t getFirstBit() const { return m_firstBit; }
|
||||
|
||||
// @copydoc
|
||||
result_t readRawValue(const SymbolString& input,
|
||||
const size_t offset, const size_t length,
|
||||
unsigned int& value) const override;
|
||||
result_t readRawValue(size_t offset, size_t length, const SymbolString& input,
|
||||
unsigned int* value) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t readSymbols(const SymbolString& input,
|
||||
const size_t offset, const size_t length,
|
||||
ostringstream& output, OutputFormat outputFormat) const override;
|
||||
result_t readSymbols(size_t offset, size_t length, const SymbolString& input,
|
||||
const OutputFormat outputFormat, ostream* output) const override;
|
||||
|
||||
/**
|
||||
* Internal method for writing the numeric raw value to a @a SymbolString.
|
||||
@@ -500,14 +489,12 @@ class NumberDataType : public DataType {
|
||||
* or NULL.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t writeRawValue(unsigned int value,
|
||||
const size_t offset, const size_t length,
|
||||
SymbolString& output, size_t* usedLength = NULL) const;
|
||||
result_t writeRawValue(unsigned int value, size_t offset, size_t length,
|
||||
SymbolString* output, size_t* usedLength) const;
|
||||
|
||||
// @copydoc
|
||||
result_t writeSymbols(istringstream& input,
|
||||
const size_t offset, const size_t length,
|
||||
SymbolString& output, size_t* usedLength) const override;
|
||||
result_t writeSymbols(size_t offset, size_t length, istringstream* input,
|
||||
SymbolString* output, size_t* usedLength) const override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -580,7 +567,7 @@ class DataTypeList {
|
||||
* @return the @a DataType instance, or NULL if not available.
|
||||
* Note: the caller may not free the instance.
|
||||
*/
|
||||
const DataType* get(const string id, const size_t length = 0) const;
|
||||
const DataType* get(const string& id, size_t length = 0) const;
|
||||
|
||||
/**
|
||||
* Returns an iterator pointing to the first ID/@a DataType pair.
|
||||
|
||||
@@ -42,7 +42,7 @@ Device::~Device() {
|
||||
close();
|
||||
}
|
||||
|
||||
Device* Device::create(const char* name, const bool checkDevice, const bool readOnly, const bool initialSend) {
|
||||
Device* Device::create(const char* name, bool checkDevice, bool readOnly, bool initialSend) {
|
||||
if (strchr(name, '/') == NULL && strchr(name, ':') != NULL) {
|
||||
char* in = strdup(name);
|
||||
bool udp = false;
|
||||
@@ -57,7 +57,7 @@ Device* Device::create(const char* name, const bool checkDevice, const bool read
|
||||
return NULL; // invalid protocol or missing port
|
||||
}
|
||||
result_t result = RESULT_OK;
|
||||
unsigned int port = parseInt(portpos+1, 10, 1, 65535, result);
|
||||
unsigned int port = parseInt(portpos+1, 10, 1, 65535, &result);
|
||||
if (result != RESULT_OK) {
|
||||
free(in);
|
||||
return NULL; // invalid port
|
||||
@@ -98,7 +98,7 @@ bool Device::isValid() {
|
||||
return m_fd != -1;
|
||||
}
|
||||
|
||||
result_t Device::send(const symbol_t value) {
|
||||
result_t Device::send(symbol_t value) {
|
||||
if (!isValid()) {
|
||||
return RESULT_ERR_DEVICE;
|
||||
}
|
||||
@@ -111,7 +111,7 @@ result_t Device::send(const symbol_t value) {
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t Device::recv(const unsigned int timeout, symbol_t& value) {
|
||||
result_t Device::recv(unsigned int timeout, symbol_t* value) {
|
||||
if (!isValid()) {
|
||||
return RESULT_ERR_DEVICE;
|
||||
}
|
||||
@@ -162,7 +162,7 @@ result_t Device::recv(const unsigned int timeout, symbol_t& value) {
|
||||
return RESULT_ERR_DEVICE;
|
||||
}
|
||||
if (m_listener != NULL) {
|
||||
m_listener->notifyDeviceData(value, true);
|
||||
m_listener->notifyDeviceData(*value, true);
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
@@ -299,14 +299,14 @@ bool NetworkDevice::available() {
|
||||
return m_buffer && m_bufLen > 0;
|
||||
}
|
||||
|
||||
ssize_t NetworkDevice::write(const symbol_t value) {
|
||||
ssize_t NetworkDevice::write(symbol_t value) {
|
||||
m_bufLen = 0; // flush read buffer
|
||||
return Device::write(value);
|
||||
}
|
||||
|
||||
ssize_t NetworkDevice::read(symbol_t& value) {
|
||||
ssize_t NetworkDevice::read(symbol_t* value) {
|
||||
if (available()) {
|
||||
value = m_buffer[m_bufPos];
|
||||
*value = m_buffer[m_bufPos];
|
||||
m_bufPos = (m_bufPos+1)%m_bufSize;
|
||||
m_bufLen--;
|
||||
return 1;
|
||||
@@ -316,7 +316,7 @@ ssize_t NetworkDevice::read(symbol_t& value) {
|
||||
if (size <= 0) {
|
||||
return size;
|
||||
}
|
||||
value = m_buffer[0];
|
||||
*value = m_buffer[0];
|
||||
m_bufPos = 1;
|
||||
m_bufLen = size-1;
|
||||
return size;
|
||||
|
||||
+13
-13
@@ -54,7 +54,7 @@ class DeviceListener {
|
||||
* @param symbol the received/sent symbol.
|
||||
* @param received @a true on reception, @a false on sending.
|
||||
*/
|
||||
virtual void notifyDeviceData(const symbol_t symbol, bool received) = 0; // abstract
|
||||
virtual void notifyDeviceData(symbol_t symbol, bool received) = 0; // abstract
|
||||
};
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ class Device {
|
||||
* @param readOnly whether to allow read access to the device only.
|
||||
* @param initialSend whether to send an initial @a ESC symbol in @a open().
|
||||
*/
|
||||
Device(const char* name, const bool checkDevice, const bool readOnly, const bool initialSend)
|
||||
Device(const char* name, bool checkDevice, bool readOnly, bool initialSend)
|
||||
: m_name(name), m_checkDevice(checkDevice), m_readOnly(readOnly), m_initialSend(initialSend), m_fd(-1),
|
||||
m_listener(NULL) {}
|
||||
|
||||
@@ -88,8 +88,8 @@ class Device {
|
||||
* @return the new @a Device, or NULL on error.
|
||||
* Note: the caller needs to free the created instance.
|
||||
*/
|
||||
static Device* create(const char* name, const bool checkDevice = true, const bool readOnly = false,
|
||||
const bool initialSend = false);
|
||||
static Device* create(const char* name, bool checkDevice = true, bool readOnly = false,
|
||||
bool initialSend = false);
|
||||
|
||||
/**
|
||||
* Get the transfer latency of this device.
|
||||
@@ -113,7 +113,7 @@ class Device {
|
||||
* @param value the byte value to write.
|
||||
* @return the @a result_t code.
|
||||
*/
|
||||
result_t send(const symbol_t value);
|
||||
result_t send(symbol_t value);
|
||||
|
||||
/**
|
||||
* Read a single byte from the device.
|
||||
@@ -121,7 +121,7 @@ class Device {
|
||||
* @param value the reference in which the received byte value is stored.
|
||||
* @return the result_t code.
|
||||
*/
|
||||
result_t recv(const unsigned int timeout, symbol_t& value);
|
||||
result_t recv(unsigned int timeout, symbol_t* value);
|
||||
|
||||
/**
|
||||
* Return the device name.
|
||||
@@ -165,14 +165,14 @@ class Device {
|
||||
* @param value the byte value to write.
|
||||
* @return the number of bytes written, or -1 on error.
|
||||
*/
|
||||
virtual ssize_t write(const symbol_t value) { return ::write(m_fd, &value, 1); }
|
||||
virtual ssize_t write(symbol_t value) { return ::write(m_fd, &value, 1); }
|
||||
|
||||
/**
|
||||
* Read a single byte.
|
||||
* @param value the reference in which the read byte value is stored.
|
||||
* @return the number of bytes read, or -1 on error.
|
||||
*/
|
||||
virtual ssize_t read(symbol_t& value) { return ::read(m_fd, &value, 1); }
|
||||
virtual ssize_t read(symbol_t* value) { return ::read(m_fd, value, 1); }
|
||||
|
||||
/** the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network). */
|
||||
const char* m_name;
|
||||
@@ -207,7 +207,7 @@ class SerialDevice : public Device {
|
||||
* @param readOnly whether to allow read access to the device only.
|
||||
* @param initialSend whether to send an initial @a ESC symbol in @a open().
|
||||
*/
|
||||
SerialDevice(const char* name, const bool checkDevice, const bool readOnly, const bool initialSend)
|
||||
SerialDevice(const char* name, bool checkDevice, bool readOnly, bool initialSend)
|
||||
: Device(name, checkDevice, readOnly, initialSend) {}
|
||||
|
||||
// @copydoc
|
||||
@@ -240,8 +240,8 @@ class NetworkDevice : public Device {
|
||||
* @param initialSend whether to send an initial @a ESC symbol in @a open().
|
||||
* @param udp true for UDP, false to TCP.
|
||||
*/
|
||||
NetworkDevice(const char* name, const struct sockaddr_in address, const bool readOnly, const bool initialSend,
|
||||
const bool udp)
|
||||
NetworkDevice(const char* name, const struct sockaddr_in& address, bool readOnly, bool initialSend,
|
||||
bool udp)
|
||||
: Device(name, true, readOnly, initialSend), m_address(address), m_udp(udp),
|
||||
m_buffer(NULL), m_bufSize(0), m_bufLen(0), m_bufPos(0) {}
|
||||
|
||||
@@ -269,10 +269,10 @@ class NetworkDevice : public Device {
|
||||
bool available() override;
|
||||
|
||||
// @copydoc
|
||||
ssize_t write(const symbol_t value) override;
|
||||
ssize_t write(symbol_t value) override;
|
||||
|
||||
// @copydoc
|
||||
ssize_t read(symbol_t& value) override;
|
||||
ssize_t read(symbol_t* value) override;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
+88
-77
@@ -36,21 +36,21 @@ using std::setw;
|
||||
using std::dec;
|
||||
|
||||
|
||||
result_t FileReader::readFromFile(const string filename, string& errorDescription, bool verbose,
|
||||
map<string, string>* defaults, size_t* hash, size_t* size, time_t* time) {
|
||||
result_t FileReader::readFromFile(const string& filename, bool verbose, map<string, string>* defaults,
|
||||
string* errorDescription, size_t* hash, size_t* size, time_t* time) {
|
||||
struct stat st;
|
||||
if (stat(filename.c_str(), &st) != 0) {
|
||||
errorDescription = filename;
|
||||
*errorDescription = filename;
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
errorDescription = filename+" is a directory";
|
||||
*errorDescription = filename+" is a directory";
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
ifstream ifs;
|
||||
ifs.open(filename.c_str(), ifstream::in);
|
||||
if (!ifs.is_open()) {
|
||||
errorDescription = filename;
|
||||
ifstream stream;
|
||||
stream.open(filename.c_str(), ifstream::in);
|
||||
if (!stream.is_open()) {
|
||||
*errorDescription = filename;
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
if (hash) {
|
||||
@@ -65,60 +65,56 @@ result_t FileReader::readFromFile(const string filename, string& errorDescriptio
|
||||
unsigned int lineNo = 0;
|
||||
vector<string> row;
|
||||
result_t result = RESULT_OK;
|
||||
while (ifs.peek() != EOF && result == RESULT_OK) {
|
||||
result = readLineFromStream(ifs, errorDescription, filename, lineNo, row, verbose, hash, size);
|
||||
while (stream.peek() != EOF && result == RESULT_OK) {
|
||||
result = readLineFromStream(filename, verbose, &stream, &lineNo, &row, errorDescription, hash, size);
|
||||
}
|
||||
ifs.close();
|
||||
stream.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
result_t FileReader::readLineFromStream(istream& stream, string& errorDescription,
|
||||
const string filename, unsigned int& lineNo, vector<string>& row, bool verbose,
|
||||
size_t* hash, size_t* size) {
|
||||
result_t FileReader::readLineFromStream(const string& filename, bool verbose, istream* stream,
|
||||
unsigned int* lineNo, vector<string>* row, string* errorDescription, size_t* hash, size_t* size) {
|
||||
result_t result;
|
||||
if (!splitFields(stream, row, lineNo, hash, size)) {
|
||||
errorDescription = "blank line";
|
||||
*errorDescription = "blank line";
|
||||
result = RESULT_ERR_EOF;
|
||||
} else {
|
||||
errorDescription = "";
|
||||
result = addFromFile(row, errorDescription, filename, lineNo);
|
||||
*errorDescription = "";
|
||||
result = addFromFile(filename, *lineNo, row, errorDescription);
|
||||
}
|
||||
if (result != RESULT_OK) {
|
||||
if (!verbose) {
|
||||
ostringstream error;
|
||||
error << filename << ":" << lineNo;
|
||||
if (errorDescription.length() > 0) {
|
||||
error << ": " << errorDescription;
|
||||
if (!errorDescription->empty()) {
|
||||
string error;
|
||||
formatError(filename, *lineNo, result, *errorDescription, &error);
|
||||
*errorDescription = error;
|
||||
if (verbose) {
|
||||
cout << error << endl;
|
||||
}
|
||||
errorDescription = error.str();
|
||||
return result;
|
||||
}
|
||||
if (!errorDescription.empty()) {
|
||||
cout << "error reading " << filename << ":" << lineNo << ": " << getResultCode(result) << ", "
|
||||
<< errorDescription << endl;
|
||||
} else if (!verbose) {
|
||||
return formatError(filename, *lineNo, result, "", errorDescription);
|
||||
}
|
||||
} else if (!verbose) {
|
||||
errorDescription = "";
|
||||
*errorDescription = "";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void FileReader::trim(string& str) {
|
||||
size_t pos = str.find_first_not_of(" \t");
|
||||
void FileReader::trim(string* str) {
|
||||
size_t pos = str->find_first_not_of(" \t");
|
||||
if (pos != string::npos) {
|
||||
str.erase(0, pos);
|
||||
str->erase(0, pos);
|
||||
}
|
||||
pos = str.find_last_not_of(" \t");
|
||||
pos = str->find_last_not_of(" \t");
|
||||
if (pos != string::npos) {
|
||||
str.erase(pos+1);
|
||||
str->erase(pos+1);
|
||||
}
|
||||
}
|
||||
|
||||
void FileReader::tolower(string& str) {
|
||||
transform(str.begin(), str.end(), str.begin(), ::tolower);
|
||||
void FileReader::tolower(string* str) {
|
||||
transform(str->begin(), str->end(), str->begin(), ::tolower);
|
||||
}
|
||||
|
||||
static size_t hashFunction(const string str) {
|
||||
static size_t hashFunction(const string& str) {
|
||||
size_t hash = 0;
|
||||
for (char c : str) {
|
||||
hash = (31 * hash) ^ c;
|
||||
@@ -126,27 +122,27 @@ static size_t hashFunction(const string str) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
bool FileReader::splitFields(istream& ifs, vector<string>& row, unsigned int& lineNo,
|
||||
bool FileReader::splitFields(istream* stream, vector<string>* row, unsigned int* lineNo,
|
||||
size_t* hash, size_t* size) {
|
||||
row.clear();
|
||||
row->clear();
|
||||
string line;
|
||||
bool quotedText = false, wasQuoted = false;
|
||||
ostringstream field;
|
||||
char prev = FIELD_SEPARATOR;
|
||||
bool empty = true, read = false;
|
||||
while (getline(ifs, line)) {
|
||||
while (getline(*stream, line)) {
|
||||
read = true;
|
||||
lineNo++;
|
||||
trim(line);
|
||||
++(*lineNo);
|
||||
trim(&line);
|
||||
size_t length = line.size();
|
||||
if (size) {
|
||||
*size += length + 1; // normalized with trailing endl
|
||||
}
|
||||
if (hash) {
|
||||
*hash ^= (hashFunction(line) ^ (length << (7 * (lineNo % 5)))) & 0xffffffff;
|
||||
*hash ^= (hashFunction(line) ^ (length << (7 * (*lineNo % 5)))) & 0xffffffff;
|
||||
}
|
||||
if (!quotedText && (length == 0 || line[0] == '#' || (line.length() > 1 && line[0] == '/' && line[1] == '/'))) {
|
||||
if (lineNo == 1) {
|
||||
if (*lineNo == 1) {
|
||||
break; // keep empty first line for applying default header
|
||||
}
|
||||
continue; // skip empty lines and comments
|
||||
@@ -159,9 +155,9 @@ bool FileReader::splitFields(istream& ifs, vector<string>& row, unsigned int& li
|
||||
field << ch;
|
||||
} else {
|
||||
string str = field.str();
|
||||
trim(str);
|
||||
trim(&str);
|
||||
empty &= str.empty();
|
||||
row.push_back(str);
|
||||
row->push_back(str);
|
||||
field.str("");
|
||||
wasQuoted = false;
|
||||
}
|
||||
@@ -197,37 +193,52 @@ bool FileReader::splitFields(istream& ifs, vector<string>& row, unsigned int& li
|
||||
}
|
||||
}
|
||||
string str = field.str();
|
||||
trim(str);
|
||||
trim(&str);
|
||||
if (empty && str.empty()) {
|
||||
row.clear();
|
||||
row->clear();
|
||||
return read;
|
||||
}
|
||||
row.push_back(str);
|
||||
row->push_back(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
result_t FileReader::formatError(const string& filename, unsigned int lineNo, result_t result,
|
||||
const string& error, string* errorDescription) {
|
||||
ostringstream str;
|
||||
if (!errorDescription->empty()) {
|
||||
str << *errorDescription << ", ";
|
||||
}
|
||||
str << filename << ":" << static_cast<unsigned>(lineNo) << ": " << getResultCode(result);
|
||||
if (!error.empty()) {
|
||||
str << ", " << error;
|
||||
}
|
||||
*errorDescription = str.str();
|
||||
return result;
|
||||
}
|
||||
|
||||
string MappedFileReader::normalizeLanguage(string lang) {
|
||||
tolower(lang);
|
||||
if (lang.size() > 2) {
|
||||
size_t pos = lang.find('.');
|
||||
|
||||
const string MappedFileReader::normalizeLanguage(const string& lang) {
|
||||
string normLang = lang;
|
||||
tolower(&normLang);
|
||||
if (normLang.size() > 2) {
|
||||
size_t pos = normLang.find('.');
|
||||
if (pos == string::npos) {
|
||||
pos = lang.size();
|
||||
pos = normLang.size();
|
||||
}
|
||||
size_t strip = lang.find('_');
|
||||
size_t strip = normLang.find('_');
|
||||
if (strip == string::npos || strip > pos) {
|
||||
strip = pos;
|
||||
}
|
||||
if (strip > 2) {
|
||||
strip = 2;
|
||||
}
|
||||
lang = lang.substr(0, strip);
|
||||
return normLang.substr(0, strip);
|
||||
}
|
||||
return lang;
|
||||
return normLang;
|
||||
}
|
||||
|
||||
result_t MappedFileReader::readFromFile(const string filename, string& errorDescription, bool verbose,
|
||||
map<string, string>* defaults, size_t* hash, size_t* size, time_t* time) {
|
||||
result_t MappedFileReader::readFromFile(const string& filename, bool verbose, map<string, string>* defaults,
|
||||
string* errorDescription, size_t* hash, size_t* size, time_t* time) {
|
||||
m_mutex.lock();
|
||||
m_columnNames.clear();
|
||||
m_lastDefaults.clear();
|
||||
@@ -237,47 +248,47 @@ result_t MappedFileReader::readFromFile(const string filename, string& errorDesc
|
||||
}
|
||||
size_t lastSep = filename.find_last_of('/');
|
||||
string defaultsPart = lastSep == string::npos ? filename : filename.substr(lastSep+1);
|
||||
extractDefaultsFromFilename(defaultsPart, m_lastDefaults[""]);
|
||||
result_t result = FileReader::readFromFile(filename, errorDescription, verbose, defaults, hash, size, time);
|
||||
extractDefaultsFromFilename(defaultsPart, &m_lastDefaults[""], NULL, NULL, NULL);
|
||||
result_t result = FileReader::readFromFile(filename, verbose, defaults, errorDescription, hash, size, time);
|
||||
m_mutex.unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
result_t MappedFileReader::addFromFile(vector<string>& row, string& errorDescription,
|
||||
const string filename, unsigned int lineNo) {
|
||||
result_t MappedFileReader::addFromFile(const string& filename, unsigned int lineNo, vector<string>* row,
|
||||
string* errorDescription) {
|
||||
result_t result;
|
||||
if (lineNo == 1) { // first line defines column names
|
||||
result = getFieldMap(row, errorDescription, m_preferLanguage);
|
||||
result = getFieldMap(m_preferLanguage, row, errorDescription);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
if (row.empty()) {
|
||||
errorDescription = "missing field map";
|
||||
if (row->empty()) {
|
||||
*errorDescription = "missing field map";
|
||||
return RESULT_ERR_EOF;
|
||||
}
|
||||
m_columnNames = row;
|
||||
m_columnNames = *row;
|
||||
return RESULT_OK;
|
||||
}
|
||||
if (row.empty()) {
|
||||
if (row->empty()) {
|
||||
return RESULT_OK;
|
||||
}
|
||||
if (m_columnNames.empty()) {
|
||||
errorDescription = "missing field map";
|
||||
*errorDescription = "missing field map";
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
map<string, string> rowMapped;
|
||||
vector< map<string, string> > subRowsMapped;
|
||||
bool isDefault = m_supportsDefaults && !row[0].empty() && row[0][0] == '*';
|
||||
bool isDefault = m_supportsDefaults && !(*row)[0].empty() && (*row)[0][0] == '*';
|
||||
if (isDefault) {
|
||||
row[0] = row[0].substr(1);
|
||||
(*row)[0].erase(0, 1);
|
||||
}
|
||||
size_t lastRepeatStart = UINT_MAX;
|
||||
map<string, string>* lastMappedRow = &rowMapped;
|
||||
bool empty = true;
|
||||
for (size_t colIdx = 0, colNameIdx = 0; colIdx < row.size(); colIdx++, colNameIdx++) {
|
||||
for (size_t colIdx = 0, colNameIdx = 0; colIdx < row->size(); colIdx++, colNameIdx++) {
|
||||
if (colNameIdx >= m_columnNames.size()) {
|
||||
if (lastRepeatStart == UINT_MAX) {
|
||||
errorDescription = "named columns exceeded";
|
||||
*errorDescription = "named columns exceeded";
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
colNameIdx = lastRepeatStart;
|
||||
@@ -297,7 +308,7 @@ result_t MappedFileReader::addFromFile(vector<string>& row, string& errorDescrip
|
||||
} else if (columnName == SKIP_COLUMN) {
|
||||
continue;
|
||||
}
|
||||
string value = row[colIdx];
|
||||
string value = (*row)[colIdx];
|
||||
empty &= value.empty();
|
||||
(*lastMappedRow)[columnName] = value;
|
||||
}
|
||||
@@ -308,12 +319,12 @@ result_t MappedFileReader::addFromFile(vector<string>& row, string& errorDescrip
|
||||
}
|
||||
}
|
||||
if (isDefault) {
|
||||
return addDefaultFromFile(rowMapped, subRowsMapped, errorDescription, filename, lineNo);
|
||||
return addDefaultFromFile(filename, lineNo, &rowMapped, &subRowsMapped, errorDescription);
|
||||
}
|
||||
return addFromFile(rowMapped, subRowsMapped, errorDescription, filename, lineNo);
|
||||
return addFromFile(filename, lineNo, &rowMapped, &subRowsMapped, errorDescription);
|
||||
}
|
||||
|
||||
string MappedFileReader::combineRow(const map<string, string>& row) {
|
||||
const string MappedFileReader::combineRow(const map<string, string>& row) {
|
||||
ostringstream ostream;
|
||||
bool first = true;
|
||||
for (auto entry : row) {
|
||||
|
||||
+51
-39
@@ -79,76 +79,88 @@ class FileReader {
|
||||
/**
|
||||
* Read the definitions from a file.
|
||||
* @param filename the name of the file being read.
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @param verbose whether to verbosely log problems.
|
||||
* @param defaults the default values by name (potentially overwritten by file name), or NULL to not use defaults.
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @param hash optional pointer to a @a size_t value for storing the hash of the file, or NULL.
|
||||
* @param size optional pointer to a @a size_t value for storing the normalized size of the file, or NULL.
|
||||
* @param time optional pointer to a @a time_t value for storing the modification time of the file, or NULL.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t readFromFile(const string filename, string& errorDescription, bool verbose = false,
|
||||
map<string, string>* defaults = NULL, size_t* hash = NULL, size_t* size = NULL, time_t* time = NULL);
|
||||
virtual result_t readFromFile(const string& filename, bool verbose, map<string, string>* defaults,
|
||||
string* errorDescription, size_t* hash, size_t* size, time_t* time);
|
||||
|
||||
/**
|
||||
* Read a single line definition from the stream.
|
||||
* @param stream the @a istream to read from.
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @param filename the name of the file being read.
|
||||
* @param verbose whether to verbosely log problems.
|
||||
* @param stream the @a istream to read from.
|
||||
* @param lineNo the last line number (incremented with each line read).
|
||||
* @param row the definition row to clear and update with the read data (for performance reasons only).
|
||||
* @param verbose whether to verbosely log problems.
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @param hash optional pointer to a @a size_t value for updating with the hash of the line, or NULL.
|
||||
* @param size optional pointer to a @a size_t value for updating with the normalized length of the line, or NULL.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t readLineFromStream(istream& stream, string& errorDescription,
|
||||
const string filename, unsigned int& lineNo, vector<string>& row, bool verbose = false,
|
||||
size_t* hash = NULL, size_t* size = NULL);
|
||||
virtual result_t readLineFromStream(const string& filename, bool verbose, istream* stream,
|
||||
unsigned int* lineNo, vector<string>* row, string* errorDescription, size_t* hash, size_t* size);
|
||||
|
||||
/**
|
||||
* Add a definition that was read from a file.
|
||||
* @param row the definition row.
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @param filename the name of the file being read.
|
||||
* @param lineNo the current line number in the file being read.
|
||||
* @param row the definition row (allowed to be modified).
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t addFromFile(vector<string>& row, string& errorDescription,
|
||||
const string filename, unsigned int lineNo) = 0;
|
||||
virtual result_t addFromFile(const string& filename, unsigned int lineNo, vector<string>* row,
|
||||
string* errorDescription) = 0;
|
||||
|
||||
/**
|
||||
* Left and right trim the string.
|
||||
* @param str the @a string to trim.
|
||||
*/
|
||||
static void trim(string& str);
|
||||
static void trim(string* str);
|
||||
|
||||
/**
|
||||
* Convert all upper case characters in the string to lower case.
|
||||
* @param str the @a string to convert.
|
||||
*/
|
||||
static void tolower(string& str);
|
||||
static void tolower(string* str);
|
||||
|
||||
/**
|
||||
* Split the next line(s) from the @a istream into fields.
|
||||
* @param ifs the @a istream to read from.
|
||||
* @param stream the @a istream to read from.
|
||||
* @param row the @a vector to which to add the fields. This will be empty for completely empty and comment lines.
|
||||
* @param lineNo the current line number (incremented with each line read).
|
||||
* @param hash optional pointer to a @a size_t value for combining the hash of the line with, or NULL.
|
||||
* @param size optional pointer to a @a size_t value to add the trimmed line length to, or NULL.
|
||||
* @return true if there are more lines to read, false when there are no more lines left.
|
||||
*/
|
||||
static bool splitFields(istream& ifs, vector<string>& row, unsigned int& lineNo,
|
||||
static bool splitFields(istream* stream, vector<string>* row, unsigned int* lineNo,
|
||||
size_t* hash = NULL, size_t* size = NULL);
|
||||
|
||||
/**
|
||||
* Format the specified hash as 8 hex digits to the output stream.
|
||||
* @param hash the hash code.
|
||||
* @param str the @a ostream to write to.
|
||||
* @param stream the @a ostream to write to.
|
||||
*/
|
||||
static void formatHash(size_t hash, ostream& str) {
|
||||
str << std::hex << std::setw(8) << std::setfill('0') << (hash & 0xffffffff) << std::dec << std::setw(0);
|
||||
static void formatHash(size_t hash, ostream* stream) {
|
||||
*stream << std::hex << std::setw(8) << std::setfill('0') << (hash & 0xffffffff) << std::dec << std::setw(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the error description with the input data.
|
||||
* @param filename the name of the file.
|
||||
* @param lineNo the line number in the file.
|
||||
* @param row the definition row.
|
||||
* @param result the result code.
|
||||
* @param error the error message.
|
||||
* @param errorDescription a string in which to store the error description.
|
||||
* @return the result code.
|
||||
*/
|
||||
static result_t formatError(const string& filename, unsigned int lineNo, result_t result,
|
||||
const string& error, string* errorDescription);
|
||||
};
|
||||
|
||||
|
||||
@@ -163,8 +175,8 @@ class MappedFileReader : public FileReader {
|
||||
* @param supportsDefaults whether this instance supports rows with defaults (starting with a star).
|
||||
* @param preferLanguage the preferred language code, or empty.
|
||||
*/
|
||||
explicit MappedFileReader(bool supportsDefaults, const string preferLanguage = "")
|
||||
: FileReader(), m_supportsDefaults(supportsDefaults), m_preferLanguage(normalizeLanguage(preferLanguage)) {
|
||||
explicit MappedFileReader(bool supportsDefaults, const string& preferLanguage = "")
|
||||
: FileReader(), m_supportsDefaults(supportsDefaults), m_preferLanguage(normalizeLanguage(preferLanguage)) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,11 +193,11 @@ class MappedFileReader : public FileReader {
|
||||
* @param lang the language string to normalize.
|
||||
* @return the normalized language code.
|
||||
*/
|
||||
static string normalizeLanguage(string lang);
|
||||
static const string normalizeLanguage(const string& lang);
|
||||
|
||||
// @copydoc
|
||||
result_t readFromFile(const string filename, string& errorDescription, bool verbose = false,
|
||||
map<string, string>* defaults = NULL, size_t* hash = NULL, size_t* size = NULL, time_t* time = NULL) override;
|
||||
result_t readFromFile(const string& filename, bool verbose, map<string, string>* defaults,
|
||||
string* errorDescription, size_t* hash, size_t* size, time_t* time) override;
|
||||
|
||||
/**
|
||||
* Extract default values from the file name.
|
||||
@@ -196,14 +208,14 @@ class MappedFileReader : public FileReader {
|
||||
* @param hardware a pointer to a in which to store the numeric hardware version, or NULL.
|
||||
* @return true if the minimum parts were extracted, false otherwise.
|
||||
*/
|
||||
virtual bool extractDefaultsFromFilename(string filename, map<string, string>& defaults,
|
||||
symbol_t* destAddress = NULL, unsigned int* software = NULL, unsigned int* hardware = NULL) const {
|
||||
virtual bool extractDefaultsFromFilename(const string& filename, map<string, string>* defaults,
|
||||
symbol_t* destAddress, unsigned int* software, unsigned int* hardware) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// @copydoc
|
||||
result_t addFromFile(vector<string>& row, string& errorDescription,
|
||||
const string filename, unsigned int lineNo) override;
|
||||
result_t addFromFile(const string& filename, unsigned int lineNo, vector<string>* row,
|
||||
string* errorDescription) override;
|
||||
|
||||
/**
|
||||
* Get the field mapping from the given first line.
|
||||
@@ -214,7 +226,7 @@ class MappedFileReader : public FileReader {
|
||||
* @param preferLanguage the preferred language code (up to 2 characters), or empty.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t getFieldMap(vector<string>& row, string& errorDescription, const string preferLanguage) const = 0;
|
||||
virtual result_t getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const = 0;
|
||||
|
||||
/**
|
||||
* Add a default row that was read from a file.
|
||||
@@ -225,23 +237,23 @@ class MappedFileReader : public FileReader {
|
||||
* @param lineNo the current line number in the file being read.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t addDefaultFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
|
||||
string& errorDescription, const string filename, unsigned int lineNo) {
|
||||
errorDescription = "defaults not supported";
|
||||
virtual result_t addDefaultFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
|
||||
vector< map<string, string> >* subRows, string* errorDescription) {
|
||||
*errorDescription = "defaults not supported";
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a definition that was read from a file.
|
||||
* @param row the main definition row by field name.
|
||||
* @param subRows the sub definition rows, each by field name.
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @param filename the name of the file being read.
|
||||
* @param lineNo the current line number in the file being read.
|
||||
* @param row the main definition row by field name (may be modified).
|
||||
* @param subRows the sub definition rows, each by field name (may be modified).
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
|
||||
string& errorDescription, const string filename, unsigned int lineNo) = 0;
|
||||
virtual result_t addFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
|
||||
vector< map<string, string> >* subRows, string* errorDescription) = 0;
|
||||
|
||||
/**
|
||||
* @return a reference to all previously extracted default values by type and field name.
|
||||
@@ -262,7 +274,7 @@ class MappedFileReader : public FileReader {
|
||||
* @param row the mapped row.
|
||||
* @return the combined string.
|
||||
*/
|
||||
static string combineRow(const map<string, string>& row);
|
||||
static const string combineRow(const map<string, string>& row);
|
||||
|
||||
private:
|
||||
/** whether this instance supports rows with defaults (starting with a star). */
|
||||
|
||||
+439
-434
File diff suppressed because it is too large
Load Diff
+165
-180
@@ -92,12 +92,12 @@ class Message : public AttributedItem {
|
||||
* @param pollPriority the priority for polling, or 0 for no polling at all.
|
||||
* @param condition the @a Condition for this message, or NULL.
|
||||
*/
|
||||
Message(const string circuit, const string level, const string name,
|
||||
const bool isWrite, const bool isPassive, const map<string, string>& attributes,
|
||||
const symbol_t srcAddress, const symbol_t dstAddress,
|
||||
const vector<symbol_t> id,
|
||||
const DataField* data, const bool deleteData,
|
||||
const size_t pollPriority = 0,
|
||||
Message(const string& circuit, const string& level, const string& name,
|
||||
bool isWrite, bool isPassive, const map<string, string>& attributes,
|
||||
symbol_t srcAddress, symbol_t dstAddress,
|
||||
const vector<symbol_t>& id,
|
||||
const DataField* data, bool deleteData,
|
||||
size_t pollPriority = 0,
|
||||
Condition* condition = NULL);
|
||||
|
||||
|
||||
@@ -113,9 +113,9 @@ class Message : public AttributedItem {
|
||||
* @param data the @a DataField for encoding/decoding the message.
|
||||
* @param deleteData whether to delete the @a DataField during destruction.
|
||||
*/
|
||||
Message(const string circuit, const string level, const string name,
|
||||
const symbol_t pb, const symbol_t sb,
|
||||
const bool broadcast, const DataField* data, const bool deleteData);
|
||||
Message(const string& circuit, const string& level, const string& name,
|
||||
symbol_t pb, symbol_t sb,
|
||||
bool broadcast, const DataField* data, bool deleteData);
|
||||
|
||||
|
||||
public:
|
||||
@@ -134,9 +134,8 @@ class Message : public AttributedItem {
|
||||
* @param dstAddress the destination address, or @a SYN for any (set later).
|
||||
* @return the key for the ID.
|
||||
*/
|
||||
static uint64_t createKey(const vector<symbol_t> id,
|
||||
const bool isWrite, const bool isPassive,
|
||||
const symbol_t srcAddress, const symbol_t dstAddress);
|
||||
static uint64_t createKey(const vector<symbol_t>& id, bool isWrite, bool isPassive, symbol_t srcAddress,
|
||||
symbol_t dstAddress);
|
||||
|
||||
/**
|
||||
* Calculate the key for the @a MasterSymbolString.
|
||||
@@ -154,7 +153,7 @@ class Message : public AttributedItem {
|
||||
* @param broadcast true for broadcast scan message, false for scan message to be sent to a slave address.
|
||||
* @return the key for the scan message.
|
||||
*/
|
||||
static uint64_t createKey(const symbol_t pb, const symbol_t sb, const bool broadcast);
|
||||
static uint64_t createKey(symbol_t pb, symbol_t sb, bool broadcast);
|
||||
|
||||
/**
|
||||
* Get the length field from the key.
|
||||
@@ -169,26 +168,29 @@ class Message : public AttributedItem {
|
||||
* @param id the vector to which to add the parsed values.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
static result_t parseId(string input, vector<symbol_t>& id);
|
||||
static result_t parseId(const string& input, vector<symbol_t>* id);
|
||||
|
||||
/**
|
||||
* Factory method for creating new instances.
|
||||
* @param row the mapped message definition row.
|
||||
* @param subRows the mapped field definition rows.
|
||||
* @param rowDefaults the mapped message definition defaults.
|
||||
* @param subRowDefaults the mapped field definition defaults.
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @param condition the @a Condition instance for the message, or NULL.
|
||||
* @param filename the name of the file being read.
|
||||
* @param templates the @a DataFieldTemplates to be referenced by name, or NULL.
|
||||
* @param rowDefaults the mapped message definition defaults.
|
||||
* @param subRowDefaults the mapped field definition defaults.
|
||||
* @param typeStr the single type of message to create.
|
||||
* @param condition the @a Condition instance for the message, or NULL.
|
||||
* @param row the mapped message definition row (may be modified).
|
||||
* @param subRows the mapped field definition rows (may be modified).
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @param messages the @a vector to which to add created instances.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
* Note: the caller needs to free the created instances.
|
||||
*/
|
||||
static result_t create(map<string, string> row, vector< map<string, string> > subRows,
|
||||
map<string, map<string, string> >& rowDefaults, map<string, vector< map<string, string> > >& subRowDefaults,
|
||||
string& errorDescription, Condition* condition, const string filename, DataFieldTemplates* templates,
|
||||
vector<Message*>& messages);
|
||||
static result_t create(const string& filename, const DataFieldTemplates* templates,
|
||||
const map<string, map<string, string> >& rowDefaults,
|
||||
const map<string, vector< map<string, string> > >& subRowDefaults,
|
||||
const string& typeStr, Condition* condition,
|
||||
map<string, string>* row, vector< map<string, string> >* subRows,
|
||||
string* errorDescription, vector<Message*>* messages);
|
||||
|
||||
/**
|
||||
* Create a new scan @a Message instance.
|
||||
@@ -200,11 +202,11 @@ class Message : public AttributedItem {
|
||||
/**
|
||||
* Extract the known field names from the input string.
|
||||
* @param str the input string with the field names separated by @a FIELD_SEPARATOR.
|
||||
* @param fields the vector to update with the extracted normalized field names with.
|
||||
* @param checkAbbreviated true to also check for abbreviated field names.
|
||||
* @param fields the vector to update with the extracted normalized field names with.
|
||||
* @return true when all fields are valid.
|
||||
*/
|
||||
static bool extractFieldNames(string str, vector<string>& fields, bool checkAbbreviated = true);
|
||||
static bool extractFieldNames(const string& str, bool checkAbbreviated, vector<string>* fields);
|
||||
|
||||
/**
|
||||
* Set that this is a special scanning @a Message instance.
|
||||
@@ -224,8 +226,7 @@ class Message : public AttributedItem {
|
||||
* @param circuit the new circuit name, or empty to use the current circuit name.
|
||||
* @return the derived @a Message instance.
|
||||
*/
|
||||
virtual Message* derive(const symbol_t dstAddress, const symbol_t srcAddress = SYN,
|
||||
const string circuit = "") const;
|
||||
virtual Message* derive(symbol_t dstAddress, symbol_t srcAddress, const string& circuit) const;
|
||||
|
||||
/**
|
||||
* Derive a new @a Message from this message.
|
||||
@@ -233,7 +234,7 @@ class Message : public AttributedItem {
|
||||
* @param extendCircuit whether to extend the current circuit name with a dot and the new destination address in hex.
|
||||
* @return the derived @a ScanMessage instance.
|
||||
*/
|
||||
Message* derive(const symbol_t dstAddress, const bool extendCircuit) const;
|
||||
Message* derive(symbol_t dstAddress, bool extendCircuit) const;
|
||||
|
||||
/**
|
||||
* Get the optional circuit name.
|
||||
@@ -254,7 +255,7 @@ class Message : public AttributedItem {
|
||||
* level to check.
|
||||
* @return true when access is granted.
|
||||
*/
|
||||
bool hasLevel(const string levels, bool includeEmpty = true) const {
|
||||
bool hasLevel(const string& levels, bool includeEmpty = true) const {
|
||||
return m_level.empty() ? (includeEmpty || levels.empty()) : checkLevel(m_level, levels);
|
||||
}
|
||||
|
||||
@@ -264,14 +265,14 @@ class Message : public AttributedItem {
|
||||
* @param checkLevels the access levels to check against, separated by semicolon.
|
||||
* @return whether the access level matches.
|
||||
*/
|
||||
static bool checkLevel(const string level, const string checkLevels);
|
||||
static bool checkLevel(const string& level, const string& checkLevels);
|
||||
|
||||
/**
|
||||
* Get the specified field name.
|
||||
* @param fieldIndex the index of the field.
|
||||
* @return the field name, or the index as string if not unique or not available.
|
||||
*/
|
||||
virtual string getFieldName(const ssize_t fieldIndex) const { return m_data->getName(fieldIndex); }
|
||||
virtual string getFieldName(ssize_t fieldIndex) const { return m_data->getName(fieldIndex); }
|
||||
|
||||
/**
|
||||
* Get whether this is a write message.
|
||||
@@ -329,14 +330,14 @@ class Message : public AttributedItem {
|
||||
* @param index the variable in which to store the message part index, or NULL to ignore.
|
||||
* @return true if the ID matches, false otherwise.
|
||||
*/
|
||||
virtual bool checkId(const MasterSymbolString& master, size_t* index = NULL) const;
|
||||
virtual bool checkId(const MasterSymbolString& master, size_t* index) const;
|
||||
|
||||
/**
|
||||
* Check the ID against the other @a Message.
|
||||
* @param other the other @a Message to check against.
|
||||
* @return true if the ID matches, false otherwise.
|
||||
*/
|
||||
virtual bool checkId(Message& other) const;
|
||||
virtual bool checkId(const Message& other) const;
|
||||
|
||||
/**
|
||||
* Return the key for storing in @a MessageMap.
|
||||
@@ -349,7 +350,7 @@ class Message : public AttributedItem {
|
||||
* @param dstAddress the destination address for the derivation.
|
||||
* @return the derived key for storing in @a MessageMap.
|
||||
*/
|
||||
uint64_t getDerivedKey(const symbol_t dstAddress) const;
|
||||
uint64_t getDerivedKey(symbol_t dstAddress) const;
|
||||
|
||||
/**
|
||||
* Get the polling priority, or 0 for no polling at all.
|
||||
@@ -362,7 +363,7 @@ class Message : public AttributedItem {
|
||||
* @param priority the polling priority, or 0 for no polling at all.
|
||||
* @return true when the priority was changed and polling was not enabled before, false otherwise.
|
||||
*/
|
||||
bool setPollPriority(size_t priority);
|
||||
bool setPollPriority(const size_t priority);
|
||||
|
||||
/**
|
||||
* Set the poll priority suitable for resolving a @a Condition.
|
||||
@@ -396,30 +397,28 @@ class Message : public AttributedItem {
|
||||
|
||||
/**
|
||||
* Prepare the master @a SymbolString for sending a query or command to the bus.
|
||||
* @param srcAddress the source address to set.
|
||||
* @param master the @a MasterSymbolString for writing symbols to.
|
||||
* @param input the @a istringstream to parse the formatted value(s) from.
|
||||
* @param separator the separator character between multiple fields.
|
||||
* @param dstAddress the destination address to set, or @a SYN to keep the address defined during construction.
|
||||
* @param index the index of the part to prepare.
|
||||
* @param srcAddress the source address to set.
|
||||
* @param dstAddress the destination address to set, or @a SYN to keep the address defined during construction.
|
||||
* @param separator the separator character between multiple fields (e.g. @a UI_FIELD_SEPARATOR).
|
||||
* @param input the @a istringstream to parse the formatted value(s) from.
|
||||
* @param master the @a MasterSymbolString for writing symbols to.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t prepareMaster(const symbol_t srcAddress, MasterSymbolString& master,
|
||||
istringstream& input, char separator = UI_FIELD_SEPARATOR,
|
||||
const symbol_t dstAddress = SYN, size_t index = 0);
|
||||
result_t prepareMaster(size_t index, symbol_t srcAddress, symbol_t dstAddress,
|
||||
char separator, istringstream* input, MasterSymbolString* master);
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Prepare a part of the master data @a SymbolString for sending (everything including NN).
|
||||
* @param master the @a MasterSymbolString for writing symbols to.
|
||||
* @param input the @a istringstream to parse the formatted value(s) from.
|
||||
* @param separator the separator character between multiple fields.
|
||||
* @param index the index of the part to prepare.
|
||||
* @param separator the separator character between multiple fields.
|
||||
* @param input the @a istringstream to parse the formatted value(s) from.
|
||||
* @param master the @a MasterSymbolString for writing symbols to.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t prepareMasterPart(MasterSymbolString& master, istringstream& input, char separator,
|
||||
size_t index);
|
||||
virtual result_t prepareMasterPart(size_t index, char separator, istringstream* input, MasterSymbolString* master);
|
||||
|
||||
|
||||
public:
|
||||
@@ -429,7 +428,7 @@ class Message : public AttributedItem {
|
||||
* @param slave the @a SlaveSymbolString for writing symbols to.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t prepareSlave(istringstream& input, SlaveSymbolString& slave);
|
||||
virtual result_t prepareSlave(istringstream* input, SlaveSymbolString* slave);
|
||||
|
||||
/**
|
||||
* Store the last seen master and slave data.
|
||||
@@ -437,68 +436,57 @@ class Message : public AttributedItem {
|
||||
* @param slave the last seen @a SlaveSymbolString.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t storeLastData(MasterSymbolString& master, SlaveSymbolString& slave);
|
||||
virtual result_t storeLastData(const MasterSymbolString& master, const SlaveSymbolString& slave);
|
||||
|
||||
/**
|
||||
* Store last seen master data.
|
||||
* @param data the last @a MasterSymbolString.
|
||||
* @param index the index of the part to store.
|
||||
* @param data the last @a MasterSymbolString.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t storeLastData(MasterSymbolString& data, size_t index);
|
||||
virtual result_t storeLastData(size_t index, const MasterSymbolString& data);
|
||||
|
||||
/**
|
||||
* Store last seen slave data.
|
||||
* @param data the last seen @a SlaveSymbolString.
|
||||
* @param index the index of the part to store.
|
||||
* @param data the last seen @a SlaveSymbolString.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t storeLastData(SlaveSymbolString& data, size_t index);
|
||||
virtual result_t storeLastData(size_t index, const SlaveSymbolString& data);
|
||||
|
||||
/**
|
||||
* Decode the value from the last stored master data.
|
||||
* @param output the @a ostringstream to append the formatted value to.
|
||||
* @param outputFormat the @a OutputFormat options to use.
|
||||
* Decode the value from the last stored master or slave data.
|
||||
* @param master true for deocding the master data, false for slave.
|
||||
* @param leadingSeparator whether to prepend a separator before the formatted value.
|
||||
* @param fieldName the optional name of a field to limit the output to.
|
||||
* @param fieldIndex the optional index of the named field to limit the output to, or -1.
|
||||
* @param outputFormat the @a OutputFormat options to use.
|
||||
* @param output the @a ostream to append the formatted value to.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t decodeLastMasterData(ostringstream& output, OutputFormat outputFormat = 0,
|
||||
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const;
|
||||
virtual result_t decodeLastData(bool master, bool leadingSeparator, const char* fieldName,
|
||||
ssize_t fieldIndex, OutputFormat outputFormat, ostream* output) const;
|
||||
|
||||
/**
|
||||
* Decode the value from the last stored slave data.
|
||||
* @param output the @a ostringstream to append the formatted value to.
|
||||
* @param outputFormat the @a OutputFormat options to use.
|
||||
* Decode the value from the last stored master and slave data.
|
||||
* @param leadingSeparator whether to prepend a separator before the formatted value.
|
||||
* @param fieldName the optional name of a field to limit the output to.
|
||||
* @param fieldIndex the optional index of the named field to limit the output to, or -1.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t decodeLastSlaveData(ostringstream& output, OutputFormat outputFormat = 0,
|
||||
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const;
|
||||
|
||||
/**
|
||||
* Decode the value from the last stored data.
|
||||
* @param output the @a ostringstream to append the formatted value to.
|
||||
* @param outputFormat the @a OutputFormat options to use.
|
||||
* @param leadingSeparator whether to prepend a separator before the formatted value.
|
||||
* @param fieldName the optional name of a field to limit the output to.
|
||||
* @param fieldIndex the optional index of the named field to limit the output to, or -1.
|
||||
* @param output the @a ostream to append the formatted value to.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t decodeLastData(ostringstream& output, OutputFormat outputFormat = 0,
|
||||
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const;
|
||||
virtual result_t decodeLastData(bool leadingSeparator, const char* fieldName,
|
||||
ssize_t fieldIndex, OutputFormat outputFormat, ostream* output) const;
|
||||
|
||||
/**
|
||||
* Decode a particular numeric field value from the last stored data.
|
||||
* @param output the variable in which to store the value.
|
||||
* @param fieldName the name of the field to decode, or NULL for the first field.
|
||||
* @param fieldIndex the optional index of the named field, or -1.
|
||||
* @param output the variable in which to store the value.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t decodeLastDataNumField(unsigned int& output, const char* fieldName, ssize_t fieldIndex = -1) const;
|
||||
virtual result_t decodeLastDataNumField(const char* fieldName, ssize_t fieldIndex, unsigned int* output) const;
|
||||
|
||||
/**
|
||||
* Get the last seen master data.
|
||||
@@ -539,36 +527,36 @@ class Message : public AttributedItem {
|
||||
|
||||
/**
|
||||
* Write the message definition header or parts of it to the @a ostream.
|
||||
* @param output the @a ostream to append the formatted value to.
|
||||
* @param fieldNames the list of field names to write, or NULL for all.
|
||||
* @param output the @a ostream to append the formatted value to.
|
||||
*/
|
||||
static void dumpHeader(ostream& output, vector<string>* fieldNames = NULL);
|
||||
static void dumpHeader(const vector<string>* fieldNames, ostream* output);
|
||||
|
||||
/**
|
||||
* Write the message definition or parts of it to the @a ostream.
|
||||
* @param output the @a ostream to append the formatted value to.
|
||||
* @param fieldNames the list of field names to write, or NULL for all.
|
||||
* @param withConditions whether to include the optional conditions prefix.
|
||||
* @param output the @a ostream to append the formatted value to.
|
||||
*/
|
||||
void dump(ostream& output, vector<string>* fieldNames = NULL, bool withConditions = false) const;
|
||||
void dump(const vector<string>* fieldNames, bool withConditions, ostream* output) const;
|
||||
|
||||
/**
|
||||
* Write the specified field to the @a ostream.
|
||||
* @param output the @a ostream to append the formatted value to.
|
||||
* @param fieldName the field name to write.
|
||||
* @param withConditions whether to include the optional conditions prefix.
|
||||
* @param output the @a ostream to append the formatted value to.
|
||||
*/
|
||||
virtual void dumpField(ostream& output, string fieldName, bool withConditions = false) const;
|
||||
virtual void dumpField(const string& fieldName, bool withConditions, ostream* output) const;
|
||||
|
||||
/**
|
||||
* Decode the message from the last stored data.
|
||||
* @param output the @a ostringstream to append the decoded value(s) to.
|
||||
* @param outputFormat the @a OutputFormat options to use.
|
||||
* @param leadingSeparator whether to prepend a separator before the first value.
|
||||
* @param fields the list of message and/or data field fields to write, or NULL for all.
|
||||
* @param outputFormat the @a OutputFormat options to use.
|
||||
* @param output the @a ostringstream to append the decoded value(s) to.
|
||||
*/
|
||||
virtual void decode(ostringstream& output, OutputFormat outputFormat = 0, bool leadingSeparator = false,
|
||||
vector<string>* fields = NULL) const;
|
||||
virtual void decode(bool leadingSeparator, const vector<string>* fields,
|
||||
OutputFormat outputFormat, ostringstream* output) const;
|
||||
|
||||
protected:
|
||||
/** the optional circuit name. */
|
||||
@@ -676,29 +664,28 @@ class ChainedMessage : public Message {
|
||||
* @param pollPriority the priority for polling, or 0 for no polling at all.
|
||||
* @param condition the @a Condition for this message, or NULL.
|
||||
*/
|
||||
ChainedMessage(const string circuit, const string level, const string name,
|
||||
const bool isWrite, const map<string, string>& attributes,
|
||||
const symbol_t srcAddress, const symbol_t dstAddress,
|
||||
const vector<symbol_t> id,
|
||||
vector< vector<symbol_t> > ids, vector<size_t> lengths,
|
||||
const DataField* data, const bool deleteData,
|
||||
const size_t pollPriority,
|
||||
ChainedMessage(const string& circuit, const string& level, const string& name,
|
||||
bool isWrite, const map<string, string>& attributes,
|
||||
symbol_t srcAddress, symbol_t dstAddress,
|
||||
const vector<symbol_t>& id,
|
||||
const vector< vector<symbol_t> >& ids, const vector<size_t>& lengths,
|
||||
const DataField* data, bool deleteData,
|
||||
size_t pollPriority = 0,
|
||||
Condition* condition = NULL);
|
||||
|
||||
virtual ~ChainedMessage();
|
||||
|
||||
// @copydoc
|
||||
Message* derive(const symbol_t dstAddress, const symbol_t srcAddress = SYN,
|
||||
const string circuit = "") const override;
|
||||
Message* derive(symbol_t dstAddress, symbol_t srcAddress, const string& circuit) const override;
|
||||
|
||||
// @copydoc
|
||||
size_t getIdLength() const override { return m_ids[0].size() - 2; }
|
||||
|
||||
// @copydoc
|
||||
bool checkId(const MasterSymbolString& master, size_t* index = NULL) const override;
|
||||
bool checkId(const MasterSymbolString& master, size_t* index) const override;
|
||||
|
||||
// @copydoc
|
||||
bool checkId(Message& other) const override;
|
||||
bool checkId(const Message& other) const override;
|
||||
|
||||
// @copydoc
|
||||
size_t getCount() const override { return m_ids.size(); }
|
||||
@@ -706,19 +693,19 @@ class ChainedMessage : public Message {
|
||||
|
||||
protected:
|
||||
// @copydoc
|
||||
result_t prepareMasterPart(MasterSymbolString& master, istringstream& input, char separator,
|
||||
size_t index) override;
|
||||
result_t prepareMasterPart(size_t index, const char separator, istringstream* input,
|
||||
MasterSymbolString* master) override;
|
||||
|
||||
|
||||
public:
|
||||
// @copydoc
|
||||
result_t storeLastData(MasterSymbolString& master, SlaveSymbolString& slave) override;
|
||||
result_t storeLastData(const MasterSymbolString& master, const SlaveSymbolString& slave) override;
|
||||
|
||||
// @copydoc
|
||||
result_t storeLastData(MasterSymbolString& data, size_t index) override;
|
||||
result_t storeLastData(size_t index, const MasterSymbolString& data) override;
|
||||
|
||||
// @copydoc
|
||||
result_t storeLastData(SlaveSymbolString& data, size_t index) override;
|
||||
result_t storeLastData(size_t index, const SlaveSymbolString& data) override;
|
||||
|
||||
/**
|
||||
* Combine all last stored data.
|
||||
@@ -728,7 +715,7 @@ class ChainedMessage : public Message {
|
||||
|
||||
protected:
|
||||
// @copydoc
|
||||
void dumpField(ostream& output, string fieldName, bool withConditions = false) const override;
|
||||
void dumpField(const string& fieldName, bool withConditions, ostream* output) const override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -810,27 +797,27 @@ class Condition {
|
||||
/**
|
||||
* Factory method for creating a new instance.
|
||||
* @param condName the name of the condition.
|
||||
* @param row the mapped definition row.
|
||||
* @param rowDefaults the mapped definition defaults.
|
||||
* @param row the mapped definition row.
|
||||
* @param returnValue the variable in which to store the created instance.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
static result_t create(const string condName, map<string, string> row, map<string, string> rowDefaults,
|
||||
SimpleCondition*& returnValue);
|
||||
static result_t create(const string& condName, const map<string, string>& rowDefaults,
|
||||
map<string, string>* row, SimpleCondition** returnValue);
|
||||
|
||||
/**
|
||||
* Derive a new @a SimpleCondition from this condition.
|
||||
* @param valueList the @a string with the new list of values.
|
||||
* @return the derived @a SimpleCondition instance, or NULL if the value list is invalid.
|
||||
*/
|
||||
virtual SimpleCondition* derive(string valueList) const { return NULL; }
|
||||
virtual SimpleCondition* derive(const string& valueList) const { return NULL; }
|
||||
|
||||
/**
|
||||
* Write the condition definition or resolved expression to the @a ostream.
|
||||
* @param output the @a ostream to append to.
|
||||
* @param matched true for dumping the matched value if the condition is true, false for dumping the definition.
|
||||
* @param output the @a ostream to append to.
|
||||
*/
|
||||
virtual void dump(ostream& output, bool matched = false) const = 0;
|
||||
virtual void dump(bool matched, ostream* output) const = 0;
|
||||
|
||||
/**
|
||||
* Combine this condition with another instance using a logical and.
|
||||
@@ -842,12 +829,12 @@ class Condition {
|
||||
/**
|
||||
* Resolve the referred @a Message instance(s) and field index(es).
|
||||
* @param messages the @a MessageMap instance for resolving.
|
||||
* @param errorMessage a @a ostringstream to which to add optional error messages.
|
||||
* @param readMessageFunc the function to call for immediate reading of a @a Message from the bus, or NULL.
|
||||
* @param errorMessage a @a ostringstream to which to add optional error messages.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage,
|
||||
void (*readMessageFunc)(Message* message) = NULL) = 0;
|
||||
virtual result_t resolve(void (*readMessageFunc)(Message* message), MessageMap* messages,
|
||||
ostringstream* errorMessage) = 0;
|
||||
|
||||
/**
|
||||
* Check and return whether this condition is fulfilled.
|
||||
@@ -882,8 +869,8 @@ class SimpleCondition : public Condition {
|
||||
* @param field the field name.
|
||||
* @param hasValues whether a value has to be checked against.
|
||||
*/
|
||||
SimpleCondition(const string condName, const string refName, const string circuit, const string level,
|
||||
const string name, const symbol_t dstAddress, const string field, const bool hasValues = false)
|
||||
SimpleCondition(const string& condName, const string& refName, const string& circuit, const string& level,
|
||||
const string& name, symbol_t dstAddress, const string& field, bool hasValues = false)
|
||||
: Condition(),
|
||||
m_condName(condName), m_refName(refName), m_circuit(circuit), m_level(level), m_name(name),
|
||||
m_dstAddress(dstAddress), m_field(field), m_hasValues(hasValues), m_message(NULL) { }
|
||||
@@ -894,17 +881,17 @@ class SimpleCondition : public Condition {
|
||||
virtual ~SimpleCondition() {}
|
||||
|
||||
// @copydoc
|
||||
SimpleCondition* derive(string valueList) const override;
|
||||
SimpleCondition* derive(const string& valueList) const override;
|
||||
|
||||
// @copydoc
|
||||
void dump(ostream& output, bool matched = false) const override;
|
||||
void dump(bool matched, ostream* output) const override;
|
||||
|
||||
// @copydoc
|
||||
CombinedCondition* combineAnd(Condition* other) override;
|
||||
|
||||
// @copydoc
|
||||
result_t resolve(MessageMap* messages, ostringstream& errorMessage,
|
||||
void (*readMessageFunc)(Message* message) = NULL) override;
|
||||
result_t resolve(void (*readMessageFunc)(Message* message), MessageMap* messages,
|
||||
ostringstream* errorMessage) override;
|
||||
|
||||
// @copydoc
|
||||
bool isTrue() override;
|
||||
@@ -923,7 +910,7 @@ class SimpleCondition : public Condition {
|
||||
* @param field the field name to check against, or empty for first field.
|
||||
* @return whether the field matches one of the valid values.
|
||||
*/
|
||||
virtual bool checkValue(Message* message, const string field) { return true; }
|
||||
virtual bool checkValue(const Message* message, const string& field) { return true; }
|
||||
|
||||
/** the value that matched in @a checkValue. */
|
||||
string m_matchedValue;
|
||||
@@ -976,8 +963,8 @@ class SimpleNumericCondition : public SimpleCondition {
|
||||
* @param field the field name.
|
||||
* @param valueRanges the valid value ranges (pairs of from/to inclusive), empty for @a m_message seen check.
|
||||
*/
|
||||
SimpleNumericCondition(const string condName, const string refName, const string circuit, const string level,
|
||||
const string name, const symbol_t dstAddress, const string field, const vector<unsigned int> valueRanges)
|
||||
SimpleNumericCondition(const string& condName, const string& refName, const string& circuit, const string& level,
|
||||
const string& name, symbol_t dstAddress, const string& field, const vector<unsigned int>& valueRanges)
|
||||
: SimpleCondition(condName, refName, circuit, level, name, dstAddress, field, true),
|
||||
m_valueRanges(valueRanges) { }
|
||||
|
||||
@@ -989,7 +976,7 @@ class SimpleNumericCondition : public SimpleCondition {
|
||||
|
||||
protected:
|
||||
// @copydoc
|
||||
bool checkValue(Message* message, const string field) override;
|
||||
bool checkValue(const Message* message, const string& field) override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -1014,8 +1001,8 @@ class SimpleStringCondition : public SimpleCondition {
|
||||
* @param field the field name.
|
||||
* @param values the valid values.
|
||||
*/
|
||||
SimpleStringCondition(const string condName, const string refName, const string circuit, const string level,
|
||||
const string name, const symbol_t dstAddress, const string field, const vector<string> values)
|
||||
SimpleStringCondition(const string& condName, const string& refName, const string& circuit, const string& level,
|
||||
const string& name, symbol_t dstAddress, const string& field, const vector<string>& values)
|
||||
: SimpleCondition(condName, refName, circuit, level, name, dstAddress, field, true),
|
||||
m_values(values) { }
|
||||
|
||||
@@ -1030,7 +1017,7 @@ class SimpleStringCondition : public SimpleCondition {
|
||||
|
||||
protected:
|
||||
// @copydoc
|
||||
bool checkValue(Message* message, const string field) override;
|
||||
bool checkValue(const Message* message, const string& field) override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -1056,14 +1043,14 @@ class CombinedCondition : public Condition {
|
||||
virtual ~CombinedCondition() {}
|
||||
|
||||
// @copydoc
|
||||
void dump(ostream& output, bool matched = false) const override;
|
||||
void dump(bool matched, ostream* output) const override;
|
||||
|
||||
// @copydoc
|
||||
CombinedCondition* combineAnd(Condition* other) override { m_conditions.push_back(other); return this; }
|
||||
|
||||
// @copydoc
|
||||
result_t resolve(MessageMap* messages, ostringstream& errorMessage,
|
||||
void (*readMessageFunc)(Message* message) = NULL) override;
|
||||
result_t resolve(void (*readMessageFunc)(Message* message), MessageMap* messages,
|
||||
ostringstream* errorMessage) override;
|
||||
|
||||
// @copydoc
|
||||
bool isTrue() override;
|
||||
@@ -1087,7 +1074,7 @@ class Instruction {
|
||||
* executed for the same source file.
|
||||
* @param defaults the mapped definition defaults.
|
||||
*/
|
||||
Instruction(Condition* condition, const bool singleton, const map<string, string>& defaults)
|
||||
Instruction(bool singleton, const map<string, string>& defaults, Condition* condition)
|
||||
: m_condition(condition), m_singleton(singleton), m_defaults(defaults) { }
|
||||
|
||||
/**
|
||||
@@ -1105,9 +1092,9 @@ class Instruction {
|
||||
* @param returnValue the variable in which to store the created instance.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
static result_t create(const string& contextPath, const string type,
|
||||
Condition* condition, map<string, string>& row, map<string, string>& defaults,
|
||||
Instruction*& returnValue);
|
||||
static result_t create(const string& contextPath, const string& type,
|
||||
Condition* condition, const map<string, string>& row, const map<string, string>& defaults,
|
||||
Instruction** returnValue);
|
||||
|
||||
/**
|
||||
* Return the @a Condition this instruction requires.
|
||||
@@ -1133,13 +1120,12 @@ class Instruction {
|
||||
* Execute the instruction.
|
||||
* @param messages the @a MessageMap.
|
||||
* @param log the @a ostringstream to log success messages to (if necessary).
|
||||
* @param condition the @a Condition that was successfully evaluated for execution, or NULL.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t execute(MessageMap* messages, ostringstream& log, Condition* condition) = 0;
|
||||
virtual result_t execute(MessageMap* messages, ostringstream* log) = 0;
|
||||
|
||||
|
||||
private:
|
||||
protected:
|
||||
/** the @a Condition this instruction requires, or null. */
|
||||
Condition* m_condition;
|
||||
|
||||
@@ -1147,8 +1133,6 @@ class Instruction {
|
||||
* same source file. */
|
||||
const bool m_singleton;
|
||||
|
||||
|
||||
protected:
|
||||
/** the defaults by field name. */
|
||||
map<string, string> m_defaults;
|
||||
};
|
||||
@@ -1167,8 +1151,9 @@ class LoadInstruction : public Instruction {
|
||||
* @param defaults the mapped definition defaults.
|
||||
* @param filename the name of the file to load.
|
||||
*/
|
||||
LoadInstruction(Condition* condition, const bool singleton, map<string, string>& defaults, const string filename)
|
||||
: Instruction(condition, singleton, defaults), m_filename(filename) { }
|
||||
LoadInstruction(bool singleton, const map<string, string>& defaults, const string& filename,
|
||||
Condition* condition)
|
||||
: Instruction(singleton, defaults, condition), m_filename(filename) { }
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
@@ -1176,7 +1161,7 @@ class LoadInstruction : public Instruction {
|
||||
virtual ~LoadInstruction() { }
|
||||
|
||||
// @copydoc
|
||||
result_t execute(MessageMap* messages, ostringstream& log, Condition* condition) override;
|
||||
result_t execute(MessageMap* messages, ostringstream* log) override;
|
||||
|
||||
|
||||
private:
|
||||
@@ -1215,7 +1200,7 @@ class MessageMap : public MappedFileReader {
|
||||
* @param addAll whether to add all messages, even if duplicate.
|
||||
* @param preferLanguage the preferred language to use, or empty.
|
||||
*/
|
||||
explicit MessageMap(const string configPath, const bool addAll = false, const string preferLanguage = "")
|
||||
explicit MessageMap(const string& configPath, bool addAll = false, const string& preferLanguage = "")
|
||||
: MappedFileReader::MappedFileReader(true),
|
||||
m_configPath(configPath),
|
||||
m_addAll(addAll), m_additionalScanMessages(false), m_maxIdLength(0), m_maxBroadcastIdLength(0),
|
||||
@@ -1244,7 +1229,7 @@ class MessageMap : public MappedFileReader {
|
||||
* @param filename the name of the configuration file (including relative path).
|
||||
* @return the relative file name.
|
||||
*/
|
||||
const string getRelativePath(const string filename) const;
|
||||
const string getRelativePath(const string& filename) const;
|
||||
|
||||
/**
|
||||
* Add a @a Message instance to this set.
|
||||
@@ -1253,36 +1238,36 @@ class MessageMap : public MappedFileReader {
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
* Note: the caller may not free the added instance on success.
|
||||
*/
|
||||
result_t add(Message* message, bool storeByName = true);
|
||||
result_t add(bool storeByName, Message* message);
|
||||
|
||||
// @copydoc
|
||||
result_t getFieldMap(vector<string>& row, string& errorDescription, const string preferLanguage) const override;
|
||||
result_t getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t addDefaultFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
|
||||
string& errorDescription, const string filename, unsigned int lineNo) override;
|
||||
result_t addDefaultFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
|
||||
vector< map<string, string> >* subRows, string* errorDescription) override;
|
||||
|
||||
/**
|
||||
* Read the @a Condition instance(s) from the types field.
|
||||
* @param types the field from which to read the @a Condition instance(s).
|
||||
* @param filename the name of the file being read.
|
||||
* @param types the field from which to read the @a Condition instance(s) and remove the definition prefix.
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @param condition the variable in which to store the result.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t readConditions(string& types, const string filename, string& errorDescription, Condition*& condition);
|
||||
result_t readConditions(const string& filename, string* types, string* errorDescription, Condition** condition);
|
||||
|
||||
// @copydoc
|
||||
bool extractDefaultsFromFilename(string filename, map<string, string>& defaults,
|
||||
symbol_t* destAddress = NULL, unsigned int* software = NULL, unsigned int* hardware = NULL) const override;
|
||||
bool extractDefaultsFromFilename(const string& filename, map<string, string>* defaults,
|
||||
symbol_t* destAddress, unsigned int* software, unsigned int* hardware) const override;
|
||||
|
||||
// @copydoc
|
||||
result_t readFromFile(const string filename, string& errorDescription, bool verbose = false,
|
||||
map<string, string>* defaults = NULL, size_t* hash = NULL, size_t* size = NULL, time_t* time = NULL) override;
|
||||
result_t readFromFile(const string& filename, bool verbose, map<string, string>* defaults,
|
||||
string* errorDescription, size_t* hash, size_t* size, time_t* time) override;
|
||||
|
||||
// @copydoc
|
||||
result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
|
||||
string& errorDescription, const string filename, unsigned int lineNo) override;
|
||||
result_t addFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
|
||||
vector< map<string, string> >* subRows, string* errorDescription) override;
|
||||
|
||||
/**
|
||||
* Get the scan @a Message instance for the specified address.
|
||||
@@ -1299,30 +1284,30 @@ class MessageMap : public MappedFileReader {
|
||||
|
||||
/**
|
||||
* Resolve all @a Condition instances.
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @param verbose whether to verbosely add all problems to the error message.
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t resolveConditions(string& errorDescription, bool verbose = false);
|
||||
result_t resolveConditions(bool verbose, string* errorDescription);
|
||||
|
||||
/**
|
||||
* Resolve a @a Condition.
|
||||
* @param readMessageFunc the function to call for immediate reading of a @a Message from the bus, or NULL.
|
||||
* @param condition the @a Condition to resolve.
|
||||
* @param errorDescription a string in which to store the error description in case of error.
|
||||
* @param readMessageFunc the function to call for immediate reading of a @a Message from the bus, or NULL.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t resolveCondition(Condition* condition, string& errorDescription,
|
||||
void (*readMessageFunc)(Message* message) = NULL);
|
||||
result_t resolveCondition(void (*readMessageFunc)(Message* message), Condition* condition,
|
||||
string* errorDescription);
|
||||
|
||||
/**
|
||||
* Run all executable @a Instruction instances.
|
||||
* @param log the @a ostringstream to log success messages to (if necessary).
|
||||
* @param readMessageFunc the function to call for immediate reading of a
|
||||
* @a Message values from the bus required for singleton instructions, or NULL.
|
||||
* @param log the @a ostringstream to log success messages to (if necessary).
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t executeInstructions(ostringstream& log, void (*readMessageFunc)(Message* message) = NULL);
|
||||
result_t executeInstructions(void (*readMessageFunc)(Message* message), ostringstream* log);
|
||||
|
||||
/**
|
||||
* Add a loaded file to a participant.
|
||||
@@ -1330,14 +1315,14 @@ class MessageMap : public MappedFileReader {
|
||||
* @param filename the name of the configuration file (including relative path).
|
||||
* @param comment an optional comment.
|
||||
*/
|
||||
void addLoadedFile(const symbol_t address, const string filename, const string comment = "");
|
||||
void addLoadedFile(symbol_t address, const string& filename, const string& comment = "");
|
||||
|
||||
/**
|
||||
* Get the loaded files for a participant.
|
||||
* @param address the slave address.
|
||||
* @return the loaded configuration files (list of file names with relative path).
|
||||
*/
|
||||
const vector<string>& getLoadedFiles(const symbol_t address) const;
|
||||
const vector<string>& getLoadedFiles(symbol_t address) const;
|
||||
|
||||
/**
|
||||
* Get all loaded files.
|
||||
@@ -1354,7 +1339,7 @@ class MessageMap : public MappedFileReader {
|
||||
* @param time optional pointer to a @a time_t value for storing the modification time of the file, or NULL.
|
||||
* @return true if the file info was found, false otherwise.
|
||||
*/
|
||||
bool getLoadedFileInfo(const string filename, string& comment, size_t* hash = NULL, size_t* size = NULL,
|
||||
bool getLoadedFileInfo(const string& filename, string* comment, size_t* hash = NULL, size_t* size = NULL,
|
||||
time_t* time = NULL) const;
|
||||
|
||||
/**
|
||||
@@ -1363,7 +1348,7 @@ class MessageMap : public MappedFileReader {
|
||||
* @return the found @a Message instances, or NULL.
|
||||
* Note: the caller may not free the returned instances.
|
||||
*/
|
||||
const vector<Message*>* getByKey(const uint64_t key) const;
|
||||
const vector<Message*>* getByKey(uint64_t key) const;
|
||||
|
||||
/**
|
||||
* Find the @a Message instance for the specified circuit and name.
|
||||
@@ -1375,8 +1360,8 @@ class MessageMap : public MappedFileReader {
|
||||
* @return the @a Message instance, or NULL.
|
||||
* Note: the caller may not free the returned instance.
|
||||
*/
|
||||
Message* find(const string& circuit, const string& name, const string& levels, const bool isWrite,
|
||||
const bool isPassive = false) const;
|
||||
Message* find(const string& circuit, const string& name, const string& levels, bool isWrite,
|
||||
bool isPassive = false) const;
|
||||
|
||||
/**
|
||||
* Find all active get @a Message instances for the specified circuit and name.
|
||||
@@ -1400,9 +1385,9 @@ class MessageMap : public MappedFileReader {
|
||||
* Note: the caller may not free the returned instances.
|
||||
*/
|
||||
deque<Message*> findAll(const string& circuit, const string& name, const string& levels,
|
||||
const bool completeMatch = true, const bool withRead = true, const bool withWrite = false,
|
||||
const bool withPassive = false, const bool includeEmptyLevel = true, const bool onlyAvailable = true,
|
||||
const time_t since = 0, const time_t until = 0) const;
|
||||
bool completeMatch = true, bool withRead = true, bool withWrite = false,
|
||||
bool withPassive = false, bool includeEmptyLevel = true, bool onlyAvailable = true,
|
||||
time_t since = 0, time_t until = 0) const;
|
||||
|
||||
/**
|
||||
* Find the @a Message instance for the specified master data.
|
||||
@@ -1416,8 +1401,8 @@ class MessageMap : public MappedFileReader {
|
||||
* @return the @a Message instance, or NULL.
|
||||
* Note: the caller may not free the returned instance.
|
||||
*/
|
||||
Message* find(const MasterSymbolString& master, const bool anyDestination = false, const bool withRead = true,
|
||||
const bool withWrite = true, const bool withPassive = true, const bool onlyAvailable = true) const;
|
||||
Message* find(const MasterSymbolString& master, bool anyDestination = false, bool withRead = true,
|
||||
bool withWrite = true, bool withPassive = true, bool onlyAvailable = true) const;
|
||||
|
||||
/**
|
||||
* Invalidate cached data of the @a Message and all other instances with a matching name key.
|
||||
@@ -1427,19 +1412,19 @@ class MessageMap : public MappedFileReader {
|
||||
|
||||
/**
|
||||
* Add a @a Message to the list of instances to poll.
|
||||
* @param message the @a Message to poll.
|
||||
* @param toFront whether to add the @a Message to the very front of the poll queue.
|
||||
* @param message the @a Message to poll.
|
||||
*/
|
||||
void addPollMessage(Message* message, bool toFront = false);
|
||||
void addPollMessage(bool toFront, Message* message);
|
||||
|
||||
/**
|
||||
* Decode circuit specific data.
|
||||
* @param circuit the name of the circuit.
|
||||
* @param output the @a ostringstream to append the decoded value(s) to.
|
||||
* @param outputFormat the @a OutputFormat options to use.
|
||||
* @param output the @a ostringstream to append the decoded value(s) to.
|
||||
* @return true if data was added, false otherwise.
|
||||
*/
|
||||
bool decodeCircuit(const string circuit, ostringstream& output, OutputFormat outputFormat) const;
|
||||
bool decodeCircuit(const string& circuit, OutputFormat outputFormat, ostringstream* output) const;
|
||||
|
||||
/**
|
||||
* Removes all @a Message instances.
|
||||
@@ -1491,10 +1476,10 @@ class MessageMap : public MappedFileReader {
|
||||
|
||||
/**
|
||||
* Write the message definitions to the @a ostream.
|
||||
* @param output the @a ostream to append the formatted messages to.
|
||||
* @param withConditions whether to include the optional conditions prefix.
|
||||
* @param output the @a ostream to append the formatted messages to.
|
||||
*/
|
||||
void dump(ostream& output, const bool withConditions = false) const;
|
||||
void dump(bool withConditions, ostream* output) const;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
+19
-19
@@ -54,59 +54,59 @@ static const symbol_t CRC_LOOKUP_TABLE[] = {
|
||||
};
|
||||
|
||||
|
||||
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue,
|
||||
result_t& result, size_t* length) {
|
||||
unsigned int parseInt(const char* str, int base, unsigned int minValue, unsigned int maxValue,
|
||||
result_t* result, size_t* length) {
|
||||
char* strEnd = NULL;
|
||||
|
||||
unsigned long ret = strtoul(str, &strEnd, base);
|
||||
|
||||
if (strEnd == NULL || strEnd == str || *strEnd != 0) {
|
||||
result = RESULT_ERR_INVALID_NUM; // invalid value
|
||||
*result = RESULT_ERR_INVALID_NUM; // invalid value
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (minValue > ret || ret > maxValue) {
|
||||
result = RESULT_ERR_OUT_OF_RANGE; // invalid value
|
||||
*result = RESULT_ERR_OUT_OF_RANGE; // invalid value
|
||||
return 0;
|
||||
}
|
||||
if (length != NULL) {
|
||||
*length = (unsigned int)(strEnd - str);
|
||||
}
|
||||
result = RESULT_OK;
|
||||
*result = RESULT_OK;
|
||||
return (unsigned int)ret;
|
||||
}
|
||||
|
||||
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result,
|
||||
size_t* length) {
|
||||
int parseSignedInt(const char* str, int base, int minValue, int maxValue,
|
||||
result_t* result, size_t* length) {
|
||||
char* strEnd = NULL;
|
||||
|
||||
long ret = strtol(str, &strEnd, base);
|
||||
|
||||
if (strEnd == NULL || *strEnd != 0) {
|
||||
result = RESULT_ERR_INVALID_NUM; // invalid value
|
||||
*result = RESULT_ERR_INVALID_NUM; // invalid value
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (minValue > ret || ret > maxValue) {
|
||||
result = RESULT_ERR_OUT_OF_RANGE; // invalid value
|
||||
*result = RESULT_ERR_OUT_OF_RANGE; // invalid value
|
||||
return 0;
|
||||
}
|
||||
if (length != NULL) {
|
||||
*length = (unsigned int)(strEnd - str);
|
||||
}
|
||||
result = RESULT_OK;
|
||||
*result = RESULT_OK;
|
||||
return static_cast<int>(ret);
|
||||
}
|
||||
|
||||
|
||||
void SymbolString::updateCrc(symbol_t& crc, const symbol_t value) {
|
||||
crc = CRC_LOOKUP_TABLE[crc]^value;
|
||||
void SymbolString::updateCrc(symbol_t value, symbol_t* crc) {
|
||||
*crc = CRC_LOOKUP_TABLE[*crc]^value;
|
||||
}
|
||||
|
||||
result_t SymbolString::parseHex(const string& str) {
|
||||
result_t result;
|
||||
for (size_t i = 0; i < str.size(); i += 2) {
|
||||
symbol_t value = (symbol_t)parseInt(str.substr(i, 2).c_str(), 16, 0, 0xff, result);
|
||||
symbol_t value = (symbol_t)parseInt(str.substr(i, 2).c_str(), 16, 0, 0xff, &result);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -119,7 +119,7 @@ result_t SymbolString::parseHexEscaped(const string& str) {
|
||||
result_t result;
|
||||
bool inEscape = false;
|
||||
for (size_t i = 0; i < str.size(); i += 2) {
|
||||
symbol_t value = (symbol_t)parseInt(str.substr(i, 2).c_str(), 16, 0, 0xff, result);
|
||||
symbol_t value = (symbol_t)parseInt(str.substr(i, 2).c_str(), 16, 0, 0xff, &result);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -162,13 +162,13 @@ symbol_t SymbolString::calcCrc() const {
|
||||
for (size_t i = 0; i < m_data.size(); i++) {
|
||||
symbol_t value = m_data[i];
|
||||
if (value == ESC) {
|
||||
updateCrc(crc, ESC);
|
||||
updateCrc(crc, 0x00);
|
||||
updateCrc(ESC, &crc);
|
||||
updateCrc(0x00, &crc);
|
||||
} else if (value == SYN) {
|
||||
updateCrc(crc, ESC);
|
||||
updateCrc(crc, 0x01);
|
||||
updateCrc(ESC, &crc);
|
||||
updateCrc(0x01, &crc);
|
||||
} else {
|
||||
updateCrc(crc, value);
|
||||
updateCrc(value, &crc);
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
|
||||
+14
-14
@@ -96,8 +96,8 @@ typedef unsigned char symbol_t;
|
||||
* @param length the optional variable in which to store the number of read characters.
|
||||
* @return the parsed value.
|
||||
*/
|
||||
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue,
|
||||
result_t& result, size_t* length = NULL);
|
||||
unsigned int parseInt(const char* str, int base, unsigned int minValue, unsigned int maxValue,
|
||||
result_t* result, size_t* length = NULL);
|
||||
|
||||
/**
|
||||
* Parse a signed int value.
|
||||
@@ -109,8 +109,8 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co
|
||||
* @param length the optional variable in which to store the number of read characters.
|
||||
* @return the parsed value.
|
||||
*/
|
||||
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result,
|
||||
size_t* length = NULL);
|
||||
int parseSignedInt(const char* str, int base, int minValue, int maxValue,
|
||||
result_t* result, size_t* length = NULL);
|
||||
|
||||
/**
|
||||
* A string of unescaped bus symbols.
|
||||
@@ -121,15 +121,15 @@ class SymbolString {
|
||||
* Creates a new empty instance.
|
||||
* @param isMaster whether this instance if for the master part.
|
||||
*/
|
||||
explicit SymbolString(const bool isMaster = false) { m_isMaster = isMaster; }
|
||||
explicit SymbolString(bool isMaster = false) { m_isMaster = isMaster; }
|
||||
|
||||
public:
|
||||
/**
|
||||
* Update the CRC by adding a value.
|
||||
* @param crc the current CRC to update.
|
||||
* @param value the escaped value to add to the current CRC.
|
||||
* @param crc the current CRC to update.
|
||||
*/
|
||||
static void updateCrc(symbol_t& crc, const symbol_t value);
|
||||
static void updateCrc(symbol_t value, symbol_t* crc);
|
||||
|
||||
/**
|
||||
* Return whether this instance if for the master part.
|
||||
@@ -175,7 +175,7 @@ class SymbolString {
|
||||
* @param index the index of the symbol to return.
|
||||
* @return the reference to the symbol at the specified index, or SYN if not available.
|
||||
*/
|
||||
symbol_t operator[](const size_t index) const {
|
||||
symbol_t operator[](size_t index) const {
|
||||
if (index >= m_data.size()) {
|
||||
return SYN;
|
||||
}
|
||||
@@ -187,7 +187,7 @@ class SymbolString {
|
||||
* @param other the other instance.
|
||||
* @return true if this instance is equal to the other instance.
|
||||
*/
|
||||
bool operator == (SymbolString& other) {
|
||||
bool operator == (const SymbolString& other) {
|
||||
return m_isMaster == other.m_isMaster && m_data == other.m_data;
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ class SymbolString {
|
||||
* @param other the other instance.
|
||||
* @return true if this instance is different from the other instance.
|
||||
*/
|
||||
bool operator != (SymbolString& other) {
|
||||
bool operator != (const SymbolString& other) {
|
||||
return m_isMaster != other.m_isMaster || m_data != other.m_data;
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ class SymbolString {
|
||||
* 1 if the data is completely different,
|
||||
* 2 if both instances are a master part and the data only differs in the first byte (the master address).
|
||||
*/
|
||||
int compareTo(SymbolString& other) {
|
||||
int compareTo(const SymbolString& other) const {
|
||||
if (m_data.size() != other.m_data.size() || m_isMaster != other.m_isMaster) {
|
||||
return 1;
|
||||
}
|
||||
@@ -230,7 +230,7 @@ class SymbolString {
|
||||
* Append a symbol to the end of the symbol string.
|
||||
* @param value the symbol to append.
|
||||
*/
|
||||
void push_back(const symbol_t value) { m_data.push_back(value); }
|
||||
void push_back(symbol_t value) { m_data.push_back(value); }
|
||||
|
||||
/**
|
||||
* Return the number of symbols in this symbol string.
|
||||
@@ -277,7 +277,7 @@ class SymbolString {
|
||||
* @param index the index of the data byte (within DD) to return.
|
||||
* @return the data byte at the specified index, or 0 if not available.
|
||||
*/
|
||||
symbol_t dataAt(const size_t index) const {
|
||||
symbol_t dataAt(size_t index) const {
|
||||
size_t offset = (m_isMaster ? 5 : 1) + index;
|
||||
if (offset < m_data.size()) {
|
||||
return m_data[offset];
|
||||
@@ -290,7 +290,7 @@ class SymbolString {
|
||||
* @param index the index of the data byte (within DD) to return.
|
||||
* @return the reference to the data byte at the specified index.
|
||||
*/
|
||||
symbol_t& dataAt(const size_t index) {
|
||||
symbol_t& dataAt(size_t index) {
|
||||
size_t offset = (m_isMaster ? 5 : 1) + index;
|
||||
if (offset >= m_data.size()) {
|
||||
m_data.resize(offset+1, 0);
|
||||
|
||||
@@ -53,34 +53,34 @@ class TestReader : public MappedFileReader {
|
||||
TestReader(DataFieldTemplates* templates, bool isSet, bool isMasterDest)
|
||||
: MappedFileReader::MappedFileReader(true), m_templates(templates), m_isSet(isSet), m_isMasterDest(isMasterDest),
|
||||
m_fields(NULL) {}
|
||||
result_t getFieldMap(vector<string>& row, string& errorDescription, const string preferLanguage) const override {
|
||||
if (row.empty()) {
|
||||
row.push_back("*name");
|
||||
row.push_back("part");
|
||||
row.push_back("type");
|
||||
row.push_back("divisor/values");
|
||||
row.push_back("unit");
|
||||
row.push_back("comment");
|
||||
result_t getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const override {
|
||||
if (row->empty()) {
|
||||
row->push_back("*name");
|
||||
row->push_back("part");
|
||||
row->push_back("type");
|
||||
row->push_back("divisor/values");
|
||||
row->push_back("unit");
|
||||
row->push_back("comment");
|
||||
return RESULT_OK;
|
||||
}
|
||||
if (row[0][0] != '*') {
|
||||
if ((*row)[0][0] != '*') {
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
return RESULT_OK; // leave it to DataField::create
|
||||
}
|
||||
result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
|
||||
string& errorDescription, const string filename, unsigned int lineNo) override {
|
||||
if (!row.empty() || subRows.empty()) {
|
||||
result_t addFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
|
||||
vector< map<string, string> >* subRows, string* errorDescription) override {
|
||||
if (!row->empty() || subRows->empty()) {
|
||||
cout << "read line " << static_cast<unsigned>(lineNo) << ": read error: got "
|
||||
<< static_cast<unsigned>(row.size()) << "/0 main, " << static_cast<unsigned>(subRows.size())
|
||||
<< static_cast<unsigned>(row->size()) << "/0 main, " << static_cast<unsigned>(subRows->size())
|
||||
<< "/>=3 sub" << endl;
|
||||
return RESULT_ERR_EOF;
|
||||
}
|
||||
cout << "read line " << static_cast<unsigned>(lineNo) << ": read OK" << endl;
|
||||
return DataField::create(subRows, errorDescription, m_templates, m_fields, m_isSet, false, m_isMasterDest);
|
||||
return DataField::create(m_isSet, false, m_isMasterDest, MAX_POS, m_templates, subRows, errorDescription, &m_fields);
|
||||
}
|
||||
private:
|
||||
DataFieldTemplates* m_templates;
|
||||
const DataFieldTemplates* m_templates;
|
||||
const bool m_isSet;
|
||||
const bool m_isMasterDest;
|
||||
public:
|
||||
@@ -508,7 +508,7 @@ int main() {
|
||||
istringstream dummystr("#");
|
||||
string errorDescription;
|
||||
vector<string> row;
|
||||
templates->readLineFromStream(dummystr, errorDescription, __FILE__, lineNo, row);
|
||||
templates->readLineFromStream(__FILE__, false, &dummystr, &lineNo, &row, &errorDescription, NULL, NULL);
|
||||
const DataField* fields = NULL;
|
||||
for (size_t i = 0; i < sizeof(checks) / sizeof(checks[0]); i++) {
|
||||
string check[5] = checks[i];
|
||||
@@ -558,7 +558,7 @@ int main() {
|
||||
}
|
||||
if (isTemplate) {
|
||||
lineNo = baseLine + i;
|
||||
result = templates->readLineFromStream(isstr, errorDescription, __FILE__, lineNo, row, false);
|
||||
result = templates->readLineFromStream(__FILE__, false, &isstr, &lineNo, &row, &errorDescription, NULL, NULL);
|
||||
if (result != RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": template read error: " << getResultCode(result) << ", "
|
||||
<< errorDescription << endl;
|
||||
@@ -570,7 +570,7 @@ int main() {
|
||||
lineNo = 0;
|
||||
dummystr.clear();
|
||||
dummystr.str("#");
|
||||
result = reader.readLineFromStream(dummystr, errorDescription, __FILE__, lineNo, row);
|
||||
result = reader.readLineFromStream(__FILE__, false, &dummystr, &lineNo, &row, &errorDescription, NULL, NULL);
|
||||
if (result != RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": reader header error: " << getResultCode(result) << ", " << errorDescription
|
||||
<< endl;
|
||||
@@ -578,7 +578,7 @@ int main() {
|
||||
continue;
|
||||
}
|
||||
lineNo = baseLine + i;
|
||||
result = reader.readLineFromStream(isstr, errorDescription, "", lineNo, row);
|
||||
result = reader.readLineFromStream("", false, &isstr, &lineNo, &row, &errorDescription, NULL, NULL);
|
||||
fields = reader.m_fields;
|
||||
if (failedCreate) {
|
||||
if (result == RESULT_OK) {
|
||||
@@ -600,7 +600,7 @@ int main() {
|
||||
continue;
|
||||
}
|
||||
cout << "\"" << check[0] << "\"=\"";
|
||||
fields->dump(cout);
|
||||
fields->dump(&cout);
|
||||
cout << "\": create OK" << endl;
|
||||
|
||||
ostringstream output;
|
||||
@@ -616,22 +616,21 @@ int main() {
|
||||
cout << " parse \"" << sstr.getStr().substr(0, 2) << "\" error: " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
}
|
||||
result = fields->read(mstr, 0, output, verbosity|(numeric?OF_NUMERIC:0), -1, false);
|
||||
result = fields->read(mstr, 0, false, NULL, -1, verbosity|(numeric?OF_NUMERIC:0), -1, &output);
|
||||
if (result >= RESULT_OK) {
|
||||
result = fields->read(sstr, 0, output, verbosity|(numeric?OF_NUMERIC:0), -1,
|
||||
!output.str().empty());
|
||||
result = fields->read(sstr, 0, !output.str().empty(), NULL, -1, verbosity|(numeric?OF_NUMERIC:0), -1, &output);
|
||||
}
|
||||
if (failedRead) {
|
||||
if (result >= RESULT_OK) {
|
||||
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
|
||||
cout << " failed read " << fields->getName(-1) << " >" << check[2] << " " << check[3]
|
||||
<< "< error: unexpectedly succeeded" << endl;
|
||||
error = true;
|
||||
} else {
|
||||
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
|
||||
cout << " failed read " << fields->getName(-1) << " >" << check[2] << " " << check[3]
|
||||
<< "< OK" << endl;
|
||||
}
|
||||
} else if (result < RESULT_OK) {
|
||||
cout << " read " << fields->getName() << " >" << check[2] << " " << check[3]
|
||||
cout << " read " << fields->getName(-1) << " >" << check[2] << " " << check[3]
|
||||
<< "< error: " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
} else {
|
||||
@@ -641,21 +640,21 @@ int main() {
|
||||
|
||||
if (verbosity == 0) {
|
||||
istringstream input(expectStr);
|
||||
result = fields->write(input, writeMstr, 0);
|
||||
result = fields->write(UI_FIELD_SEPARATOR, 0, &input, &writeMstr, NULL);
|
||||
if (result >= RESULT_OK) {
|
||||
result = fields->write(input, writeSstr, 0);
|
||||
result = fields->write(UI_FIELD_SEPARATOR, 0, &input, &writeSstr, NULL);
|
||||
}
|
||||
if (failedWrite) {
|
||||
if (result >= RESULT_OK) {
|
||||
cout << " failed write " << fields->getName() << " >"
|
||||
cout << " failed write " << fields->getName(-1) << " >"
|
||||
<< expectStr << "< error: unexpectedly succeeded" << endl;
|
||||
error = true;
|
||||
} else {
|
||||
cout << " failed write " << fields->getName() << " >"
|
||||
cout << " failed write " << fields->getName(-1) << " >"
|
||||
<< expectStr << "< OK" << endl;
|
||||
}
|
||||
} else if (result < RESULT_OK) {
|
||||
cout << " write " << fields->getName() << " >" << expectStr
|
||||
cout << " write " << fields->getName(-1) << " >" << expectStr
|
||||
<< "< error: " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
} else {
|
||||
|
||||
@@ -40,7 +40,7 @@ int main() {
|
||||
|
||||
while (1) {
|
||||
symbol_t byte = 0;
|
||||
result = device->recv(0, byte);
|
||||
result = device->recv(0, &byte);
|
||||
|
||||
if (result == RESULT_OK) {
|
||||
cout << hex << setw(2) << setfill('0')
|
||||
|
||||
@@ -73,8 +73,8 @@ static unsigned int baseLine = 0;
|
||||
|
||||
class NoopReader : public FileReader {
|
||||
public:
|
||||
result_t addFromFile(vector<string>& row, string& errorDescription,
|
||||
const string filename, unsigned int lineNo) override {
|
||||
result_t addFromFile(const string& filename, unsigned int lineNo, vector<string>* row,
|
||||
string* errorDescription) override {
|
||||
return RESULT_OK;
|
||||
}
|
||||
};
|
||||
@@ -83,25 +83,25 @@ class TestReader : public MappedFileReader {
|
||||
public:
|
||||
TestReader(size_t expectedCols, size_t langCols)
|
||||
: MappedFileReader::MappedFileReader(false, ""), m_expectedCols(expectedCols), m_langCols(langCols) {}
|
||||
result_t getFieldMap(vector<string>& row, string& errorDescription, const string preferLanguage) const override {
|
||||
if (row.size() == m_expectedCols+m_langCols) {
|
||||
result_t getFieldMap(const string& preferLanguage, vector<string>* row, string* errorDescription) const override {
|
||||
if (row->size() == m_expectedCols+m_langCols) {
|
||||
cout << "get field map: split OK" << endl;
|
||||
if (m_langCols == 1) {
|
||||
row[0] = SKIP_COLUMN;
|
||||
size_t pos = row[1].find_last_of('.');
|
||||
row[1] = row[1].substr(0, pos);
|
||||
(*row)[0] = SKIP_COLUMN;
|
||||
size_t pos = (*row)[1].find_last_of('.');
|
||||
(*row)[1] = (*row)[1].substr(0, pos);
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
cout << "get field map: error got " << static_cast<unsigned>(row.size()) << " columns, expected " <<
|
||||
cout << "get field map: error got " << static_cast<unsigned>(row->size()) << " columns, expected " <<
|
||||
static_cast<unsigned>(m_expectedCols+m_langCols) << endl;
|
||||
return RESULT_ERR_EOF;
|
||||
}
|
||||
result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
|
||||
string& errorDescription, const string filename, unsigned int lineNo) override {
|
||||
if (row.empty() || (m_expectedCols == 3) != subRows.empty()) {
|
||||
result_t addFromFile(const string& filename, unsigned int lineNo, map<string, string>* row,
|
||||
vector< map<string, string> >* subRows, string* errorDescription) override {
|
||||
if (row->empty() || (m_expectedCols == 3) != subRows->empty()) {
|
||||
cout << "read line " << static_cast<unsigned>(baseLine + lineNo) << ": read error: got "
|
||||
<< static_cast<unsigned>(row.size()) << "/3 main, " << static_cast<unsigned>(subRows.size())
|
||||
<< static_cast<unsigned>(row->size()) << "/3 main, " << static_cast<unsigned>(subRows->size())
|
||||
<< (m_expectedCols == 3 ? "/0 sub" : "/>0 sub") << endl;
|
||||
return RESULT_ERR_EOF;
|
||||
}
|
||||
@@ -111,7 +111,7 @@ class TestReader : public MappedFileReader {
|
||||
}
|
||||
cout << "read line " << static_cast<unsigned>(baseLine + lineNo) << ": split OK" << endl;
|
||||
string resultline[3] = resultlines[lineNo - 1];
|
||||
if (row.empty()) {
|
||||
if (row->empty()) {
|
||||
cout << " result empty";
|
||||
if (resultline[0] == "") {
|
||||
cout << ": OK" << endl;
|
||||
@@ -127,7 +127,7 @@ class TestReader : public MappedFileReader {
|
||||
map<string, string>& defaults = getDefaults()[""];
|
||||
for (size_t colIdx = 0; colIdx < 3; colIdx++) {
|
||||
string col = colnames[colIdx];
|
||||
string got = row[col] + defaults[col];
|
||||
string got = (*row)[col] + defaults[col];
|
||||
string expect = resultline[colIdx];
|
||||
ostringstream type;
|
||||
type << "line " << static_cast<unsigned>(baseLine + lineNo) << " column \"" << col << "\"";
|
||||
@@ -137,17 +137,17 @@ class TestReader : public MappedFileReader {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
if (row.size() > 3) {
|
||||
if (row->size() > 3) {
|
||||
ostringstream type;
|
||||
type << "line " << static_cast<unsigned>(baseLine + lineNo);
|
||||
verify(false, type.str(), "", false, "", "extra column");
|
||||
error = true;
|
||||
}
|
||||
|
||||
for (size_t subIdx = 0; subIdx < subRows.size(); subIdx++) {
|
||||
for (size_t subIdx = 0; subIdx < subRows->size(); subIdx++) {
|
||||
string resultsubline[4] = resultsublines[lineNo - 1][subIdx];
|
||||
row = subRows[subIdx];
|
||||
if (row.empty()) {
|
||||
*row = (*subRows)[subIdx];
|
||||
if (row->empty()) {
|
||||
cout << " sub " << subIdx << " result empty";
|
||||
if (resultline[0] == "") {
|
||||
cout << ": OK" << endl;
|
||||
@@ -161,7 +161,7 @@ class TestReader : public MappedFileReader {
|
||||
vector< map<string, string> >& subDefaults = getSubDefaults()[""];
|
||||
for (size_t colIdx = 0; colIdx < 2; colIdx++) {
|
||||
string col = resultsubline[colIdx*2];
|
||||
string got = row[col];
|
||||
string got = (*row)[col];
|
||||
if (subIdx < subDefaults.size()) {
|
||||
got += subDefaults[subIdx][col];
|
||||
}
|
||||
@@ -174,7 +174,7 @@ class TestReader : public MappedFileReader {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
if (row.size() > 2) {
|
||||
if (row->size() > 2) {
|
||||
ostringstream type;
|
||||
type << "line " << static_cast<unsigned>(baseLine + lineNo) << " sub " << subIdx;
|
||||
verify(false, type.str(), "", false, "", "extra sub column");
|
||||
@@ -196,14 +196,14 @@ int main(int argc, char** argv) {
|
||||
size_t hash = 0, size = 0;
|
||||
time_t time = 0;
|
||||
string errorDescription;
|
||||
result_t result = reader.readFromFile(argv[argpos], errorDescription, false, NULL, &hash, &size, &time);
|
||||
result_t result = reader.readFromFile(argv[argpos], false, NULL, &errorDescription, &hash, &size, &time);
|
||||
cout << argv[argpos] << " ";
|
||||
if (result != RESULT_OK) {
|
||||
cout << getResultCode(result) << ", " << errorDescription << endl;
|
||||
error = true;
|
||||
continue;
|
||||
}
|
||||
FileReader::formatHash(hash, cout);
|
||||
FileReader::formatHash(hash, &cout);
|
||||
cout << " " << size << " " << time << endl;
|
||||
}
|
||||
return error ? 1 : 0;
|
||||
@@ -226,7 +226,7 @@ int main(int argc, char** argv) {
|
||||
string errorDescription;
|
||||
while (ifs.peek() != EOF) {
|
||||
istringstream str;
|
||||
result_t result = reader.readLineFromStream(ifs, errorDescription, "", lineNo, row, true, &hash, &size);
|
||||
result_t result = reader.readLineFromStream("", true, &ifs, &lineNo, &row, &errorDescription, &hash, &size);
|
||||
if (result != RESULT_OK) {
|
||||
cout << " error " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
@@ -267,7 +267,7 @@ int main(int argc, char** argv) {
|
||||
subDefaults[0]["subcol 2"] = ";default of sub 0 subcol 2";
|
||||
while (ifs.peek() != EOF) {
|
||||
istringstream str;
|
||||
result_t result = reader2.readLineFromStream(ifs, errorDescription, "", lineNo, row, true, &hash, &size);
|
||||
result_t result = reader2.readLineFromStream("", true, &ifs, &lineNo, &row, &errorDescription, &hash, &size);
|
||||
if (result != RESULT_OK) {
|
||||
cout << " error " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
|
||||
@@ -54,7 +54,7 @@ DataFieldTemplates* templates = NULL;
|
||||
|
||||
namespace ebusd {
|
||||
|
||||
DataFieldTemplates* getTemplates(const string filename) {
|
||||
DataFieldTemplates* getTemplates(const string& filename) {
|
||||
if (filename == "") { // avoid compiler warning
|
||||
return templates;
|
||||
}
|
||||
@@ -71,7 +71,9 @@ int main() {
|
||||
unsigned int baseLine = __LINE__+1;
|
||||
string checks[][5] = {
|
||||
{"date,HDA:3,,,Datum", "", "", "", "template"},
|
||||
{"bdate:date,BDA,,,Datum", "", "", "", "template"},
|
||||
{"time,VTI,,,", "", "", "", "template"},
|
||||
{"btime:time,BTI,,,Uhrzeit", "", "", "", "template"},
|
||||
{"dcfstate,UCH,0=nosignal;1=ok;2=sync;3=valid,,", "", "", "", "template"},
|
||||
{"temp,D2C,,°C,Temperatur", "", "", "", "template"},
|
||||
{"temp1,D1C,,°C,Temperatur", "", "", "", "template"},
|
||||
@@ -93,6 +95,8 @@ int main() {
|
||||
{"r,cir,name,,,25,B509,0d28,,m,sensorc,,,,,,temp", "-14.00", "ff25b509030d2855", "0220ff", ""},
|
||||
{"u,cir,first,,,fe,0700,,x,,bda", "26.10.2014", "fffe07000426100614", "00", "p"},
|
||||
{"u,broadcast,hwStatus,,,fe,b505,27,,,UCH,,,,,,UCH,,,,,,UCH,,,", "0;19;0", "10feb505042700130097", "00", ""},
|
||||
{"u,broadcast,datetime,Datum/Uhrzeit,,fe,0700,,outsidetemp,,temp2,,°C,Aussentemperatur,time,,btime,,,,date,,BDA,,,Datum", "outsidetemp=14.500 °C [Aussentemperatur];time=12:25:01 [Uhrzeit];date=01.05.2017 [Datum]", "10fe070009800e01251201050017", "", "D"},
|
||||
{"u,broadcast,datetime,Datum Uhrzeit,,fe,0700,,,,temp2;btime;bdate", "temp2=14.500 °C [Temperatur];time=12:25:01 [Uhrzeit];date=01.05.2017 [Datum]", "10fe070009800e01251201050017", "", "D"},
|
||||
{"w,cir,first,,,15,b509,0400,date,,bda", "26.10.2014", "ff15b50906040026100614", "00", ""},
|
||||
{"w,cir,first,,,15,b509", "", "ff15b50900", "00", ""},
|
||||
{"*w,,,,,,b505,2d", "", "", "", ""},
|
||||
@@ -147,12 +151,12 @@ int main() {
|
||||
istringstream dummystr("#");
|
||||
string errorDescription;
|
||||
vector<string> row;
|
||||
templates->readLineFromStream(dummystr, errorDescription, __FILE__, lineNo, row, false);
|
||||
templates->readLineFromStream(__FILE__, false, &dummystr, &lineNo, &row, &errorDescription, NULL, NULL);
|
||||
lineNo = 0;
|
||||
MessageMap* messages = new MessageMap("");
|
||||
dummystr.clear();
|
||||
dummystr.str("#");
|
||||
messages->readLineFromStream(dummystr, errorDescription, __FILE__, lineNo, row, false);
|
||||
messages->readLineFromStream(__FILE__, false, &dummystr, &lineNo, &row, &errorDescription, NULL, NULL);
|
||||
vector< vector<string> > defaultsRows;
|
||||
Message* message = NULL;
|
||||
vector<MasterSymbolString*> mstrs;
|
||||
@@ -183,7 +187,7 @@ int main() {
|
||||
lineNo = baseLine + i;
|
||||
cout << "line " << (lineNo+1) << " ";
|
||||
if (isTemplate) {
|
||||
result = templates->readLineFromStream(isstr, errorDescription, __FILE__, lineNo, row);
|
||||
result = templates->readLineFromStream(__FILE__, false, &isstr, &lineNo, &row, &errorDescription, NULL, NULL);
|
||||
if (result != RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": template read error: " << getResultCode(result) << ", " << errorDescription
|
||||
<< endl;
|
||||
@@ -197,7 +201,7 @@ int main() {
|
||||
}
|
||||
if (isstr.peek() == '*') {
|
||||
// store defaults or condition
|
||||
result = messages->readLineFromStream(isstr, errorDescription, __FILE__, lineNo, row);
|
||||
result = messages->readLineFromStream(__FILE__, false, &isstr, &lineNo, &row, &errorDescription, NULL, NULL);
|
||||
if (result != RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": default read error: " << getResultCode(result) << ", " << errorDescription << endl;
|
||||
error = true;
|
||||
@@ -279,7 +283,7 @@ int main() {
|
||||
}
|
||||
cout << "\"" << check[2] << "\": find OK" << endl;
|
||||
} else {
|
||||
result = messages->readLineFromStream(isstr, errorDescription, __FILE__, lineNo, row);
|
||||
result = messages->readLineFromStream(__FILE__, false, &isstr, &lineNo, &row, &errorDescription, NULL, NULL);
|
||||
if (failedCreate) {
|
||||
if (result == RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": failed create error: unexpectedly succeeded" << endl;
|
||||
@@ -345,11 +349,11 @@ int main() {
|
||||
}
|
||||
ostringstream output;
|
||||
if (withMessageDump && !decodeJson) {
|
||||
message->dump(output, NULL, true);
|
||||
message->dump(NULL, true, &output);
|
||||
output << ": ";
|
||||
}
|
||||
result = message->decodeLastData(output,
|
||||
(decodeVerbose?OF_NAMES|OF_UNITS|OF_COMMENTS:0)|(decodeJson?OF_NAMES|OF_JSON:0), false);
|
||||
result = message->decodeLastData(false, NULL, -1,
|
||||
(decodeVerbose?OF_NAMES|OF_UNITS|OF_COMMENTS:0)|(decodeJson?OF_NAMES|OF_JSON:0), &output);
|
||||
if (result != RESULT_OK) {
|
||||
cout << " \"" << check[2] << "\" / \"" << check[3] << "\": decode error: "
|
||||
<< getResultCode(result) << endl;
|
||||
@@ -385,7 +389,7 @@ int main() {
|
||||
if (!message->isPassive() && (withInput || !decode)) {
|
||||
istringstream input(inputStr);
|
||||
MasterSymbolString writeMstr;
|
||||
result = message->prepareMaster(0xff, writeMstr, input);
|
||||
result = message->prepareMaster(0, 0xff, SYN, UI_FIELD_SEPARATOR, &input, &writeMstr);
|
||||
if (failedPrepare) {
|
||||
if (result == RESULT_OK) {
|
||||
cout << " \"" << inputStr << "\": failed prepare error: unexpectedly succeeded" << endl;
|
||||
|
||||
@@ -120,7 +120,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
string fetchData(ebusd::TCPSocket* socket, bool& listening) {
|
||||
string fetchData(ebusd::TCPSocket* socket, bool listening) {
|
||||
char data[1024];
|
||||
ssize_t datalen;
|
||||
ostringstream ostream;
|
||||
|
||||
Reference in New Issue
Block a user