protozero/filtering: Extract MessageFilter::Config class
The MessageFilter stores the configuration of the filter and some
runtime state about the messages that are being parsed.
This commit moves all the configuration into a separate class, to make
the copy constuctor easier to maintain. Now the fields do not need to be
listed explicitly anymore.
Change-Id: I9305f50ab624ad96f57b3aac7e8da40767141e7a
diff --git a/src/protozero/filtering/message_filter.cc b/src/protozero/filtering/message_filter.cc
index 44c9851..8461938 100644
--- a/src/protozero/filtering/message_filter.cc
+++ b/src/protozero/filtering/message_filter.cc
@@ -75,19 +75,19 @@
}
MessageFilter::MessageFilter(const MessageFilter& other)
- : root_msg_index_(other.root_msg_index_),
- filter_(other.filter_),
- string_filter_(other.string_filter_) {
+ : config_(other.config_) {
stack_.emplace_back();
}
MessageFilter::~MessageFilter() = default;
-bool MessageFilter::LoadFilterBytecode(const void* filter_data, size_t len) {
+bool MessageFilter::Config::LoadFilterBytecode(const void* filter_data,
+ size_t len) {
return filter_.Load(filter_data, len);
}
-bool MessageFilter::SetFilterRoot(std::initializer_list<uint32_t> field_ids) {
+bool MessageFilter::Config::SetFilterRoot(
+ std::initializer_list<uint32_t> field_ids) {
uint32_t root_msg_idx = 0;
for (uint32_t field_id : field_ids) {
auto res = filter_.Query(root_msg_idx, field_id);
@@ -123,7 +123,7 @@
stack_[0].eat_next_bytes = UINT32_MAX;
// stack_[1] is the actual root message.
stack_[1].in_bytes_limit = total_len;
- stack_[1].msg_index = root_msg_index_;
+ stack_[1].msg_index = config_.root_msg_index();
// Process the input data and write the output.
for (size_t slice_idx = 0; slice_idx < num_slices; ++slice_idx) {
@@ -163,7 +163,7 @@
} else if (state->action == StackState::kFilterString) {
*(out_++) = octet;
if (state->eat_next_bytes == 0) {
- string_filter_.MaybeFilter(
+ config_.string_filter().MaybeFilter(
reinterpret_cast<char*>(state->filter_string_ptr),
static_cast<size_t>(out_ - state->filter_string_ptr));
}
@@ -174,7 +174,7 @@
// a varint field, only the last byte yields a token, all the other bytes
// return an invalid token, they just update the internal tokenizer state.
if (token.valid()) {
- auto filter = filter_.Query(state->msg_index, token.field_id);
+ auto filter = config_.filter().Query(state->msg_index, token.field_id);
switch (token.type) {
case proto_utils::ProtoWireType::kVarInt:
if (filter.allowed && filter.simple_field())
diff --git a/src/protozero/filtering/message_filter.h b/src/protozero/filtering/message_filter.h
index 6daf77f..2fc09ef 100644
--- a/src/protozero/filtering/message_filter.h
+++ b/src/protozero/filtering/message_filter.h
@@ -53,6 +53,21 @@
// intended only on host tools.
class MessageFilter {
public:
+ class Config {
+ public:
+ bool LoadFilterBytecode(const void* filter_data, size_t len);
+ bool SetFilterRoot(std::initializer_list<uint32_t> field_ids);
+
+ const FilterBytecodeParser& filter() const { return filter_; }
+ const StringFilter& string_filter() const { return string_filter_; }
+ StringFilter& string_filter() { return string_filter_; }
+ uint32_t root_msg_index() const { return root_msg_index_; }
+
+ private:
+ FilterBytecodeParser filter_;
+ StringFilter string_filter_;
+ uint32_t root_msg_index_ = 0;
+ };
MessageFilter();
explicit MessageFilter(const MessageFilter&);
~MessageFilter();
@@ -74,7 +89,9 @@
// message. Must be called before the first call to FilterMessage*().
// |filter_data| must point to a byte buffer for a proto-encoded ProtoFilter
// message (see proto_filter.proto).
- bool LoadFilterBytecode(const void* filter_data, size_t len);
+ bool LoadFilterBytecode(const void* filter_data, size_t len) {
+ return config_.LoadFilterBytecode(filter_data, len);
+ }
// This affects the filter starting point of the subsequent FilterMessage*()
// calls. By default the filtering process starts from the message @ index 0,
@@ -88,7 +105,9 @@
// will identify the sub-message for the field "root.1.2.3" and use that.
// In order for this to succeed all the fields in the path must be allowed
// in the filter and must be a nested message type.
- bool SetFilterRoot(std::initializer_list<uint32_t> field_ids);
+ bool SetFilterRoot(std::initializer_list<uint32_t> field_ids) {
+ return config_.SetFilterRoot(field_ids);
+ }
// Takes an input message, fragmented in arbitrary slices, and returns a
// filtered message in output.
@@ -115,11 +134,10 @@
return field_usage_;
}
- // Exposed only for DCHECKS in TracingServiceImpl.
- uint32_t root_msg_index() { return root_msg_index_; }
+ const Config& config() const { return config_; }
// Retuns the helper class used to perform string filtering.
- StringFilter& string_filter() { return string_filter_; }
+ StringFilter& string_filter() { return config_.string_filter(); }
private:
// This is called by FilterMessageFragments().
@@ -204,14 +222,13 @@
uint32_t out_written() { return static_cast<uint32_t>(out_ - &out_buf_[0]); }
// WARNING: Some of these fields should be in the copy constructor.
+ Config config_;
+
std::unique_ptr<uint8_t[]> out_buf_;
uint8_t* out_ = nullptr;
uint8_t* out_end_ = nullptr;
- uint32_t root_msg_index_ = 0;
- FilterBytecodeParser filter_;
MessageTokenizer tokenizer_;
- StringFilter string_filter_;
std::vector<StackState> stack_;
bool error_ = false;
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index 5960a24..257accb 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -2402,7 +2402,7 @@
protozero::MessageFilter& trace_filter = *tracing_session->trace_filter;
// The filter root shoud be reset from protos.Trace to protos.TracePacket
// by the earlier call to SetFilterRoot() in EnableTracing().
- PERFETTO_DCHECK(trace_filter.root_msg_index() != 0);
+ PERFETTO_DCHECK(trace_filter.config().root_msg_index() != 0);
std::vector<protozero::MessageFilter::InputSlice> filter_input;
auto start = base::GetWallTimeNs();
for (TracePacket& packet : *packets) {