• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__
32 #define GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__
33 
34 #include <map>
35 #include <string>
36 #include <vector>
37 
38 #include <google/protobuf/io/printer.h>
39 #include <google/protobuf/descriptor.h>
40 #include <google/protobuf/wire_format_lite.h>
41 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
42 #include <google/protobuf/compiler/cpp/cpp_options.h>
43 
44 namespace google {
45 namespace protobuf {
46 namespace compiler {
47 namespace cpp {
48 
49 // Helper class for generating tailcall parsing functions.
50 struct TailCallTableInfo {
51   TailCallTableInfo(const Descriptor* descriptor, const Options& options,
52                     const std::vector<const FieldDescriptor*>& ordered_fields,
53                     const std::vector<int>& has_bit_indices,
54                     const std::vector<int>& inlined_string_indices,
55                     MessageSCCAnalyzer* scc_analyzer);
56 
57   // Fields parsed by the table fast-path.
58   struct FastFieldInfo {
59     std::string func_name;
60     const FieldDescriptor* field;
61     uint16_t coded_tag;
62     uint8_t hasbit_idx;
63     uint8_t aux_idx;
64   };
65   std::vector<FastFieldInfo> fast_path_fields;
66 
67   // Fields parsed by mini parsing routines.
68   struct FieldEntryInfo {
69     const FieldDescriptor* field;
70     int hasbit_idx;
71     int inlined_string_idx;
72     uint16_t aux_idx;
73     // True for enums entirely covered by the start/length fields of FieldAux:
74     bool is_enum_range;
75   };
76   std::vector<FieldEntryInfo> field_entries;
77   std::vector<std::string> aux_entries;
78 
79   // Fields parsed by generated fallback function.
80   std::vector<const FieldDescriptor*> fallback_fields;
81 
82   // Table size.
83   int table_size_log2;
84   // Mask for has-bits of required fields.
85   uint32_t has_hasbits_required_mask;
86   // True if a generated fallback function is required instead of generic.
87   bool use_generated_fallback;
88 };
89 
90 // ParseFunctionGenerator generates the _InternalParse function for a message
91 // (and any associated supporting members).
92 class ParseFunctionGenerator {
93  public:
94   ParseFunctionGenerator(const Descriptor* descriptor, int max_has_bit_index,
95                          const std::vector<int>& has_bit_indices,
96                          const std::vector<int>& inlined_string_indices,
97                          const Options& options,
98                          MessageSCCAnalyzer* scc_analyzer,
99                          const std::map<std::string, std::string>& vars);
100 
101   // Emits class-level method declarations to `printer`:
102   void GenerateMethodDecls(io::Printer* printer);
103 
104   // Emits out-of-class method implementation definitions to `printer`:
105   void GenerateMethodImpls(io::Printer* printer);
106 
107   // Emits class-level data member declarations to `printer`:
108   void GenerateDataDecls(io::Printer* printer);
109 
110   // Emits out-of-class data member definitions to `printer`:
111   void GenerateDataDefinitions(io::Printer* printer);
112 
113  private:
114   // Returns true if tailcall table code should be generated.
115   bool should_generate_tctable() const;
116 
117   // Returns true if tailcall table code should be generated, but inside an
118   // #ifdef guard.
should_generate_guarded_tctable()119   bool should_generate_guarded_tctable() const {
120     return should_generate_tctable() &&
121            options_.tctable_mode == Options::kTCTableGuarded;
122   }
123 
124   // Generates a tail-calling `_InternalParse` function.
125   void GenerateTailcallParseFunction(Formatter& format);
126 
127   // Generates a fallback function for tailcall table-based parsing.
128   void GenerateTailcallFallbackFunction(Formatter& format);
129 
130   // Generates a looping `_InternalParse` function.
131   void GenerateLoopingParseFunction(Formatter& format);
132 
133   // Generates the tail-call table definition.
134   void GenerateTailCallTable(Formatter& format);
135   void GenerateFastFieldEntries(Formatter& format);
136   void GenerateFieldEntries(Formatter& format);
137   int CalculateFieldNamesSize() const;
138   void GenerateFieldNames(Formatter& format);
139 
140   // Generates parsing code for an `ArenaString` field.
141   void GenerateArenaString(Formatter& format, const FieldDescriptor* field);
142 
143   // Generates parsing code for a string-typed field.
144   void GenerateStrings(Formatter& format, const FieldDescriptor* field,
145                        bool check_utf8);
146 
147   // Generates parsing code for a length-delimited field (strings, messages,
148   // etc.).
149   void GenerateLengthDelim(Formatter& format, const FieldDescriptor* field);
150 
151   // Generates the parsing code for a known field.
152   void GenerateFieldBody(Formatter& format,
153                          google::protobuf::internal::WireFormatLite::WireType wiretype,
154                          const FieldDescriptor* field);
155 
156   // Generates code to parse the next field from the input stream.
157   void GenerateParseIterationBody(
158       Formatter& format, const Descriptor* descriptor,
159       const std::vector<const FieldDescriptor*>& fields);
160 
161   // Generates a `switch` statement to parse each of `fields`.
162   void GenerateFieldSwitch(Formatter& format,
163                            const std::vector<const FieldDescriptor*>& fields);
164 
165   const Descriptor* descriptor_;
166   MessageSCCAnalyzer* scc_analyzer_;
167   const Options& options_;
168   std::map<std::string, std::string> variables_;
169   std::unique_ptr<TailCallTableInfo> tc_table_info_;
170   std::vector<int> inlined_string_indices_;
171   const std::vector<const FieldDescriptor*> ordered_fields_;
172   int num_hasbits_;
173 };
174 
175 }  // namespace cpp
176 }  // namespace compiler
177 }  // namespace protobuf
178 }  // namespace google
179 
180 #endif  // GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__
181