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:
john30
2017-05-01 15:31:09 +02:00
parent 3d4d876d5e
commit 7b11a540b6
32 changed files with 1946 additions and 1949 deletions
+146 -141
View File
@@ -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
View File
@@ -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;
+2 -2
View File
@@ -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;
}
+6 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+5 -5
View File
@@ -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;
+34
View File
@@ -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
View File
@@ -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.
+19 -22
View File
@@ -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
+6 -8
View File
@@ -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;
};
/**
+28 -28
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+126 -124
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+9 -9
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+165 -180
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+30 -31
View File
@@ -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 {
+1 -1
View File
@@ -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')
+24 -24
View File
@@ -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;
+14 -10
View File
@@ -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;
+1 -1
View File
@@ -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;