extended "-i" parameter of find command to accept further ID parts
This commit is contained in:
+32
-14
@@ -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
@@ -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
@@ -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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user