extended "-i" parameter of find command to accept further ID parts

This commit is contained in:
john30
2015-11-22 14:19:38 +01:00
parent 427d6a7dca
commit 0d97462dee
3 changed files with 82 additions and 46 deletions
+32 -14
View File
@@ -647,7 +647,7 @@ string MainLoop::executeFind(vector<string> &args)
bool verbose = false, configFormat = false, exact = false, withRead = true, withWrite = false, withPassive = true, first = true, onlyWithData = false; bool verbose = false, configFormat = false, exact = false, withRead = true, withWrite = false, withPassive = true, first = true, onlyWithData = false;
vector<size_t> columns; vector<size_t> columns;
string circuit; string circuit;
short pb = -1; vector<unsigned char> id;
while (args.size() > argPos && args[argPos][0] == '-') { while (args.size() > argPos && args[argPos][0] == '-') {
if (args[argPos] == "-v") if (args[argPos] == "-v")
verbose = true; verbose = true;
@@ -706,16 +706,18 @@ string MainLoop::executeFind(vector<string> &args)
onlyWithData = true; onlyWithData = true;
else if (args[argPos] == "-i") { else if (args[argPos] == "-i") {
argPos++; argPos++;
if (argPos >= args.size()) { if (argPos >= args.size() || !id.empty()) {
argPos = 0; // print usage argPos = 0; // print usage
break; break;
} }
const char* str = args[argPos].c_str(); result_t result = Message::parseId(args[argPos], id);
result_t result = RESULT_OK;
pb = (short)parseInt(str+2, 16, 0, 0xff, result);
if (result != RESULT_OK) { if (result != RESULT_OK) {
return getResultCode(result); return getResultCode(result);
} }
if (id.empty()) {
argPos = 0; // print usage
break;
}
} }
else if (args[argPos] == "-c") { else if (args[argPos] == "-c") {
argPos++; argPos++;
@@ -732,14 +734,14 @@ string MainLoop::executeFind(vector<string> &args)
argPos++; argPos++;
} }
if (argPos == 0 || args.size() < argPos || args.size() > argPos + 1) if (argPos == 0 || args.size() < argPos || args.size() > argPos + 1)
return "usage: find [-v] [-r] [-w] [-p] [-d] [-i PB] [-f] [-F COL[,COL]*] [-e] [-c CIRCUIT] [NAME]\n" return "usage: find [-v] [-r] [-w] [-p] [-d] [-i ID] [-f] [-F COL[,COL]*] [-e] [-c CIRCUIT] [NAME]\n"
" Find message(s).\n" " Find message(s).\n"
" -v be verbose (append destination address and update time)\n" " -v be verbose (append destination address and update time)\n"
" -r limit to active read messages (default: read + passive)\n" " -r limit to active read messages (default: read + passive)\n"
" -w limit to active write messages (default: read + passive)\n" " -w limit to active write messages (default: read + passive)\n"
" -p limit to passive messages (default: read + passive)\n" " -p limit to passive messages (default: read + passive)\n"
" -d only include messages with actual data\n" " -d only include messages with actual data\n"
" -i PB limit to messages with primary command byte PB (in hex)\n" " -i ID limit to messages with ID (in hex, PB, SB and further ID bytes)\n"
" -f list messages in CSV configuration file format\n" " -f list messages in CSV configuration file format\n"
" -F COL[,COL]* list messages in the specified format\n" " -F COL[,COL]* list messages in the specified format\n"
" (COL: type,circuit,name,comment,qq,zz,pbsb,id,fields)\n" " (COL: type,circuit,name,comment,qq,zz,pbsb,id,fields)\n"
@@ -748,7 +750,7 @@ string MainLoop::executeFind(vector<string> &args)
" NAME the NAME of the messages to find (or a part thereof without '-e')"; " NAME the NAME of the messages to find (or a part thereof without '-e')";
deque<Message*> messages = m_messages->findAll( deque<Message*> messages = m_messages->findAll(
circuit, args.size() == argPos ? "" : args[argPos], pb, exact, withRead, withWrite, withPassive circuit, args.size() == argPos ? "" : args[argPos], exact, withRead, withWrite, withPassive
); );
bool found = false; bool found = false;
@@ -756,6 +758,22 @@ string MainLoop::executeFind(vector<string> &args)
char str[32]; char str[32];
for (deque<Message*>::iterator it = messages.begin(); it < messages.end();) { for (deque<Message*>::iterator it = messages.begin(); it < messages.end();) {
Message* message = *it++; Message* message = *it++;
if (!id.empty()) {
vector<unsigned char> msgId = message->getId();
if (id.size()>msgId.size()) {
continue;
}
bool mismatch = false;
for (size_t pos = 0; pos<id.size(); pos++) {
if (id[pos]!=msgId[pos]) {
mismatch = true;
break;
}
}
if (mismatch) {
continue;
}
}
time_t lastup = message->getLastUpdateTime(); time_t lastup = message->getLastUpdateTime();
if (onlyWithData && lastup == 0) if (onlyWithData && lastup == 0)
continue; continue;
@@ -1009,7 +1027,7 @@ string MainLoop::executeHelp()
" Read hex message: read [-f] [-m SECONDS] [-c CIRCUIT] -h ZZPBSBNNDx\n" " Read hex message: read [-f] [-m SECONDS] [-c CIRCUIT] -h ZZPBSBNNDx\n"
" write|w Write value(s): write [-d ZZ] [-c] CIRCUIT NAME [VALUE[;VALUE]*]\n" " write|w Write value(s): write [-d ZZ] [-c] CIRCUIT NAME [VALUE[;VALUE]*]\n"
" Write hex message: write -h ZZPBSBNNDx\n" " Write hex message: write -h ZZPBSBNNDx\n"
" find|f Find message(s): find [-v] [-r] [-w] [-p] [-d] [-i PB] [-f] [-F COL[,COL]*] [-e] [-c CIRCUIT] [NAME]\n" " find|f Find message(s): find [-v] [-r] [-w] [-p] [-d] [-i ID] [-f] [-F COL[,COL]*] [-e] [-c CIRCUIT] [NAME]\n"
" listen|l Listen for updates: listen [stop]\n" " listen|l Listen for updates: listen [stop]\n"
" state|s Report bus state\n" " state|s Report bus state\n"
" info|i Report information about the daemon, the configuration, and seen devices.\n" " info|i Report information about the daemon, the configuration, and seen devices.\n"
@@ -1039,12 +1057,12 @@ string MainLoop::executeGet(vector<string> &args, bool& connected)
int type = -1; int type = -1;
if (strncmp(uri.c_str(), "/data/", 6) == 0) { if (strncmp(uri.c_str(), "/data/", 6) == 0) {
string clazz = "", name = ""; string circuit = "", name = "";
size_t pos = uri.find('/', 6); size_t pos = uri.find('/', 6);
if (pos == string::npos) { if (pos == string::npos) {
clazz = uri.substr(6); circuit = uri.substr(6);
} else { } else {
clazz = uri.substr(6, pos-6); circuit = uri.substr(6, pos-6);
name = uri.substr(pos+1); name = uri.substr(pos+1);
} }
time_t since = 0; time_t since = 0;
@@ -1080,7 +1098,7 @@ string MainLoop::executeGet(vector<string> &args, bool& connected)
break; break;
} }
} }
deque<Message*> messages = m_messages->findAll(clazz, name, -1, exact, true, false, true); deque<Message*> messages = m_messages->findAll(circuit, name, exact, true, false, true);
bool first = true; bool first = true;
result << "{"; result << "{";
@@ -1243,7 +1261,7 @@ string MainLoop::getUpdates(time_t since, time_t until)
ostringstream result; ostringstream result;
deque<Message*> messages; deque<Message*> messages;
messages = m_messages->findAll("", "", -1, false, true, true, true); messages = m_messages->findAll("", "", false, true, true, true);
for (deque<Message*>::iterator it = messages.begin(); it < messages.end();) { for (deque<Message*>::iterator it = messages.begin(); it < messages.end();) {
Message* message = *it++; Message* message = *it++;
+35 -27
View File
@@ -70,10 +70,11 @@ Message::Message(const string circuit, const string name,
m_key = key; m_key = key;
} }
Message::Message(const bool isWrite, const bool isPassive, Message::Message(const string circuit, const string name,
const bool isWrite, const bool isPassive,
const unsigned char pb, const unsigned char sb, const unsigned char pb, const unsigned char sb,
DataField* data, const bool deleteData) DataField* data, const bool deleteData)
: m_circuit(), m_name(), m_isWrite(isWrite), : m_circuit(circuit), m_name(name), m_isWrite(isWrite),
m_isPassive(isPassive), m_comment(), m_isPassive(isPassive), m_comment(),
m_srcAddress(SYN), m_dstAddress(SYN), m_srcAddress(SYN), m_dstAddress(SYN),
m_data(data), m_deleteData(true), m_data(data), m_deleteData(true),
@@ -108,6 +109,31 @@ string getDefault(const string value, vector<string>* defaults, size_t pos)
return defaults->at(pos); return defaults->at(pos);
} }
result_t Message::parseId(string input, vector<unsigned char>& id)
{
istringstream in(input);
while (!in.eof()) {
while (in.peek() == ' ')
in.get();
if (in.eof()) // no more digits
break;
input.clear();
input.push_back((char)in.get());
if (in.eof()) {
return RESULT_ERR_INVALID_ARG; // too short hex
}
input.push_back((char)in.get());
result_t result;
unsigned char value = (unsigned char)parseInt(input.c_str(), 16, 0, 0xff, result);
if (result != RESULT_OK) {
return result; // invalid hex value
}
id.push_back(value);
}
return RESULT_OK;
}
result_t Message::create(vector<string>::iterator& it, const vector<string>::iterator end, result_t Message::create(vector<string>::iterator& it, const vector<string>::iterator end,
vector< vector<string> >* defaultsRows, Condition* condition, const string& filename, vector< vector<string> >* defaultsRows, Condition* condition, const string& filename,
DataFieldTemplates* templates, vector<Message*>& messages) DataFieldTemplates* templates, vector<Message*>& messages)
@@ -226,25 +252,9 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
else else
token = getDefault("", defaults, defaultPos).append(token); token = getDefault("", defaults, defaultPos).append(token);
} }
istringstream input(token); result = parseId(token, id);
while (!input.eof()) { if (result!=RESULT_OK)
while (input.peek() == ' ') return result;
input.get();
if (input.eof()) // no more digits
break;
token.clear();
token.push_back((char)input.get());
if (input.eof()) {
return RESULT_ERR_INVALID_ARG; // to short hex
}
token.push_back((char)input.get());
unsigned char value = (unsigned char)parseInt(token.c_str(), 16, 0, 0xff, result);
if (result != RESULT_OK) {
return result; // invalid hex value
}
id.push_back(value);
}
if (pos == 0 && id.size() != 2) if (pos == 0 && id.size() != 2)
return RESULT_ERR_INVALID_ARG; // missing/to short/to long PBSB return RESULT_ERR_INVALID_ARG; // missing/to short/to long PBSB
@@ -1064,7 +1074,7 @@ Message* MessageMap::find(const string& circuit, const string& name, const bool
return NULL; return NULL;
} }
deque<Message*> MessageMap::findAll(const string& circuit, const string& name, const short pb, const bool completeMatch, deque<Message*> MessageMap::findAll(const string& circuit, const string& name, const bool completeMatch,
const bool withRead, const bool withWrite, const bool withPassive) const bool withRead, const bool withWrite, const bool withPassive)
{ {
deque<Message*> ret; deque<Message*> ret;
@@ -1074,7 +1084,6 @@ deque<Message*> MessageMap::findAll(const string& circuit, const string& name, c
FileReader::tolower(lname); FileReader::tolower(lname);
bool checkCircuit = lcircuit.length() > 0; bool checkCircuit = lcircuit.length() > 0;
bool checkName = name.length() > 0; bool checkName = name.length() > 0;
bool checkPb = pb >= 0;
for (map<string, vector<Message*> >::iterator it = m_messagesByName.begin(); it != m_messagesByName.end(); it++) { for (map<string, vector<Message*> >::iterator it = m_messagesByName.begin(); it != m_messagesByName.end(); it++) {
if (it->first[0] == '-') // avoid duplicates: instances stored multiple times have a key starting with "-" if (it->first[0] == '-') // avoid duplicates: instances stored multiple times have a key starting with "-"
continue; continue;
@@ -1093,8 +1102,6 @@ deque<Message*> MessageMap::findAll(const string& circuit, const string& name, c
if (completeMatch ? (check != lname) : (check.find(lname) == check.npos)) if (completeMatch ? (check != lname) : (check.find(lname) == check.npos))
continue; continue;
} }
if (checkPb && message->getId()[0] != pb)
continue;
if (message->isPassive()) { if (message->isPassive()) {
if (!withPassive) if (!withPassive)
continue; continue;
@@ -1184,7 +1191,7 @@ void MessageMap::invalidateCache(Message* message)
if (pos!=string::npos) if (pos!=string::npos)
circuit.resize(pos); circuit.resize(pos);
string name = message->getName(); string name = message->getName();
deque<Message*> messages = findAll(circuit, name, -1, false, true, true, true); deque<Message*> messages = findAll(circuit, name, false, true, true, true);
for (deque<Message*>::iterator it = messages.begin(); it != messages.end(); it++) { for (deque<Message*>::iterator it = messages.begin(); it != messages.end(); it++) {
if (*it==message) if (*it==message)
continue; continue;
@@ -1244,7 +1251,8 @@ void MessageMap::clear()
for (map<unsigned long long, vector<Message*> >::iterator it = m_messagesByKey.begin(); it != m_messagesByKey.end(); it++) { for (map<unsigned long long, vector<Message*> >::iterator it = m_messagesByKey.begin(); it != m_messagesByKey.end(); it++) {
vector<Message*> keyMessages = it->second; vector<Message*> keyMessages = it->second;
for (vector<Message*>::iterator kit = keyMessages.begin(); kit != keyMessages.end(); kit++) { for (vector<Message*>::iterator kit = keyMessages.begin(); kit != keyMessages.end(); kit++) {
delete *kit; Message* message = *kit;
delete message;
} }
keyMessages.clear(); keyMessages.clear();
} }
+15 -5
View File
@@ -94,7 +94,9 @@ public:
Condition* condition=NULL); Condition* condition=NULL);
/** /**
* Construct a new temporary instance. * Construct a new simple instance (e.g. for scanning).
* @param circuit the circuit name, or empty for not storing by name.
* @param name the message name (unique within the same circuit and type), or empty for not storing by name.
* @param isWrite whether this is a write message. * @param isWrite whether this is a write message.
* @param isPassive true if message can only be initiated by a participant other than us, * @param isPassive true if message can only be initiated by a participant other than us,
* false if message can be initiated by any participant. * false if message can be initiated by any participant.
@@ -103,7 +105,8 @@ public:
* @param data the @a DataField for encoding/decoding the message. * @param data the @a DataField for encoding/decoding the message.
* @param deleteData whether to delete the @a DataField during destruction. * @param deleteData whether to delete the @a DataField during destruction.
*/ */
Message(const bool isWrite, const bool isPassive, Message(const string circuit, const string name,
const bool isWrite, const bool isPassive,
const unsigned char pb, const unsigned char sb, const unsigned char pb, const unsigned char sb,
DataField* data, const bool deleteData); DataField* data, const bool deleteData);
@@ -112,6 +115,14 @@ public:
*/ */
virtual ~Message() { if (m_deleteData) delete m_data; } virtual ~Message() { if (m_deleteData) delete m_data; }
/**
* Parse an ID part from the input @a string.
* @param input the input @a string, hex digits optionally separated by space.
* @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<unsigned char>& id);
/** /**
* Factory method for creating new instances. * Factory method for creating new instances.
* @param it the iterator to traverse for the definition parts. * @param it the iterator to traverse for the definition parts.
@@ -644,7 +655,7 @@ public:
MessageMap(const bool addAll=false) : FileReader::FileReader(true), MessageMap(const bool addAll=false) : FileReader::FileReader(true),
m_addAll(addAll), m_maxIdLength(0), m_messageCount(0), m_conditionalMessageCount(0), m_passiveMessageCount(0) m_addAll(addAll), m_maxIdLength(0), m_messageCount(0), m_conditionalMessageCount(0), m_passiveMessageCount(0)
{ {
m_scanMessage = new Message(false, false, 0x07, 0x04, DataFieldSet::getIdentFields(), true); m_scanMessage = new Message("scan", "ident", false, false, 0x07, 0x04, DataFieldSet::getIdentFields(), true);
} }
/** /**
@@ -720,7 +731,6 @@ public:
* Find all active get @a Message instances for the specified circuit and name. * Find all active get @a Message instances for the specified circuit and name.
* @param circuit the circuit name, or empty for any. * @param circuit the circuit name, or empty for any.
* @param name the message name, or empty for any. * @param name the message name, or empty for any.
* @param pb the primary ID byte, or -1 for any (default any).
* @param completeMatch false to also include messages where the circuit and name matches only a part of the given circuit and name (default true). * @param completeMatch false to also include messages where the circuit and name matches only a part of the given circuit and name (default true).
* @param withRead true to include read messages (default true). * @param withRead true to include read messages (default true).
* @param withWrite true to include write messages (default false). * @param withWrite true to include write messages (default false).
@@ -728,7 +738,7 @@ public:
* @return the found @a Message instances. * @return the found @a Message instances.
* Note: the caller may not free the returned instances. * Note: the caller may not free the returned instances.
*/ */
deque<Message*> findAll(const string& circuit, const string& name, const short pb=-1, const bool completeMatch=true, deque<Message*> findAll(const string& circuit, const string& name, const bool completeMatch=true,
const bool withRead=true, const bool withWrite=false, const bool withPassive=false); const bool withRead=true, const bool withWrite=false, const bool withPassive=false);
/** /**