|
@@ -895,9 +895,76 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static char* skipSpaces(char* s) {
|
|
|
|
|
+ while (*s == ' ') s++;
|
|
|
|
|
+ return s;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void rtrimSpaces(char* s) {
|
|
|
|
|
+ char* e = s + strlen(s);
|
|
|
|
|
+ while (e > s && e[-1] == ' ') *--e = '\0';
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static char* takeToken(char** cursor) {
|
|
|
|
|
+ char* p = skipSpaces(*cursor);
|
|
|
|
|
+ if (*p == '\0') { *cursor = p; return nullptr; }
|
|
|
|
|
+ char* tok = p;
|
|
|
|
|
+ while (*p && *p != ' ') p++;
|
|
|
|
|
+ if (*p) *p++ = '\0';
|
|
|
|
|
+ *cursor = p;
|
|
|
|
|
+ return tok;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static char* splitNameJump(char* tok) {
|
|
|
|
|
+ for (char* q = tok; *q; q++) {
|
|
|
|
|
+ if (*q == '|' || *q == ',') {
|
|
|
|
|
+ *q = '\0';
|
|
|
|
|
+ char* jump = skipSpaces(q + 1);
|
|
|
|
|
+ rtrimSpaces(jump);
|
|
|
|
|
+ return jump;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return nullptr;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static bool processRegionDefSegment(RegionMap* map, char* tok, RegionEntry** cursor, char* reply) {
|
|
|
|
|
+ char* jump = splitNameJump(tok);
|
|
|
|
|
+ char* name = skipSpaces(tok);
|
|
|
|
|
+ if (*name == '\0') { snprintf(reply, 160, "Err - empty name"); return false; }
|
|
|
|
|
+ if (jump && *jump == '\0') { snprintf(reply, 160, "Err - empty jump"); return false; }
|
|
|
|
|
+
|
|
|
|
|
+ RegionEntry* r = map->putRegion(name, (*cursor)->id);
|
|
|
|
|
+ if (r == NULL) { snprintf(reply, 160, "Err - put failed: %s", name); return false; }
|
|
|
|
|
+ r->flags = 0;
|
|
|
|
|
+
|
|
|
|
|
+ if (jump) {
|
|
|
|
|
+ RegionEntry* j = map->findByNamePrefix(jump);
|
|
|
|
|
+ if (j == NULL) { snprintf(reply, 160, "Err - unknown jump: %s", jump); return false; }
|
|
|
|
|
+ *cursor = j;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ *cursor = r;
|
|
|
|
|
+ }
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void CommonCLI::handleRegionCmd(char* command, char* reply) {
|
|
void CommonCLI::handleRegionCmd(char* command, char* reply) {
|
|
|
reply[0] = 0;
|
|
reply[0] = 0;
|
|
|
|
|
|
|
|
|
|
+ // `region def`: must run before parseTextParts mutates the buffer
|
|
|
|
|
+ char* cmd = skipSpaces(command);
|
|
|
|
|
+ if (strncmp(cmd, "region def", 10) == 0 && (cmd[10] == ' ' || cmd[10] == '\0')) {
|
|
|
|
|
+ char* payload = skipSpaces(cmd + 10);
|
|
|
|
|
+ rtrimSpaces(payload);
|
|
|
|
|
+ if (*payload == '\0') { snprintf(reply, 160, "Err - empty def"); return; }
|
|
|
|
|
+
|
|
|
|
|
+ RegionEntry* cursor = &_region_map->getWildcard();
|
|
|
|
|
+ for (char* tok; (tok = takeToken(&payload)) != nullptr; ) {
|
|
|
|
|
+ if (!processRegionDefSegment(_region_map, tok, &cursor, reply)) return;
|
|
|
|
|
+ }
|
|
|
|
|
+ _region_map->exportTo(reply, 160);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
const char* parts[4];
|
|
const char* parts[4];
|
|
|
int n = mesh::Utils::parseTextParts(command, parts, 4, ' ');
|
|
int n = mesh::Utils::parseTextParts(command, parts, 4, ' ');
|
|
|
if (n == 1) {
|
|
if (n == 1) {
|