1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SRC_PROTOZERO_FILTERING_FILTER_BYTECODE_GENERATOR_H_
18 #define SRC_PROTOZERO_FILTERING_FILTER_BYTECODE_GENERATOR_H_
19 
20 #include <stddef.h>
21 #include <stdint.h>
22 
23 #include <string>
24 #include <vector>
25 
26 namespace protozero {
27 
28 // Creates a filter bytecode that can be passed to the FilterBytecodeParser.
29 // This class is typically only used by offline tools (e.g. the proto_filter
30 // cmdline tool). See go/trace-filtering for the full filtering design.
31 class FilterBytecodeGenerator {
32  public:
33   FilterBytecodeGenerator();
34   ~FilterBytecodeGenerator();
35 
36   // Call at the end of every message. It implicitly starts a new message, there
37   // is no corresponding BeginMessage().
38   void EndMessage();
39 
40   // All the methods below must be called in monotonic field_id order or the
41   // generator will CHECK() and crash.
42 
43   // Allows a simple field (varint, fixed32/64, string or bytes).
44   void AddSimpleField(uint32_t field_id);
45 
46   // Allows a range of simple fields. |range_start| is the id of the first field
47   // in range, |range_len| the number of fields in the range.
48   // AddSimpleFieldRange(N,1) is semantically equivalent to AddSimpleField(N)
49   // (but it takes 2 words to encode, rather than just one).
50   void AddSimpleFieldRange(uint32_t range_start, uint32_t range_len);
51 
52   // Adds a nested field. |message_index| is the index of the message that the
53   // parser must recurse into. This implies that at least |message_index| calls
54   // to Begin/EndMessage will be made.
55   // The Serialize() method will fail if any field points to an index that is
56   // out of range (e.g., if message_index = 5 but only 3 EndMessage() calls were
57   // made).
58   void AddNestedField(uint32_t field_id, uint32_t message_index);
59 
60   // Returns the filter bytecode, which is a buffer containing a sequence of
61   // varints and a checksum. The returned string can be passed to
62   // FilterBytecodeParser.Load().
63   std::string Serialize();
64 
65  private:
66   uint32_t num_messages_ = 0;
67   uint32_t last_field_id_ = 0;
68   uint32_t max_msg_index_ = 0;
69   bool endmessage_called_ = false;
70 
71   std::vector<uint32_t> bytecode_;
72 };
73 
74 }  // namespace protozero
75 
76 #endif  // SRC_PROTOZERO_FILTERING_FILTER_BYTECODE_GENERATOR_H_
77