• 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 // Author: kenton@google.com (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
36 #define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
37 
38 #include <memory>
39 #include <set>
40 #include <string>
41 #include <google/protobuf/compiler/cpp/cpp_field.h>
42 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
43 #include <google/protobuf/compiler/cpp/cpp_message_layout_helper.h>
44 #include <google/protobuf/compiler/cpp/cpp_options.h>
45 
46 namespace google {
47 namespace protobuf {
48 namespace io {
49 class Printer;  // printer.h
50 }
51 }  // namespace protobuf
52 }  // namespace google
53 
54 namespace google {
55 namespace protobuf {
56 namespace compiler {
57 namespace cpp {
58 
59 class EnumGenerator;       // enum.h
60 class ExtensionGenerator;  // extension.h
61 
62 class MessageGenerator {
63  public:
64   // See generator.cc for the meaning of dllexport_decl.
65   MessageGenerator(const Descriptor* descriptor,
66                    const std::map<std::string, std::string>& vars,
67                    int index_in_file_messages, const Options& options,
68                    MessageSCCAnalyzer* scc_analyzer);
69   ~MessageGenerator();
70 
71   // Append the two types of nested generators to the corresponding vector.
72   void AddGenerators(
73       std::vector<std::unique_ptr<EnumGenerator>>* enum_generators,
74       std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators);
75 
76   // Generate definitions for this class and all its nested types.
77   void GenerateClassDefinition(io::Printer* printer);
78 
79   // Generate definitions of inline methods (placed at the end of the header
80   // file).
81   void GenerateInlineMethods(io::Printer* printer);
82 
83   // Source file stuff.
84 
85   // Generate all non-inline methods for this class.
86   void GenerateClassMethods(io::Printer* printer);
87 
88   // Generate source file code that should go outside any namespace.
89   void GenerateSourceInProto2Namespace(io::Printer* printer);
90 
91  private:
92   // Generate declarations and definitions of accessors for fields.
93   void GenerateFieldAccessorDeclarations(io::Printer* printer);
94   void GenerateFieldAccessorDefinitions(io::Printer* printer);
95 
96   // Generate the table-driven parsing array.  Returns the number of entries
97   // generated.
98   size_t GenerateParseOffsets(io::Printer* printer);
99   size_t GenerateParseAuxTable(io::Printer* printer);
100   // Generates a ParseTable entry.  Returns whether the proto uses
101   // table-driven parsing.
102   bool GenerateParseTable(io::Printer* printer, size_t offset,
103                           size_t aux_offset);
104 
105   // Generate the field offsets array.  Returns the a pair of the total number
106   // of entries generated and the index of the first has_bit entry.
107   std::pair<size_t, size_t> GenerateOffsets(io::Printer* printer);
108   void GenerateSchema(io::Printer* printer, int offset, int has_offset);
109   // For each field generates a table entry describing the field for the
110   // table driven serializer.
111   int GenerateFieldMetadata(io::Printer* printer);
112 
113   // Generate constructors and destructor.
114   void GenerateStructors(io::Printer* printer);
115 
116   // The compiler typically generates multiple copies of each constructor and
117   // destructor: http://gcc.gnu.org/bugs.html#nonbugs_cxx
118   // Placing common code in a separate method reduces the generated code size.
119   //
120   // Generate the shared constructor code.
121   void GenerateSharedConstructorCode(io::Printer* printer);
122   // Generate the shared destructor code.
123   void GenerateSharedDestructorCode(io::Printer* printer);
124   // Generate the arena-specific destructor code.
125   void GenerateArenaDestructorCode(io::Printer* printer);
126 
127   // Generate standard Message methods.
128   void GenerateClear(io::Printer* printer);
129   void GenerateOneofClear(io::Printer* printer);
130   void GenerateMergeFromCodedStream(io::Printer* printer);
131   void GenerateSerializeWithCachedSizes(io::Printer* printer);
132   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer);
133   void GenerateSerializeWithCachedSizesBody(io::Printer* printer);
134   void GenerateSerializeWithCachedSizesBodyShuffled(io::Printer* printer);
135   void GenerateByteSize(io::Printer* printer);
136   void GenerateMergeFrom(io::Printer* printer);
137   void GenerateClassSpecificMergeFrom(io::Printer* printer);
138   void GenerateCopyFrom(io::Printer* printer);
139   void GenerateSwap(io::Printer* printer);
140   void GenerateIsInitialized(io::Printer* printer);
141 
142   // Helpers for GenerateSerializeWithCachedSizes().
143   //
144   // cached_has_bit_index maintains that:
145   //   cached_has_bits = _has_bits_[cached_has_bit_index]
146   // for cached_has_bit_index >= 0
147   void GenerateSerializeOneField(io::Printer* printer,
148                                  const FieldDescriptor* field,
149                                  int cached_has_bits_index);
150   // Generate a switch statement to serialize 2+ fields from the same oneof.
151   // Or, if fields.size() == 1, just call GenerateSerializeOneField().
152   void GenerateSerializeOneofFields(
153       io::Printer* printer, const std::vector<const FieldDescriptor*>& fields);
154   void GenerateSerializeOneExtensionRange(
155       io::Printer* printer, const Descriptor::ExtensionRange* range);
156 
157   // Generates has_foo() functions and variables for singular field has-bits.
158   void GenerateSingularFieldHasBits(const FieldDescriptor* field,
159                                     Formatter format);
160   // Generates has_foo() functions and variables for oneof field has-bits.
161   void GenerateOneofHasBits(io::Printer* printer);
162   // Generates has_foo_bar() functions for oneof members.
163   void GenerateOneofMemberHasBits(const FieldDescriptor* field,
164                                   const Formatter& format);
165   // Generates the clear_foo() method for a field.
166   void GenerateFieldClear(const FieldDescriptor* field, bool is_inline,
167                           Formatter format);
168 
169   void GenerateConstructorBody(io::Printer* printer,
170                                std::vector<bool> already_processed,
171                                bool copy_constructor) const;
172 
173   size_t HasBitsSize() const;
174   int HasBitIndex(const FieldDescriptor* a) const;
175   int HasByteIndex(const FieldDescriptor* a) const;
176   int HasWordIndex(const FieldDescriptor* a) const;
177   bool SameHasByte(const FieldDescriptor* a, const FieldDescriptor* b) const;
178   std::vector<uint32> RequiredFieldsBitMask() const;
179 
180   const Descriptor* descriptor_;
181   int index_in_file_messages_;
182   std::string classname_;
183   Options options_;
184   FieldGeneratorMap field_generators_;
185   // optimized_order_ is the order we layout the message's fields in the
186   // class. This is reused to initialize the fields in-order for cache
187   // efficiency.
188   //
189   // optimized_order_ excludes oneof fields and weak fields.
190   std::vector<const FieldDescriptor*> optimized_order_;
191   std::vector<int> has_bit_indices_;
192   int max_has_bit_index_;
193   std::vector<const EnumGenerator*> enum_generators_;
194   std::vector<const ExtensionGenerator*> extension_generators_;
195   int num_required_fields_;
196   int num_weak_fields_;
197   // table_driven_ indicates the generated message uses table-driven parsing.
198   bool table_driven_;
199 
200   std::unique_ptr<MessageLayoutHelper> message_layout_helper_;
201 
202   MessageSCCAnalyzer* scc_analyzer_;
203 
204   std::map<std::string, std::string> variables_;
205 
206   friend class FileGenerator;
207   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
208 };
209 
210 }  // namespace cpp
211 }  // namespace compiler
212 }  // namespace protobuf
213 }  // namespace google
214 
215 #endif  // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
216