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 <cstdint>
39#include <memory>
40#include <set>
41#include <string>
42
43#include <google/protobuf/compiler/cpp/field.h>
44#include <google/protobuf/compiler/cpp/helpers.h>
45#include <google/protobuf/compiler/cpp/message_layout_helper.h>
46#include <google/protobuf/compiler/cpp/options.h>
47#include <google/protobuf/compiler/cpp/parse_function_generator.h>
48
49namespace google {
50namespace protobuf {
51namespace io {
52class Printer; // printer.h
53}
54} // namespace protobuf
55} // namespace google
56
57namespace google {
58namespace protobuf {
59namespace compiler {
60namespace cpp {
61
62class EnumGenerator; // enum.h
63class ExtensionGenerator; // extension.h
64
65class MessageGenerator {
66 public:
67 // See generator.cc for the meaning of dllexport_decl.
68 MessageGenerator(const Descriptor* descriptor,
69 const std::map<std::string, std::string>& vars,
70 int index_in_file_messages, const Options& options,
71 MessageSCCAnalyzer* scc_analyzer);
72 ~MessageGenerator();
73
74 // Append the two types of nested generators to the corresponding vector.
75 void AddGenerators(
76 std::vector<std::unique_ptr<EnumGenerator>>* enum_generators,
77 std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators);
78
79 // Generate definitions for this class and all its nested types.
80 void GenerateClassDefinition(io::Printer* printer);
81
82 // Generate definitions of inline methods (placed at the end of the header
83 // file).
84 void GenerateInlineMethods(io::Printer* printer);
85
86 // Source file stuff.
87
88 // Generate all non-inline methods for this class.
89 void GenerateClassMethods(io::Printer* printer);
90
91 // Generate source file code that should go outside any namespace.
92 void GenerateSourceInProto2Namespace(io::Printer* printer);
93
94 private:
95 // Generate declarations and definitions of accessors for fields.
96 void GenerateFieldAccessorDeclarations(io::Printer* printer);
97 void GenerateFieldAccessorDefinitions(io::Printer* printer);
98
99 // Generate the field offsets array. Returns the a pair of the total number
100 // of entries generated and the index of the first has_bit entry.
101 std::pair<size_t, size_t> GenerateOffsets(io::Printer* printer);
102 void GenerateSchema(io::Printer* printer, int offset, int has_offset);
103
104 // Generate constructors and destructor.
105 void GenerateStructors(io::Printer* printer);
106
107 // The compiler typically generates multiple copies of each constructor and
108 // destructor: http://gcc.gnu.org/bugs.html#nonbugs_cxx
109 // Placing common code in a separate method reduces the generated code size.
110 //
111 // Generate the shared constructor code.
112 void GenerateSharedConstructorCode(io::Printer* printer);
113 // Generate the shared destructor code.
114 void GenerateSharedDestructorCode(io::Printer* printer);
115 // Generate the arena-specific destructor code.
116 void GenerateArenaDestructorCode(io::Printer* printer);
117
118 // Generate the constexpr constructor for constant initialization of the
119 // default instance.
120 void GenerateConstexprConstructor(io::Printer* printer);
121
122 void GenerateCreateSplitMessage(io::Printer* printer);
123 void GenerateInitDefaultSplitInstance(io::Printer* printer);
124
125 // Generate standard Message methods.
126 void GenerateClear(io::Printer* printer);
127 void GenerateOneofClear(io::Printer* printer);
128 void GenerateVerify(io::Printer* printer);
129 void GenerateSerializeWithCachedSizes(io::Printer* printer);
130 void GenerateSerializeWithCachedSizesToArray(io::Printer* printer);
131 void GenerateSerializeWithCachedSizesBody(io::Printer* printer);
132 void GenerateSerializeWithCachedSizesBodyShuffled(io::Printer* printer);
133 void GenerateByteSize(io::Printer* printer);
134 void GenerateMergeFrom(io::Printer* printer);
135 void GenerateClassSpecificMergeImpl(io::Printer* printer);
136 void GenerateCopyFrom(io::Printer* printer);
137 void GenerateSwap(io::Printer* printer);
138 void GenerateIsInitialized(io::Printer* printer);
139
140 // Helpers for GenerateSerializeWithCachedSizes().
141 //
142 // cached_has_bit_index maintains that:
143 // cached_has_bits = _has_bits_[cached_has_bit_index]
144 // for cached_has_bit_index >= 0
145 void GenerateSerializeOneField(io::Printer* printer,
146 const FieldDescriptor* field,
147 int cached_has_bits_index);
148 // Generate a switch statement to serialize 2+ fields from the same oneof.
149 // Or, if fields.size() == 1, just call GenerateSerializeOneField().
150 void GenerateSerializeOneofFields(
151 io::Printer* printer, const std::vector<const FieldDescriptor*>& fields);
152 void GenerateSerializeOneExtensionRange(
153 io::Printer* printer, const Descriptor::ExtensionRange* range);
154
155 // Generates has_foo() functions and variables for singular field has-bits.
156 void GenerateSingularFieldHasBits(const FieldDescriptor* field,
157 Formatter format);
158 // Generates has_foo() functions and variables for oneof field has-bits.
159 void GenerateOneofHasBits(io::Printer* printer);
160 // Generates has_foo_bar() functions for oneof members.
161 void GenerateOneofMemberHasBits(const FieldDescriptor* field,
162 const Formatter& format);
163 // Generates the clear_foo() method for a field.
164 void GenerateFieldClear(const FieldDescriptor* field, bool is_inline,
165 Formatter format);
166
167 // Generates the body of the message's copy constructor.
168 void GenerateCopyConstructorBody(io::Printer* printer) const;
169
170 // Returns the level that this message needs ArenaDtor. If the message has
171 // a field that is not arena-exclusive, it needs an ArenaDtor
172 // (go/proto-destructor).
173 //
174 // - Returning kNone means we don't need to generate ArenaDtor.
175 // - Returning kOnDemand means we need to generate ArenaDtor, but don't need
176 // to register ArenaDtor at construction. Such as when the message's
177 // ArenaDtor code is only for destructing inlined string.
178 // - Returning kRequired means we meed to generate ArenaDtor and register it
179 // at construction.
180 ArenaDtorNeeds NeedsArenaDestructor() const;
181
182 size_t HasBitsSize() const;
183 size_t InlinedStringDonatedSize() const;
184 int HasBitIndex(const FieldDescriptor* a) const;
185 int HasByteIndex(const FieldDescriptor* a) const;
186 int HasWordIndex(const FieldDescriptor* a) const;
187 bool SameHasByte(const FieldDescriptor* a, const FieldDescriptor* b) const;
188 std::vector<uint32_t> RequiredFieldsBitMask() const;
189
190 const Descriptor* descriptor_;
191 int index_in_file_messages_;
192 std::string classname_;
193 Options options_;
194 FieldGeneratorMap field_generators_;
195 // optimized_order_ is the order we layout the message's fields in the
196 // class. This is reused to initialize the fields in-order for cache
197 // efficiency.
198 //
199 // optimized_order_ excludes oneof fields and weak fields.
200 std::vector<const FieldDescriptor*> optimized_order_;
201 std::vector<int> has_bit_indices_;
202 int max_has_bit_index_;
203
204 // A map from field index to inlined_string index. For non-inlined-string
205 // fields, the element is -1. If there is no inlined string in the message,
206 // this is empty.
207 std::vector<int> inlined_string_indices_;
208 // The count of inlined_string fields in the message.
209 int max_inlined_string_index_;
210
211 std::vector<const EnumGenerator*> enum_generators_;
212 std::vector<const ExtensionGenerator*> extension_generators_;
213 int num_required_fields_;
214 int num_weak_fields_;
215
216 std::unique_ptr<MessageLayoutHelper> message_layout_helper_;
217 std::unique_ptr<ParseFunctionGenerator> parse_function_generator_;
218
219 MessageSCCAnalyzer* scc_analyzer_;
220
221 std::map<std::string, std::string> variables_;
222
223 friend class FileGenerator;
224 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
225};
226
227} // namespace cpp
228} // namespace compiler
229} // namespace protobuf
230} // namespace google
231
232#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
233