Support globs in maps
We need to remap sub folders. This is very annoying to do with one map
per folder. Recognize * and match it accordingly.
Change-Id: Ieae86dcec000206eadb913c29a8ee141e9e93f0f
diff --git a/aos/configuration.cc b/aos/configuration.cc
index f250c93..0a34b02 100644
--- a/aos/configuration.cc
+++ b/aos/configuration.cc
@@ -1,11 +1,11 @@
#include "aos/configuration.h"
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <netinet/in.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
#include <unistd.h>
#include <set>
@@ -80,8 +80,7 @@
namespace {
// Extracts the folder part of a path. Returns ./ if there is no path.
-std::string_view ExtractFolder(
- const std::string_view filename) {
+std::string_view ExtractFolder(const std::string_view filename) {
auto last_slash_pos = filename.find_last_of("/\\");
return last_slash_pos == std::string_view::npos
@@ -178,7 +177,7 @@
// Compares for equality (c == p) a channel, and a name, type tuple.
bool EqualsChannels(const Channel *c,
- ::std::pair<std::string_view, std::string_view> p) {
+ ::std::pair<std::string_view, std::string_view> p) {
return c->name()->string_view() == p.first &&
c->type()->string_view() == p.second;
}
@@ -195,8 +194,7 @@
// Maps name for the provided maps. Modifies name.
void HandleMaps(const flatbuffers::Vector<flatbuffers::Offset<aos::Map>> *maps,
- std::string_view *name, std::string_view type,
- const Node *node) {
+ std::string *name, std::string_view type, const Node *node) {
// For the same reason we merge configs in reverse order, we want to process
// maps in reverse order. That lets the outer config overwrite channels from
// the inner configs.
@@ -210,8 +208,16 @@
// Handle normal maps (now that we know that match and rename are filled
// out).
- if (i->match()->name()->string_view() != *name) {
- continue;
+ const std::string_view match_name = i->match()->name()->string_view();
+ if (match_name != *name) {
+ if (match_name.back() == '*' &&
+ std::string_view(*name).substr(
+ 0, std::min(name->size(), match_name.size() - 1)) ==
+ match_name.substr(0, match_name.size() - 1)) {
+ CHECK_EQ(match_name.find('*'), match_name.size() - 1);
+ } else {
+ continue;
+ }
}
// Handle type specific maps.
@@ -219,15 +225,19 @@
continue;
}
+ // Now handle node specific maps.
if (node != nullptr && i->match()->has_source_node() &&
i->match()->source_node()->string_view() !=
node->name()->string_view()) {
continue;
}
- VLOG(1) << "Renamed \"" << *name << "\" to \""
- << i->rename()->name()->string_view() << "\"";
- *name = i->rename()->name()->string_view();
+ std::string new_name(i->rename()->name()->string_view());
+ if (match_name.back() == '*') {
+ new_name += std::string(name->substr(match_name.size() - 1));
+ }
+ VLOG(1) << "Renamed \"" << *name << "\" to \"" << new_name << "\"";
+ *name = std::move(new_name);
}
}
@@ -298,8 +308,7 @@
{
::std::vector<flatbuffers::Offset<Channel>> channel_offsets;
for (const FlatbufferDetachedBuffer<Channel> &c : channels) {
- channel_offsets.emplace_back(
- CopyFlatBuffer<Channel>(&c.message(), &fbb));
+ channel_offsets.emplace_back(CopyFlatBuffer<Channel>(&c.message(), &fbb));
}
channels_offset = fbb.CreateVector(channel_offsets);
}
@@ -362,8 +371,36 @@
// Check that if there is a node list, all the source nodes are filled out and
// valid, and all the destination nodes are valid (and not the source). This
// is a basic consistency check.
- if (result.message().has_nodes() && config.message().has_channels()) {
- for (const Channel *c : *config.message().channels()) {
+ if (result.message().has_channels()) {
+ for (const Channel *c : *result.message().channels()) {
+ if (c->name()->string_view().back() == '/') {
+ LOG(FATAL) << "Channel names can't end with '/'";
+ }
+ if(c->name()->string_view().find("//")!= std::string_view::npos) {
+ LOG(FATAL) << ": Invalid channel name " << c->name()->string_view()
+ << ", can't use //.";
+ }
+ for (const char data : c->name()->string_view()) {
+ if (data >= '0' && data <= '9') {
+ continue;
+ }
+ if (data >= 'a' && data <= 'z') {
+ continue;
+ }
+ if (data >= 'A' && data <= 'Z') {
+ continue;
+ }
+ if (data == '-' || data == '_' || data == '/') {
+ continue;
+ }
+ LOG(FATAL) << "Invalid channel name " << c->name()->string_view()
+ << ", can only use [-a-zA-Z0-9_/]";
+ }
+ }
+ }
+
+ if (result.message().has_nodes() && result.message().has_channels()) {
+ for (const Channel *c : *result.message().channels()) {
CHECK(c->has_source_node()) << ": Channel " << FlatbufferToJson(c)
<< " is missing \"source_node\"";
CHECK(GetNode(&result.message(), c->source_node()->string_view()) !=
@@ -431,6 +468,7 @@
std::string_view type,
std::string_view application_name, const Node *node) {
const std::string_view original_name = name;
+ std::string mutable_name;
VLOG(1) << "Looking up { \"name\": \"" << name << "\", \"type\": \"" << type
<< "\" }";
@@ -443,14 +481,18 @@
if (application_iterator != config->applications()->cend() &&
EqualsApplications(*application_iterator, application_name)) {
if (application_iterator->has_maps()) {
- HandleMaps(application_iterator->maps(), &name, type, node);
+ mutable_name = std::string(name);
+ HandleMaps(application_iterator->maps(), &mutable_name, type, node);
+ name = std::string_view(mutable_name);
}
}
}
// Now do global maps.
if (config->has_maps()) {
- HandleMaps(config->maps(), &name, type, node);
+ mutable_name = std::string(name);
+ HandleMaps(config->maps(), &mutable_name, type, node);
+ name = std::string_view(mutable_name);
}
if (original_name != name) {
@@ -460,8 +502,7 @@
// Then look for the channel.
auto channel_iterator =
- std::lower_bound(config->channels()->cbegin(),
- config->channels()->cend(),
+ std::lower_bound(config->channels()->cbegin(), config->channels()->cend(),
std::make_pair(name, type), CompareChannels);
// Make sure we actually found it, and it matches.
@@ -514,7 +555,7 @@
// Search for a schema with a matching type.
const aos::FlatbufferString<reflection::Schema> *found_schema = nullptr;
- for (const aos::FlatbufferString<reflection::Schema> &schema: schemas) {
+ for (const aos::FlatbufferString<reflection::Schema> &schema : schemas) {
if (schema.message().root_table() != nullptr) {
if (schema.message().root_table()->name()->string_view() ==
c->type()->string_view()) {
@@ -771,7 +812,7 @@
}
bool ChannelMessageIsLoggedOnNode(const Channel *channel, const Node *node) {
- switch(channel->logger()) {
+ switch (channel->logger()) {
case LoggerConfig::LOCAL_LOGGER:
if (node == nullptr) {
// Single node world. If there is a local logger, then we want to use