blob: ddeb8c38639d676615f0dcb9e59d3f24c7112bb9 [file] [log] [blame]
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
#include <cstddef>
#include <cstdint>
#include <limits>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/compiler/cpp/enum.h"
#include "google/protobuf/compiler/cpp/extension.h"
#include "google/protobuf/compiler/cpp/field.h"
#include "google/protobuf/compiler/cpp/helpers.h"
#include "google/protobuf/compiler/cpp/message_layout_helper.h"
#include "google/protobuf/compiler/cpp/options.h"
#include "google/protobuf/compiler/cpp/parse_function_generator.h"
#include "google/protobuf/io/printer.h"
namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {
class MessageGenerator {
public:
MessageGenerator(
const Descriptor* descriptor,
const absl::flat_hash_map<absl::string_view, std::string>& ignored,
int index_in_file_messages, const Options& options,
MessageSCCAnalyzer* scc_analyzer);
MessageGenerator(const MessageGenerator&) = delete;
MessageGenerator& operator=(const MessageGenerator&) = delete;
~MessageGenerator() = default;
int index_in_file_messages() const { return index_in_file_messages_; }
// Append the two types of nested generators to the corresponding vector.
void AddGenerators(
std::vector<std::unique_ptr<EnumGenerator>>* enum_generators,
std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators);
// Generate definitions for this class and all its nested types.
void GenerateClassDefinition(io::Printer* p);
// Generate definitions of inline methods (placed at the end of the header
// file).
void GenerateInlineMethods(io::Printer* p);
// Generate all non-inline methods for this class.
void GenerateClassMethods(io::Printer* p);
// Generate source file code that should go outside any namespace.
void GenerateSourceInProto2Namespace(io::Printer* p);
void GenerateInitDefaultSplitInstance(io::Printer* p);
// Generate the constexpr constructor for constant initialization of the
// default instance.
void GenerateConstexprConstructor(io::Printer* p);
void GenerateSchema(io::Printer* p, int offset, int has_offset);
// Generate the field offsets array. Returns the a pair of the total number
// of entries generated and the index of the first has_bit entry.
std::pair<size_t, size_t> GenerateOffsets(io::Printer* p);
const Descriptor* descriptor() const { return descriptor_; }
private:
using GeneratorFunction = FieldGeneratorBase::GeneratorFunction;
enum class InitType { kConstexpr, kArena, kArenaCopy };
// Generate declarations and definitions of accessors for fields.
void GenerateFieldAccessorDeclarations(io::Printer* p);
void GenerateFieldAccessorDefinitions(io::Printer* p);
// Generate constructors and destructor.
void GenerateStructors(io::Printer* p);
void GenerateZeroInitFields(io::Printer* p) const;
void GenerateCopyInitFields(io::Printer* p) const;
void GenerateImplMemberInit(io::Printer* p, InitType init_type);
void GenerateArenaEnabledCopyConstructor(io::Printer* p);
// The compiler typically generates multiple copies of each constructor and
// destructor: http://gcc.gnu.org/bugs.html#nonbugs_cxx
// Placing common code in a separate method reduces the generated code size.
//
// Generate the shared constructor code.
void GenerateSharedConstructorCode(io::Printer* p);
// Generate the shared destructor code.
void GenerateSharedDestructorCode(io::Printer* p);
// Generate the arena-specific destructor code.
void GenerateArenaDestructorCode(io::Printer* p);
// Generate standard Message methods.
void GenerateClear(io::Printer* p);
void GenerateOneofClear(io::Printer* p);
void GenerateVerify(io::Printer* p);
void GenerateSerializeWithCachedSizes(io::Printer* p);
void GenerateSerializeWithCachedSizesToArray(io::Printer* p);
void GenerateSerializeWithCachedSizesBody(io::Printer* p);
void GenerateSerializeWithCachedSizesBodyShuffled(io::Printer* p);
void GenerateByteSize(io::Printer* p);
void GenerateClassData(io::Printer* p);
void GenerateMapEntryClassDefinition(io::Printer* p);
void GenerateAnyMethodDefinition(io::Printer* p);
void GenerateImplDefinition(io::Printer* p);
void GenerateClassSpecificMergeImpl(io::Printer* p);
void GenerateCopyFrom(io::Printer* p);
void GenerateSwap(io::Printer* p);
void GenerateIsInitialized(io::Printer* p);
bool NeedsIsInitialized();
// Helpers for GenerateSerializeWithCachedSizes().
//
// cached_has_bit_index maintains that:
// cached_has_bits = _has_bits_[cached_has_bit_index]
// for cached_has_bit_index >= 0
void GenerateSerializeOneField(io::Printer* p, const FieldDescriptor* field,
int cached_has_bits_index);
// Generate a switch statement to serialize 2+ fields from the same oneof.
// Or, if fields.size() == 1, just call GenerateSerializeOneField().
void GenerateSerializeOneofFields(
io::Printer* p, const std::vector<const FieldDescriptor*>& fields);
void GenerateSerializeOneExtensionRange(io::Printer* p, int start, int end);
// Generates has_foo() functions and variables for singular field has-bits.
void GenerateSingularFieldHasBits(const FieldDescriptor* field,
io::Printer* p);
// Generates has_foo() functions and variables for oneof field has-bits.
void GenerateOneofHasBits(io::Printer* p);
// Generates has_foo_bar() functions for oneof members.
void GenerateOneofMemberHasBits(const FieldDescriptor* field, io::Printer* p);
// Generates the clear_foo() method for a field.
void GenerateFieldClear(const FieldDescriptor* field, bool is_inline,
io::Printer* p);
// Returns true if any of the fields needs an `arena` variable containing
// the current message's arena, reducing `GetArena()` call churn.
bool RequiresArena(GeneratorFunction function) const;
// Returns whether impl_ has a copy ctor.
bool ImplHasCopyCtor() const;
// Returns the level that this message needs ArenaDtor. If the message has
// a field that is not arena-exclusive, it needs an ArenaDtor
// (go/proto-destructor).
//
// - Returning kNone means we don't need to generate ArenaDtor.
// - Returning kOnDemand means we need to generate ArenaDtor, but don't need
// to register ArenaDtor at construction. Such as when the message's
// ArenaDtor code is only for destructing inlined string.
// - Returning kRequired means we meed to generate ArenaDtor and register it
// at construction.
ArenaDtorNeeds NeedsArenaDestructor() const;
size_t HasBitsSize() const;
size_t InlinedStringDonatedSize() const;
absl::flat_hash_map<absl::string_view, std::string> HasBitVars(
const FieldDescriptor* field) const;
int HasBitIndex(const FieldDescriptor* field) const;
int HasByteIndex(const FieldDescriptor* field) const;
int HasWordIndex(const FieldDescriptor* field) const;
std::vector<uint32_t> RequiredFieldsBitMask() const;
const Descriptor* descriptor_;
int index_in_file_messages_;
Options options_;
FieldGeneratorTable field_generators_;
// optimized_order_ is the order we layout the message's fields in the
// class. This is reused to initialize the fields in-order for cache
// efficiency.
//
// optimized_order_ excludes oneof fields and weak fields.
std::vector<const FieldDescriptor*> optimized_order_;
std::vector<int> has_bit_indices_;
int max_has_bit_index_ = 0;
// A map from field index to inlined_string index. For non-inlined-string
// fields, the element is -1. If there is no inlined string in the message,
// this is empty.
std::vector<int> inlined_string_indices_;
// The count of inlined_string fields in the message.
int max_inlined_string_index_ = 0;
std::vector<const EnumGenerator*> enum_generators_;
std::vector<const ExtensionGenerator*> extension_generators_;
int num_required_fields_ = 0;
int num_weak_fields_ = 0;
std::unique_ptr<MessageLayoutHelper> message_layout_helper_;
std::unique_ptr<ParseFunctionGenerator> parse_function_generator_;
MessageSCCAnalyzer* scc_analyzer_;
absl::flat_hash_map<absl::string_view, std::string> variables_;
};
} // namespace cpp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__