Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
0eb74768d0
@ -81,22 +81,18 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
|
||||
return unknownFields.mergeFieldFrom(tag, input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by parsing constructors in generated classes.
|
||||
*/
|
||||
protected void makeExtensionsImmutable() {
|
||||
// Noop for messages without extensions.
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public abstract static class Builder<MessageType extends GeneratedMessageLite,
|
||||
BuilderType extends Builder>
|
||||
extends AbstractMessageLite.Builder<BuilderType> {
|
||||
|
||||
private final MessageType defaultInstance;
|
||||
private UnknownFieldSetLite unknownFields =
|
||||
UnknownFieldSetLite.getDefaultInstance();
|
||||
|
||||
protected Builder() {}
|
||||
protected Builder(MessageType defaultInstance) {
|
||||
this.defaultInstance = defaultInstance;
|
||||
}
|
||||
|
||||
//@Override (Java 1.6 override semantics, but we must support 1.5)
|
||||
public BuilderType clear() {
|
||||
@ -111,15 +107,25 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
|
||||
builder.mergeFrom(buildPartial());
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
/** All subclasses implement this. */
|
||||
public abstract MessageType buildPartial();
|
||||
|
||||
//@Override (Java 1.6 override semantics, but we must support 1.5)
|
||||
public final MessageType build() {
|
||||
MessageType result = buildPartial();
|
||||
if (!result.isInitialized()) {
|
||||
throw newUninitializedMessageException(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** All subclasses implement this. */
|
||||
public abstract BuilderType mergeFrom(MessageType message);
|
||||
|
||||
// Defined here for return type covariance.
|
||||
public abstract MessageType getDefaultInstanceForType();
|
||||
|
||||
public MessageType getDefaultInstanceForType() {
|
||||
return defaultInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by subclasses to parse an unknown field.
|
||||
@ -288,8 +294,8 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
|
||||
/**
|
||||
* Used by parsing constructors in generated classes.
|
||||
*/
|
||||
@Override
|
||||
protected void makeExtensionsImmutable() {
|
||||
protected static void makeExtensionsImmutable(
|
||||
FieldSet<ExtensionDescriptor> extensions) {
|
||||
extensions.makeImmutable();
|
||||
}
|
||||
|
||||
@ -361,7 +367,9 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
|
||||
BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
|
||||
extends Builder<MessageType, BuilderType>
|
||||
implements ExtendableMessageOrBuilder<MessageType> {
|
||||
protected ExtendableBuilder() {}
|
||||
protected ExtendableBuilder(MessageType defaultInstance) {
|
||||
super(defaultInstance);
|
||||
}
|
||||
|
||||
private FieldSet<ExtensionDescriptor> extensions = FieldSet.emptySet();
|
||||
private boolean extensionsIsMutable;
|
||||
|
@ -282,7 +282,7 @@ public final class MapEntry<K, V> extends AbstractMessage {
|
||||
@Override
|
||||
public MapEntry<K, V> buildPartial() {
|
||||
if (dataBuilder != null) {
|
||||
data = dataBuilder.build();
|
||||
data = dataBuilder.buildPartial();
|
||||
dataBuilder = null;
|
||||
}
|
||||
return new MapEntry<K, V>(metadata, data);
|
||||
|
@ -91,7 +91,7 @@ public class MapField<K, V> {
|
||||
}
|
||||
|
||||
public Message convertKeyAndValueToMessage(K key, V value) {
|
||||
return defaultEntry.newBuilderForType().setKey(key).setValue(value).build();
|
||||
return defaultEntry.newBuilderForType().setKey(key).setValue(value).buildPartial();
|
||||
}
|
||||
|
||||
public void convertMessageToKeyAndValue(Message message, Map<K, V> map) {
|
||||
|
@ -33,6 +33,7 @@ package com.google.protobuf;
|
||||
import com.google.protobuf.Descriptors.FieldDescriptor;
|
||||
import map_test.MapForProto2TestProto.TestMap;
|
||||
import map_test.MapForProto2TestProto.TestMap.MessageValue;
|
||||
import map_test.MapForProto2TestProto.TestMap.MessageWithRequiredFields;
|
||||
import map_test.MapForProto2TestProto.TestUnknownEnumValue;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
@ -485,4 +486,17 @@ public class MapForProto2Test extends TestCase {
|
||||
assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
|
||||
}
|
||||
|
||||
|
||||
public void testRequiredMessage() throws Exception {
|
||||
TestMap.Builder builder = TestMap.newBuilder();
|
||||
builder.getMutableRequiredMessageMap().put(0,
|
||||
MessageWithRequiredFields.newBuilder().buildPartial());
|
||||
TestMap message = builder.buildPartial();
|
||||
assertFalse(message.isInitialized());
|
||||
|
||||
builder.getMutableRequiredMessageMap().put(0,
|
||||
MessageWithRequiredFields.newBuilder().setValue(1).build());
|
||||
message = builder.build();
|
||||
assertTrue(message.isInitialized());
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,11 @@ message TestMap {
|
||||
map<int32, EnumValue> int32_to_enum_field = 4;
|
||||
map<int32, MessageValue> int32_to_message_field = 5;
|
||||
map<string, int32> string_to_int32_field = 6;
|
||||
|
||||
message MessageWithRequiredFields {
|
||||
required int32 value = 1;
|
||||
}
|
||||
map<int32, MessageWithRequiredFields> required_message_map = 11;
|
||||
}
|
||||
|
||||
message TestUnknownEnumValue {
|
||||
|
@ -53,6 +53,11 @@ message TestMap {
|
||||
map<int32, EnumValue> int32_to_enum_field = 4;
|
||||
map<int32, MessageValue> int32_to_message_field = 5;
|
||||
map<string, int32> string_to_int32_field = 6;
|
||||
|
||||
message MessageWithRequiredFields {
|
||||
required int32 value = 1;
|
||||
}
|
||||
map<int32, MessageWithRequiredFields> required_message_map = 11;
|
||||
}
|
||||
|
||||
message TestUnknownEnumValue {
|
||||
|
@ -281,8 +281,6 @@ class GeneratorTest(basetest.TestCase):
|
||||
"baz")
|
||||
self.assertEqual(message.Extensions[test_bad_identifiers_pb2.service],
|
||||
"qux")
|
||||
self.assertEqual(message.Extensions[test_bad_identifiers_pb2.class_],
|
||||
"Foo")
|
||||
|
||||
def testOneof(self):
|
||||
desc = unittest_pb2.TestAllTypes.DESCRIPTOR
|
||||
|
@ -40,15 +40,13 @@ message TestBadIdentifiers {
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
// Make sure these reasonable extension names don't conflict with internal
|
||||
// variables.
|
||||
extend TestBadIdentifiers {
|
||||
// Make sure these reasonable extension names don't conflict with internal
|
||||
// variables.
|
||||
optional string message = 100 [default="foo"];
|
||||
optional string descriptor = 101 [default="bar"];
|
||||
optional string reflection = 102 [default="baz"];
|
||||
optional string service = 103 [default="qux"];
|
||||
// And Python keywords.
|
||||
optional string class = 104 [default="Foo"];
|
||||
}
|
||||
|
||||
message AnotherMessage {}
|
||||
|
@ -217,24 +217,6 @@ def PrintFieldValue(field, value, out, indent=0, as_utf8=False,
|
||||
out.write(str(value))
|
||||
|
||||
|
||||
def _ParseOrMerge(lines, message, allow_multiple_scalars):
|
||||
"""Converts an ASCII representation of a protocol message into a message.
|
||||
|
||||
Args:
|
||||
lines: Lines of a message's ASCII representation.
|
||||
message: A protocol buffer message to merge into.
|
||||
allow_multiple_scalars: Determines if repeated values for a non-repeated
|
||||
field are permitted, e.g., the string "foo: 1 foo: 2" for a
|
||||
required/optional field named "foo".
|
||||
|
||||
Raises:
|
||||
ParseError: On ASCII parsing problems.
|
||||
"""
|
||||
tokenizer = _Tokenizer(lines)
|
||||
while not tokenizer.AtEnd():
|
||||
_MergeField(tokenizer, message, allow_multiple_scalars)
|
||||
|
||||
|
||||
def Parse(text, message):
|
||||
"""Parses an ASCII representation of a protocol message into a message.
|
||||
|
||||
@ -305,6 +287,24 @@ def MergeLines(lines, message):
|
||||
return message
|
||||
|
||||
|
||||
def _ParseOrMerge(lines, message, allow_multiple_scalars):
|
||||
"""Converts an ASCII representation of a protocol message into a message.
|
||||
|
||||
Args:
|
||||
lines: Lines of a message's ASCII representation.
|
||||
message: A protocol buffer message to merge into.
|
||||
allow_multiple_scalars: Determines if repeated values for a non-repeated
|
||||
field are permitted, e.g., the string "foo: 1 foo: 2" for a
|
||||
required/optional field named "foo".
|
||||
|
||||
Raises:
|
||||
ParseError: On ASCII parsing problems.
|
||||
"""
|
||||
tokenizer = _Tokenizer(lines)
|
||||
while not tokenizer.AtEnd():
|
||||
_MergeField(tokenizer, message, allow_multiple_scalars)
|
||||
|
||||
|
||||
def _MergeField(tokenizer, message, allow_multiple_scalars):
|
||||
"""Merges a single protocol message field into a message.
|
||||
|
||||
|
@ -40,6 +40,7 @@ MAINTAINERCLEANFILES = \
|
||||
nobase_include_HEADERS = \
|
||||
google/protobuf/stubs/atomic_sequence_num.h \
|
||||
google/protobuf/stubs/atomicops.h \
|
||||
google/protobuf/stubs/atomicops_internals_aix.h \
|
||||
google/protobuf/stubs/atomicops_internals_arm64_gcc.h \
|
||||
google/protobuf/stubs/atomicops_internals_arm_gcc.h \
|
||||
google/protobuf/stubs/atomicops_internals_arm_qnx.h \
|
||||
@ -71,6 +72,11 @@ nobase_include_HEADERS = \
|
||||
google/protobuf/generated_enum_reflection.h \
|
||||
google/protobuf/generated_message_reflection.h \
|
||||
google/protobuf/generated_message_util.h \
|
||||
google/protobuf/map_entry.h \
|
||||
google/protobuf/map_field.h \
|
||||
google/protobuf/map_field_inl.h \
|
||||
google/protobuf/map.h \
|
||||
google/protobuf/map_type_handler.h \
|
||||
google/protobuf/message.h \
|
||||
google/protobuf/message_lite.h \
|
||||
google/protobuf/metadata.h \
|
||||
@ -120,6 +126,7 @@ libprotobuf_lite_la_SOURCES = \
|
||||
google/protobuf/arenastring.cc \
|
||||
google/protobuf/extension_set.cc \
|
||||
google/protobuf/generated_message_util.cc \
|
||||
google/protobuf/map_field.cc \
|
||||
google/protobuf/message_lite.cc \
|
||||
google/protobuf/repeated_field.cc \
|
||||
google/protobuf/wire_format_lite.cc \
|
||||
@ -182,6 +189,8 @@ libprotoc_la_SOURCES = \
|
||||
google/protobuf/compiler/cpp/cpp_generator.cc \
|
||||
google/protobuf/compiler/cpp/cpp_helpers.cc \
|
||||
google/protobuf/compiler/cpp/cpp_helpers.h \
|
||||
google/protobuf/compiler/cpp/cpp_map_field.cc \
|
||||
google/protobuf/compiler/cpp/cpp_map_field.h \
|
||||
google/protobuf/compiler/cpp/cpp_message.cc \
|
||||
google/protobuf/compiler/cpp/cpp_message.h \
|
||||
google/protobuf/compiler/cpp/cpp_message_field.cc \
|
||||
@ -239,6 +248,9 @@ protoc_SOURCES = google/protobuf/compiler/main.cc
|
||||
# Tests ==============================================================
|
||||
|
||||
protoc_inputs = \
|
||||
google/protobuf/map_lite_unittest.proto \
|
||||
google/protobuf/map_proto2_unittest.proto \
|
||||
google/protobuf/map_unittest.proto \
|
||||
google/protobuf/unittest.proto \
|
||||
google/protobuf/unittest_arena.proto \
|
||||
google/protobuf/unittest_custom_options.proto \
|
||||
@ -292,6 +304,12 @@ protoc_lite_outputs = \
|
||||
|
||||
protoc_outputs = \
|
||||
$(protoc_lite_outputs) \
|
||||
google/protobuf/map_lite_unittest.pb.cc \
|
||||
google/protobuf/map_lite_unittest.pb.h \
|
||||
google/protobuf/map_proto2_unittest.pb.cc \
|
||||
google/protobuf/map_proto2_unittest.pb.h \
|
||||
google/protobuf/map_unittest.pb.cc \
|
||||
google/protobuf/map_unittest.pb.h \
|
||||
google/protobuf/unittest.pb.cc \
|
||||
google/protobuf/unittest.pb.h \
|
||||
google/protobuf/unittest_arena.pb.cc \
|
||||
@ -351,6 +369,8 @@ endif
|
||||
$(protoc_outputs): unittest_proto_middleman
|
||||
|
||||
COMMON_TEST_SOURCES = \
|
||||
google/protobuf/map_test_util.cc \
|
||||
google/protobuf/map_test_util.h \
|
||||
google/protobuf/test_util.cc \
|
||||
google/protobuf/test_util.h \
|
||||
google/protobuf/testing/googletest.cc \
|
||||
@ -385,6 +405,8 @@ protobuf_test_SOURCES = \
|
||||
google/protobuf/dynamic_message_unittest.cc \
|
||||
google/protobuf/extension_set_unittest.cc \
|
||||
google/protobuf/generated_message_reflection_unittest.cc \
|
||||
google/protobuf/map_field_test.cc \
|
||||
google/protobuf/map_test.cc \
|
||||
google/protobuf/message_unittest.cc \
|
||||
google/protobuf/no_field_presence_test.cc \
|
||||
google/protobuf/preserve_unknown_enum_test.cc \
|
||||
|
@ -138,7 +138,7 @@ void* Arena::AllocateAligned(size_t n) {
|
||||
// for this thread.
|
||||
if (!owns_first_block_ && b->next == NULL) {
|
||||
MutexLock l(&blocks_lock_);
|
||||
if (b->owner == &b->owner) {
|
||||
if (b->owner == &b->owner && b->avail() >= n) {
|
||||
b->owner = me;
|
||||
SetThreadCacheBlock(b);
|
||||
return AllocFromBlock(b, n);
|
||||
|
@ -30,14 +30,26 @@
|
||||
|
||||
#include <google/protobuf/arena.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#ifndef _SHARED_PTR_H
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#endif
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/test_util.h>
|
||||
#include <google/protobuf/unittest.pb.h>
|
||||
#include <google/protobuf/unittest_arena.pb.h>
|
||||
#include <google/protobuf/unittest_no_arena.pb.h>
|
||||
#include <google/protobuf/unittest.pb.h>
|
||||
#include <google/protobuf/testing/googletest.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
|
||||
@ -110,6 +122,31 @@ TEST(ArenaTest, BasicCreate) {
|
||||
EXPECT_EQ(2, notifier.GetCount());
|
||||
}
|
||||
|
||||
TEST(ArenaTest, InitialBlockTooSmall) {
|
||||
// Construct a small (64 byte) initial block of memory to be used by the
|
||||
// arena allocator; then, allocate an object which will not fit in the
|
||||
// initial block.
|
||||
std::vector<char> arena_block(64);
|
||||
ArenaOptions options;
|
||||
options.initial_block = arena_block.data();
|
||||
options.initial_block_size = arena_block.size();
|
||||
Arena arena(options);
|
||||
|
||||
char* p = ::google::protobuf::Arena::CreateArray<char>(&arena, 96);
|
||||
uintptr_t allocation = reinterpret_cast<uintptr_t>(p);
|
||||
|
||||
// Ensure that the arena allocator did not return memory pointing into the
|
||||
// initial block of memory.
|
||||
uintptr_t arena_start = reinterpret_cast<uintptr_t>(arena_block.data());
|
||||
uintptr_t arena_end = arena_start + arena_block.size();
|
||||
EXPECT_FALSE(allocation >= arena_start && allocation < arena_end);
|
||||
|
||||
// Write to the memory we allocated; this should (but is not guaranteed to)
|
||||
// trigger a check for heap corruption if the object was allocated from the
|
||||
// initially-provided block.
|
||||
memset(p, '\0', 128);
|
||||
}
|
||||
|
||||
TEST(ArenaTest, Parsing) {
|
||||
TestAllTypes original;
|
||||
TestUtil::SetAllFields(&original);
|
||||
|
@ -38,6 +38,16 @@ namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
|
||||
void ArenaStringPtr::AssignWithDefault(const ::std::string* default_value,
|
||||
ArenaStringPtr value) {
|
||||
const ::std::string* me = *UnsafeRawStringPointer();
|
||||
const ::std::string* other = *value.UnsafeRawStringPointer();
|
||||
// If the pointers are the same then do nothing.
|
||||
if (me != other) {
|
||||
SetNoArena(default_value, value.GetNoArena(default_value));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
@ -214,6 +214,8 @@ struct ArenaStringPtr {
|
||||
}
|
||||
}
|
||||
|
||||
void AssignWithDefault(const ::std::string* default_value, ArenaStringPtr value);
|
||||
|
||||
inline const ::std::string& GetNoArena(const ::std::string* default_value) const {
|
||||
return *ptr_;
|
||||
}
|
||||
|
@ -300,7 +300,7 @@ class CommandLineInterface::MemoryOutputStream
|
||||
bool append_mode_;
|
||||
|
||||
// StringOutputStream writing to data_.
|
||||
scoped_ptr<io::StringOutputStream> inner_;
|
||||
google::protobuf::scoped_ptr<io::StringOutputStream> inner_;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
@ -1321,7 +1321,7 @@ bool CommandLineInterface::GeneratePluginOutput(
|
||||
|
||||
// Write the files. We do this even if there was a generator error in order
|
||||
// to match the behavior of a compiled-in generator.
|
||||
scoped_ptr<io::ZeroCopyOutputStream> current_output;
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> current_output;
|
||||
for (int i = 0; i < response.file_size(); i++) {
|
||||
const CodeGeneratorResponse::File& output_file = response.file(i);
|
||||
|
||||
@ -1370,7 +1370,7 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
|
||||
}
|
||||
|
||||
DynamicMessageFactory dynamic_factory(pool);
|
||||
scoped_ptr<Message> message(dynamic_factory.GetPrototype(type)->New());
|
||||
google::protobuf::scoped_ptr<Message> message(dynamic_factory.GetPrototype(type)->New());
|
||||
|
||||
if (mode_ == MODE_ENCODE) {
|
||||
SetFdToTextMode(STDIN_FILENO);
|
||||
|
@ -261,7 +261,7 @@ void CommandLineInterfaceTest::SetUp() {
|
||||
|
||||
void CommandLineInterfaceTest::TearDown() {
|
||||
// Delete the temp directory.
|
||||
if (File::Exists(temp_directory_)) {
|
||||
if (FileExists(temp_directory_)) {
|
||||
File::DeleteRecursively(temp_directory_, NULL, NULL);
|
||||
}
|
||||
|
||||
@ -312,7 +312,7 @@ void CommandLineInterfaceTest::Run(const string& command) {
|
||||
}
|
||||
}
|
||||
|
||||
scoped_array<const char*> argv(new const char* [args.size()]);
|
||||
google::protobuf::scoped_array<const char * > argv(new const char* [args.size()]);
|
||||
|
||||
for (int i = 0; i < args.size(); i++) {
|
||||
args[i] = StringReplace(args[i], "$tmpdir", temp_directory_, true);
|
||||
@ -1550,7 +1550,7 @@ class EncodeDecodeTest : public testing::Test {
|
||||
SplitStringUsing(command, " ", &args);
|
||||
args.push_back("--proto_path=" + TestSourceDir());
|
||||
|
||||
scoped_array<const char*> argv(new const char* [args.size()]);
|
||||
google::protobuf::scoped_array<const char * > argv(new const char* [args.size()]);
|
||||
for (int i = 0; i < args.size(); i++) {
|
||||
argv[i] = args[i].c_str();
|
||||
}
|
||||
|
@ -106,8 +106,8 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
|
||||
// INT32_MIN and INT32_MAX
|
||||
if (descriptor_->value_count() > 0) printer->Print(",\n");
|
||||
printer->Print(vars,
|
||||
"$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = INT32_MIN,\n"
|
||||
"$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = INT32_MAX");
|
||||
"$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,\n"
|
||||
"$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max");
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_string_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_map_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_message_field.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
@ -65,6 +66,12 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||
(*variables)["classname"] = ClassName(FieldScope(descriptor), false);
|
||||
(*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
|
||||
|
||||
// non_null_ptr_to_name is usable only if has_$name$ is true. It yields a
|
||||
// pointer that will not be NULL. Subclasses of FieldGenerator may set
|
||||
// (*variables)["non_null_ptr_to_name"] differently.
|
||||
(*variables)["non_null_ptr_to_name"] =
|
||||
StrCat("&this->", FieldName(descriptor), "()");
|
||||
|
||||
(*variables)["tag_size"] = SimpleItoa(
|
||||
WireFormat::TagSize(descriptor->number(), descriptor->type()));
|
||||
(*variables)["deprecation"] = descriptor->options().deprecated()
|
||||
@ -89,8 +96,11 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||
|
||||
void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables) {
|
||||
(*variables)["oneof_prefix"] = descriptor->containing_oneof()->name() + "_.";
|
||||
const string prefix = descriptor->containing_oneof()->name() + "_.";
|
||||
(*variables)["oneof_prefix"] = prefix;
|
||||
(*variables)["oneof_name"] = descriptor->containing_oneof()->name();
|
||||
(*variables)["non_null_ptr_to_name"] =
|
||||
StrCat(prefix, (*variables)["name"], "_");
|
||||
}
|
||||
|
||||
FieldGenerator::~FieldGenerator() {}
|
||||
@ -111,7 +121,7 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor),
|
||||
field_generators_(
|
||||
new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
|
||||
new google::protobuf::scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
|
||||
// Construct all the FieldGenerators.
|
||||
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||
field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
|
||||
@ -123,7 +133,11 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
|
||||
if (field->is_repeated()) {
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return new RepeatedMessageFieldGenerator(field, options);
|
||||
if (field->is_map()) {
|
||||
return new MapFieldGenerator(field, options);
|
||||
} else {
|
||||
return new RepeatedMessageFieldGenerator(field, options);
|
||||
}
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
switch (field->options().ctype()) {
|
||||
default: // RepeatedStringFieldGenerator handles unknown ctypes.
|
||||
|
@ -182,7 +182,7 @@ class FieldGeneratorMap {
|
||||
|
||||
private:
|
||||
const Descriptor* descriptor_;
|
||||
scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<FieldGenerator> > field_generators_;
|
||||
|
||||
static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
|
||||
const Options& options);
|
||||
|
@ -59,13 +59,13 @@ namespace cpp {
|
||||
FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
|
||||
: file_(file),
|
||||
message_generators_(
|
||||
new scoped_ptr<MessageGenerator>[file->message_type_count()]),
|
||||
new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
|
||||
enum_generators_(
|
||||
new scoped_ptr<EnumGenerator>[file->enum_type_count()]),
|
||||
new google::protobuf::scoped_ptr<EnumGenerator>[file->enum_type_count()]),
|
||||
service_generators_(
|
||||
new scoped_ptr<ServiceGenerator>[file->service_count()]),
|
||||
new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]),
|
||||
extension_generators_(
|
||||
new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
|
||||
new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]),
|
||||
options_(options) {
|
||||
|
||||
for (int i = 0; i < file->message_type_count(); i++) {
|
||||
@ -105,7 +105,6 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
||||
"#define PROTOBUF_$filename_identifier$__INCLUDED\n"
|
||||
"\n"
|
||||
"#include <string>\n"
|
||||
"#include <stdint.h>\n" // INT32_MIN, INT32_MAX
|
||||
"\n",
|
||||
"filename", file_->name(),
|
||||
"filename_identifier", filename_identifier);
|
||||
@ -151,6 +150,11 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
||||
printer->Print(
|
||||
"#include <google/protobuf/repeated_field.h>\n"
|
||||
"#include <google/protobuf/extension_set.h>\n");
|
||||
if (HasMapFields(file_)) {
|
||||
printer->Print(
|
||||
"#include <google/protobuf/map.h>\n"
|
||||
"#include <google/protobuf/map_field_inl.h>\n");
|
||||
}
|
||||
|
||||
if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) {
|
||||
printer->Print(
|
||||
@ -396,6 +400,19 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
|
||||
|
||||
// Generate classes.
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
if (i == 0 && HasGeneratedMethods(file_)) {
|
||||
printer->Print(
|
||||
"\n"
|
||||
"namespace {\n"
|
||||
"\n"
|
||||
"static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;\n"
|
||||
"static void MergeFromFail(int line) {\n"
|
||||
" GOOGLE_CHECK(false) << __FILE__ << \":\" << line;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"} // namespace\n"
|
||||
"\n");
|
||||
}
|
||||
printer->Print("\n");
|
||||
printer->Print(kThickSeparator);
|
||||
printer->Print("\n");
|
||||
|
@ -82,10 +82,10 @@ class FileGenerator {
|
||||
|
||||
const FileDescriptor* file_;
|
||||
|
||||
scoped_array<scoped_ptr<MessageGenerator> > message_generators_;
|
||||
scoped_array<scoped_ptr<EnumGenerator> > enum_generators_;
|
||||
scoped_array<scoped_ptr<ServiceGenerator> > service_generators_;
|
||||
scoped_array<scoped_ptr<ExtensionGenerator> > extension_generators_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > message_generators_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ServiceGenerator> > service_generators_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
|
||||
|
||||
// E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.
|
||||
vector<string> package_parts_;
|
||||
|
@ -105,7 +105,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
|
||||
|
||||
// Generate header.
|
||||
{
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
generator_context->Open(basename + ".h"));
|
||||
io::Printer printer(output.get(), '$');
|
||||
file_generator.GenerateHeader(&printer);
|
||||
@ -113,7 +113,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
|
||||
|
||||
// Generate cc file.
|
||||
{
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
generator_context->Open(basename + ".cc"));
|
||||
io::Printer printer(output.get(), '$');
|
||||
file_generator.GenerateSource(&printer);
|
||||
|
@ -453,6 +453,25 @@ void PrintHandlingOptionalStaticInitializers(
|
||||
}
|
||||
|
||||
|
||||
static bool HasMapFields(const Descriptor* descriptor) {
|
||||
for (int i = 0; i < descriptor->field_count(); ++i) {
|
||||
if (descriptor->field(i)->is_map()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < descriptor->nested_type_count(); ++i) {
|
||||
if (HasMapFields(descriptor->nested_type(i))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HasMapFields(const FileDescriptor* file) {
|
||||
for (int i = 0; i < file->message_type_count(); ++i) {
|
||||
if (HasMapFields(file->message_type(i))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool HasEnumDefinitions(const Descriptor* message_type) {
|
||||
if (message_type->enum_type_count() > 0) return true;
|
||||
for (int i = 0; i < message_type->nested_type_count(); ++i) {
|
||||
|
@ -149,6 +149,10 @@ inline bool UseUnknownFieldSet(const FileDescriptor* file) {
|
||||
}
|
||||
|
||||
|
||||
// Does the file have any map fields, necessitating the file to include
|
||||
// map_field_inl.h and map.h.
|
||||
bool HasMapFields(const FileDescriptor* file);
|
||||
|
||||
// Does this file have any enum type definitions?
|
||||
bool HasEnumDefinitions(const FileDescriptor* file);
|
||||
|
||||
@ -200,6 +204,10 @@ void PrintHandlingOptionalStaticInitializers(
|
||||
const char* without_static_init);
|
||||
|
||||
|
||||
inline bool IsMapEntryMessage(const Descriptor* descriptor) {
|
||||
return descriptor->options().map_entry();
|
||||
}
|
||||
|
||||
// Returns true if the field's CPPTYPE is string or message.
|
||||
bool IsStringOrMessage(const FieldDescriptor* field);
|
||||
|
||||
@ -216,7 +224,7 @@ inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) {
|
||||
}
|
||||
|
||||
inline bool SupportsArenas(const FileDescriptor* file) {
|
||||
return true;
|
||||
return file->options().cc_enable_arenas();
|
||||
}
|
||||
|
||||
inline bool SupportsArenas(const Descriptor* desc) {
|
||||
|
255
src/google/protobuf/compiler/cpp/cpp_map_field.cc
Normal file
255
src/google/protobuf/compiler/cpp/cpp_map_field.cc
Normal file
@ -0,0 +1,255 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_map_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
bool IsProto3Field(const FieldDescriptor* field_descriptor) {
|
||||
const FileDescriptor* file_descriptor = field_descriptor->file();
|
||||
return file_descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3;
|
||||
}
|
||||
|
||||
void SetMessageVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables,
|
||||
const Options& options) {
|
||||
SetCommonFieldVariables(descriptor, variables, options);
|
||||
(*variables)["type"] = FieldMessageTypeName(descriptor);
|
||||
(*variables)["stream_writer"] = (*variables)["declared_type"] +
|
||||
(HasFastArraySerialization(descriptor->message_type()->file()) ?
|
||||
"MaybeToArray" :
|
||||
"");
|
||||
(*variables)["full_name"] = descriptor->full_name();
|
||||
|
||||
const FieldDescriptor* key =
|
||||
descriptor->message_type()->FindFieldByName("key");
|
||||
const FieldDescriptor* val =
|
||||
descriptor->message_type()->FindFieldByName("value");
|
||||
(*variables)["key_cpp"] = PrimitiveTypeName(key->cpp_type());
|
||||
switch (val->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
(*variables)["val_cpp"] = FieldMessageTypeName(val);
|
||||
(*variables)["wrapper"] = "EntryWrapper";
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
(*variables)["val_cpp"] = ClassName(val->enum_type(), false);
|
||||
(*variables)["wrapper"] = "EnumEntryWrapper";
|
||||
break;
|
||||
default:
|
||||
(*variables)["val_cpp"] = PrimitiveTypeName(val->cpp_type());
|
||||
(*variables)["wrapper"] = "EntryWrapper";
|
||||
}
|
||||
(*variables)["key_type"] =
|
||||
"::google::protobuf::FieldDescriptor::TYPE_" +
|
||||
ToUpper(DeclaredTypeMethodName(key->type()));
|
||||
(*variables)["val_type"] =
|
||||
"::google::protobuf::FieldDescriptor::TYPE_" +
|
||||
ToUpper(DeclaredTypeMethodName(val->type()));
|
||||
(*variables)["map_classname"] = ClassName(descriptor->message_type(), false);
|
||||
(*variables)["number"] = Int32ToString(descriptor->number());
|
||||
|
||||
if (!IsProto3Field(descriptor) &&
|
||||
val->type() == FieldDescriptor::TYPE_ENUM) {
|
||||
const EnumValueDescriptor* default_value = val->default_value_enum();
|
||||
(*variables)["default_enum_value"] = Int32ToString(default_value->number());
|
||||
} else {
|
||||
(*variables)["default_enum_value"] = "0";
|
||||
}
|
||||
}
|
||||
|
||||
MapFieldGenerator::
|
||||
MapFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: descriptor_(descriptor) {
|
||||
SetMessageVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
MapFieldGenerator::~MapFieldGenerator() {}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"typedef ::google::protobuf::internal::MapEntry<\n"
|
||||
" $key_cpp$, $val_cpp$,\n"
|
||||
" $key_type$,\n"
|
||||
" $val_type$, $default_enum_value$>\n"
|
||||
" $map_classname$;\n"
|
||||
"::google::protobuf::internal::MapField< $key_cpp$, $val_cpp$,"
|
||||
"$key_type$, $val_type$, $default_enum_value$ > $name$_;\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
|
||||
" $name$() const$deprecation$;\n"
|
||||
"inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
|
||||
" mutable_$name$()$deprecation$;\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
|
||||
"$classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_map:$full_name$)\n"
|
||||
" return $name$_.GetMap();\n"
|
||||
"}\n"
|
||||
"inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
|
||||
"$classname$::mutable_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_mutable_map:$full_name$)\n"
|
||||
" return $name$_.MutableMap();\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Clear();\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateConstructorCode(io::Printer* printer) const {
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
"$name$_.SetAssignDescriptorCallback(\n"
|
||||
" protobuf_AssignDescriptorsOnce);\n"
|
||||
"$name$_.SetEntryDescriptor(\n"
|
||||
" &$type$_descriptor_);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
const FieldDescriptor* value_field =
|
||||
descriptor_->message_type()->FindFieldByName("value");
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::scoped_ptr<$map_classname$> entry($name$_.NewEntry());\n");
|
||||
|
||||
if (IsProto3Field(descriptor_) ||
|
||||
value_field->type() != FieldDescriptor::TYPE_ENUM) {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
|
||||
" input, entry.get()));\n");
|
||||
switch (value_field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
printer->Print(variables_,
|
||||
"(*mutable_$name$())[entry->key()].Swap("
|
||||
"entry->mutable_value());\n");
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
printer->Print(variables_,
|
||||
"(*mutable_$name$())[entry->key()] =\n"
|
||||
" static_cast<$val_cpp$>(*entry->mutable_value());\n");
|
||||
break;
|
||||
default:
|
||||
printer->Print(variables_,
|
||||
"(*mutable_$name$())[entry->key()] = *entry->mutable_value();\n");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"{\n"
|
||||
" ::std::string data;\n"
|
||||
" DO_(::google::protobuf::internal::WireFormatLite::ReadString(input, &data));\n"
|
||||
" DO_(entry->ParseFromString(data));\n"
|
||||
" if ($val_cpp$_IsValid(*entry->mutable_value())) {\n"
|
||||
" (*mutable_$name$())[entry->key()] =\n"
|
||||
" static_cast<$val_cpp$>(*entry->mutable_value());\n"
|
||||
" } else {\n"
|
||||
" mutable_unknown_fields()->AddLengthDelimited($number$, data);\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"{\n"
|
||||
" ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
|
||||
" for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
||||
" it = $name$().begin(); it != $name$().end(); ++it) {\n"
|
||||
" entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
|
||||
" $number$, *entry, output);\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"{\n"
|
||||
" ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
|
||||
" for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
||||
" it = $name$().begin(); it != $name$().end(); ++it) {\n"
|
||||
" entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
|
||||
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" Write$declared_type$NoVirtualToArray(\n"
|
||||
" $number$, *entry, target);\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MapFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ * this->$name$_size();\n"
|
||||
"{\n"
|
||||
" ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
|
||||
" for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
||||
" it = $name$().begin(); it != $name$().end(); ++it) {\n"
|
||||
" entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
|
||||
" total_size += ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" $declared_type$SizeNoVirtual(*entry);\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
75
src/google/protobuf/compiler/cpp/cpp_map_field.h
Normal file
75
src/google/protobuf/compiler/cpp/cpp_map_field.h
Normal file
@ -0,0 +1,75 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_message_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
class MapFieldGenerator : public FieldGenerator {
|
||||
public:
|
||||
explicit MapFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options);
|
||||
~MapFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
void GenerateMergingCode(io::Printer* printer) const;
|
||||
void GenerateSwappingCode(io::Printer* printer) const;
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
const FieldDescriptor* descriptor_;
|
||||
map<string, string> variables_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
|
@ -334,6 +334,31 @@ bool HasHasMethod(const FieldDescriptor* field) {
|
||||
return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE;
|
||||
}
|
||||
|
||||
// Collects map entry message type information.
|
||||
void CollectMapInfo(const Descriptor* descriptor,
|
||||
map<string, string>* variables) {
|
||||
GOOGLE_CHECK(IsMapEntryMessage(descriptor));
|
||||
const FieldDescriptor* key = descriptor->FindFieldByName("key");
|
||||
const FieldDescriptor* val = descriptor->FindFieldByName("value");
|
||||
(*variables)["key"] = PrimitiveTypeName(key->cpp_type());
|
||||
switch (val->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
(*variables)["val"] = FieldMessageTypeName(val);
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
(*variables)["val"] = ClassName(val->enum_type(), false);
|
||||
break;
|
||||
default:
|
||||
(*variables)["val"] = PrimitiveTypeName(val->cpp_type());
|
||||
}
|
||||
(*variables)["key_type"] =
|
||||
"::google::protobuf::FieldDescriptor::TYPE_" +
|
||||
ToUpper(DeclaredTypeMethodName(key->type()));
|
||||
(*variables)["val_type"] =
|
||||
"::google::protobuf::FieldDescriptor::TYPE_" +
|
||||
ToUpper(DeclaredTypeMethodName(val->type()));
|
||||
}
|
||||
|
||||
// Does the given field have a private (internal helper only) has_$name$()
|
||||
// method?
|
||||
bool HasPrivateHasMethod(const FieldDescriptor* field) {
|
||||
@ -353,11 +378,11 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
|
||||
classname_(ClassName(descriptor, false)),
|
||||
options_(options),
|
||||
field_generators_(descriptor, options),
|
||||
nested_generators_(new scoped_ptr<
|
||||
nested_generators_(new google::protobuf::scoped_ptr<
|
||||
MessageGenerator>[descriptor->nested_type_count()]),
|
||||
enum_generators_(
|
||||
new scoped_ptr<EnumGenerator>[descriptor->enum_type_count()]),
|
||||
extension_generators_(new scoped_ptr<
|
||||
new google::protobuf::scoped_ptr<EnumGenerator>[descriptor->enum_type_count()]),
|
||||
extension_generators_(new google::protobuf::scoped_ptr<
|
||||
ExtensionGenerator>[descriptor->extension_count()]) {
|
||||
|
||||
for (int i = 0; i < descriptor->nested_type_count(); i++) {
|
||||
@ -391,6 +416,10 @@ GenerateForwardDeclaration(io::Printer* printer) {
|
||||
"classname", classname_);
|
||||
|
||||
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
||||
// map entry message doesn't need forward declaration. Since map entry
|
||||
// message cannot be a top level class, we just need to avoid calling
|
||||
// GenerateForwardDeclaration here.
|
||||
if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
|
||||
nested_generators_[i]->GenerateForwardDeclaration(printer);
|
||||
}
|
||||
}
|
||||
@ -622,6 +651,10 @@ static bool CanClearByZeroing(const FieldDescriptor* field) {
|
||||
void MessageGenerator::
|
||||
GenerateClassDefinition(io::Printer* printer) {
|
||||
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
||||
// map entry message doesn't need class definition. Since map entry message
|
||||
// cannot be a top level class, we just need to avoid calling
|
||||
// GenerateClassDefinition here.
|
||||
if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
|
||||
nested_generators_[i]->GenerateClassDefinition(printer);
|
||||
printer->Print("\n");
|
||||
printer->Print(kThinSeparator);
|
||||
@ -876,9 +909,11 @@ GenerateClassDefinition(io::Printer* printer) {
|
||||
// Import all nested message classes into this class's scope with typedefs.
|
||||
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
||||
const Descriptor* nested_type = descriptor_->nested_type(i);
|
||||
printer->Print("typedef $nested_full_name$ $nested_name$;\n",
|
||||
"nested_name", nested_type->name(),
|
||||
"nested_full_name", ClassName(nested_type, false));
|
||||
if (!IsMapEntryMessage(nested_type)) {
|
||||
printer->Print("typedef $nested_full_name$ $nested_name$;\n",
|
||||
"nested_name", nested_type->name(),
|
||||
"nested_full_name", ClassName(nested_type, false));
|
||||
}
|
||||
}
|
||||
|
||||
if (descriptor_->nested_type_count() > 0) {
|
||||
@ -1124,6 +1159,10 @@ GenerateClassDefinition(io::Printer* printer) {
|
||||
void MessageGenerator::
|
||||
GenerateInlineMethods(io::Printer* printer) {
|
||||
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
||||
// map entry message doesn't need inline methods. Since map entry message
|
||||
// cannot be a top level class, we just need to avoid calling
|
||||
// GenerateInlineMethods here.
|
||||
if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
|
||||
nested_generators_[i]->GenerateInlineMethods(printer);
|
||||
printer->Print(kThinSeparator);
|
||||
printer->Print("\n");
|
||||
@ -1151,11 +1190,17 @@ GenerateInlineMethods(io::Printer* printer) {
|
||||
|
||||
void MessageGenerator::
|
||||
GenerateDescriptorDeclarations(io::Printer* printer) {
|
||||
printer->Print(
|
||||
"const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n"
|
||||
"const ::google::protobuf::internal::GeneratedMessageReflection*\n"
|
||||
" $name$_reflection_ = NULL;\n",
|
||||
"name", classname_);
|
||||
if (!IsMapEntryMessage(descriptor_)) {
|
||||
printer->Print(
|
||||
"const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n"
|
||||
"const ::google::protobuf::internal::GeneratedMessageReflection*\n"
|
||||
" $name$_reflection_ = NULL;\n",
|
||||
"name", classname_);
|
||||
} else {
|
||||
printer->Print(
|
||||
"const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n",
|
||||
"name", classname_);
|
||||
}
|
||||
|
||||
// Generate oneof default instance for reflection usage.
|
||||
if (descriptor_->oneof_decl_count() > 0) {
|
||||
@ -1206,13 +1251,20 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
|
||||
"$parent$_descriptor_->nested_type($index$);\n");
|
||||
}
|
||||
|
||||
if (IsMapEntryMessage(descriptor_)) return;
|
||||
|
||||
// Generate the offsets.
|
||||
GenerateOffsets(printer);
|
||||
|
||||
const bool pass_pool_and_factory = false;
|
||||
vars["fn"] = pass_pool_and_factory ?
|
||||
"new ::google::protobuf::internal::GeneratedMessageReflection" :
|
||||
"::google::protobuf::internal::GeneratedMessageReflection"
|
||||
"::NewGeneratedMessageReflection";
|
||||
// Construct the reflection object.
|
||||
printer->Print(vars,
|
||||
"$classname$_reflection_ =\n"
|
||||
" new ::google::protobuf::internal::GeneratedMessageReflection(\n"
|
||||
" $fn$(\n"
|
||||
" $classname$_descriptor_,\n"
|
||||
" $classname$::default_instance_,\n"
|
||||
" $classname$_offsets_,\n");
|
||||
@ -1254,10 +1306,12 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
|
||||
"$classname$, _oneof_case_[0]),\n");
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
" ::google::protobuf::DescriptorPool::generated_pool(),\n");
|
||||
printer->Print(vars,
|
||||
" ::google::protobuf::MessageFactory::generated_factory(),\n");
|
||||
if (pass_pool_and_factory) {
|
||||
printer->Print(
|
||||
" ::google::protobuf::DescriptorPool::generated_pool(),\n");
|
||||
printer->Print(vars,
|
||||
" ::google::protobuf::MessageFactory::generated_factory(),\n");
|
||||
}
|
||||
|
||||
printer->Print(vars,
|
||||
" sizeof($classname$),\n");
|
||||
@ -1289,10 +1343,37 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
|
||||
void MessageGenerator::
|
||||
GenerateTypeRegistrations(io::Printer* printer) {
|
||||
// Register this message type with the message factory.
|
||||
printer->Print(
|
||||
"::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
|
||||
" $classname$_descriptor_, &$classname$::default_instance());\n",
|
||||
"classname", classname_);
|
||||
if (!IsMapEntryMessage(descriptor_)) {
|
||||
printer->Print(
|
||||
"::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
|
||||
" $classname$_descriptor_, &$classname$::default_instance());\n",
|
||||
"classname", classname_);
|
||||
}
|
||||
else {
|
||||
map<string, string> vars;
|
||||
CollectMapInfo(descriptor_, &vars);
|
||||
vars["classname"] = classname_;
|
||||
|
||||
const FieldDescriptor* val = descriptor_->FindFieldByName("value");
|
||||
if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO2 &&
|
||||
val->type() == FieldDescriptor::TYPE_ENUM) {
|
||||
const EnumValueDescriptor* default_value = val->default_value_enum();
|
||||
vars["default_enum_value"] = Int32ToString(default_value->number());
|
||||
} else {
|
||||
vars["default_enum_value"] = "0";
|
||||
}
|
||||
|
||||
printer->Print(vars,
|
||||
"::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
|
||||
" $classname$_descriptor_,\n"
|
||||
" ::google::protobuf::internal::MapEntry<\n"
|
||||
" $key$,\n"
|
||||
" $val$,\n"
|
||||
" $key_type$,\n"
|
||||
" $val_type$,\n"
|
||||
" $default_enum_value$>::CreateDefaultInstance(\n"
|
||||
" $classname$_descriptor_));\n");
|
||||
}
|
||||
|
||||
// Handle nested types.
|
||||
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
||||
@ -1309,6 +1390,8 @@ GenerateDefaultInstanceAllocator(io::Printer* printer) {
|
||||
.GenerateDefaultInstanceAllocator(printer);
|
||||
}
|
||||
|
||||
if (IsMapEntryMessage(descriptor_)) return;
|
||||
|
||||
// Construct the default instance. We can't call InitAsDefaultInstance() yet
|
||||
// because we need to make sure all default instances that this one might
|
||||
// depend on are constructed first.
|
||||
@ -1343,6 +1426,10 @@ GenerateDefaultInstanceInitializer(io::Printer* printer) {
|
||||
|
||||
// Handle nested types.
|
||||
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
||||
// map entry message doesn't need to initialize default instance manually.
|
||||
// Since map entry message cannot be a top level class, we just need to
|
||||
// avoid calling DefaultInstanceInitializer here.
|
||||
if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
|
||||
nested_generators_[i]->GenerateDefaultInstanceInitializer(printer);
|
||||
}
|
||||
}
|
||||
@ -1372,6 +1459,7 @@ GenerateShutdownCode(io::Printer* printer) {
|
||||
|
||||
// Handle nested types.
|
||||
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
||||
if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
|
||||
nested_generators_[i]->GenerateShutdownCode(printer);
|
||||
}
|
||||
}
|
||||
@ -1383,6 +1471,10 @@ GenerateClassMethods(io::Printer* printer) {
|
||||
}
|
||||
|
||||
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
||||
// map entry message doesn't need class methods. Since map entry message
|
||||
// cannot be a top level class, we just need to avoid calling
|
||||
// GenerateClassMethods here.
|
||||
if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
|
||||
nested_generators_[i]->GenerateClassMethods(printer);
|
||||
printer->Print("\n");
|
||||
printer->Print(kThinSeparator);
|
||||
@ -2195,7 +2287,7 @@ GenerateMergeFrom(io::Printer* printer) {
|
||||
// base class as a parameter).
|
||||
printer->Print(
|
||||
"void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
|
||||
" GOOGLE_CHECK_NE(&from, this);\n",
|
||||
" if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
|
||||
"classname", classname_);
|
||||
printer->Indent();
|
||||
|
||||
@ -2230,7 +2322,7 @@ GenerateMergeFrom(io::Printer* printer) {
|
||||
// Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
|
||||
printer->Print(
|
||||
"void $classname$::MergeFrom(const $classname$& from) {\n"
|
||||
" GOOGLE_CHECK_NE(&from, this);\n",
|
||||
" if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
|
||||
"classname", classname_);
|
||||
printer->Indent();
|
||||
|
||||
@ -2429,7 +2521,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
|
||||
printer->Print("for (;;) {\n");
|
||||
printer->Indent();
|
||||
|
||||
scoped_array<const FieldDescriptor*> ordered_fields(
|
||||
google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields(
|
||||
SortFieldsByNumber(descriptor_));
|
||||
uint32 maxtag = descriptor_->field_count() == 0 ? 0 :
|
||||
WireFormat::MakeTag(ordered_fields[descriptor_->field_count() - 1]);
|
||||
@ -2788,7 +2880,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) {
|
||||
|
||||
void MessageGenerator::
|
||||
GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
|
||||
scoped_array<const FieldDescriptor*> ordered_fields(
|
||||
google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields(
|
||||
SortFieldsByNumber(descriptor_));
|
||||
|
||||
vector<const Descriptor::ExtensionRange*> sorted_extensions;
|
||||
@ -3186,14 +3278,14 @@ GenerateIsInitialized(io::Printer* printer) {
|
||||
" return false;\n",
|
||||
"name", FieldName(field));
|
||||
} else {
|
||||
if (field->options().weak()) {
|
||||
if (field->options().weak() || !field->containing_oneof()) {
|
||||
// For weak fields, use the data member (::google::protobuf::Message*) instead
|
||||
// of the getter to avoid a link dependency on the weak message type
|
||||
// which is only forward declared.
|
||||
printer->Print(
|
||||
"if (has_$name$()) {\n"
|
||||
" if (!this->$name$_->IsInitialized()) return false;\n"
|
||||
"}\n",
|
||||
"if (has_$name$()) {\n"
|
||||
" if (!this->$name$_->IsInitialized()) return false;\n"
|
||||
"}\n",
|
||||
"name", FieldName(field));
|
||||
} else {
|
||||
printer->Print(
|
||||
|
@ -163,9 +163,9 @@ class MessageGenerator {
|
||||
Options options_;
|
||||
FieldGeneratorMap field_generators_;
|
||||
vector< vector<string> > runs_of_fields_; // that might be trivially cleared
|
||||
scoped_array<scoped_ptr<MessageGenerator> > nested_generators_;
|
||||
scoped_array<scoped_ptr<EnumGenerator> > enum_generators_;
|
||||
scoped_array<scoped_ptr<ExtensionGenerator> > extension_generators_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > nested_generators_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
|
||||
int num_required_fields_;
|
||||
bool uses_string_;
|
||||
|
||||
|
@ -49,6 +49,10 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
|
||||
const Options& options) {
|
||||
SetCommonFieldVariables(descriptor, variables, options);
|
||||
(*variables)["type"] = FieldMessageTypeName(descriptor);
|
||||
if (descriptor->options().weak() || !descriptor->containing_oneof()) {
|
||||
(*variables)["non_null_ptr_to_name"] =
|
||||
StrCat("this->", (*variables)["name"], "_");
|
||||
}
|
||||
(*variables)["stream_writer"] = (*variables)["declared_type"] +
|
||||
(HasFastArraySerialization(descriptor->message_type()->file()) ?
|
||||
"MaybeToArray" :
|
||||
@ -293,7 +297,7 @@ void MessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
|
||||
" $number$, this->$name$(), output);\n");
|
||||
" $number$, *$non_null_ptr_to_name$, output);\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
@ -301,7 +305,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" Write$declared_type$NoVirtualToArray(\n"
|
||||
" $number$, this->$name$(), target);\n");
|
||||
" $number$, *$non_null_ptr_to_name$, target);\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
@ -309,7 +313,7 @@ GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
|
||||
" this->$name$());\n");
|
||||
" *$non_null_ptr_to_name$);\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
@ -591,7 +595,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
"for (unsigned int i = 0, n = this->$name$_size(); i < n; i++) {\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
|
||||
" $number$, this->$name$(i), output);\n"
|
||||
"}\n");
|
||||
@ -600,7 +604,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
"for (unsigned int i = 0, n = this->$name$_size(); i < n; i++) {\n"
|
||||
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" Write$declared_type$NoVirtualToArray(\n"
|
||||
" $number$, this->$name$(i), target);\n"
|
||||
|
@ -171,7 +171,7 @@ class TestGenerator : public CodeGenerator {
|
||||
|
||||
void TryInsert(const string& filename, const string& insertion_point,
|
||||
GeneratorContext* context) const {
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
context->OpenForInsert(filename, insertion_point));
|
||||
io::Printer printer(output.get(), '$');
|
||||
printer.Print("// inserted $name$\n", "name", insertion_point);
|
||||
|
@ -306,7 +306,14 @@ GenerateClearingCode(io::Printer* printer) const {
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "set_$name$(from.$name$());\n");
|
||||
if (SupportsArenas(descriptor_) || descriptor_->containing_oneof() != NULL) {
|
||||
// TODO(gpike): improve this
|
||||
printer->Print(variables_, "set_$name$(from.$name$());\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"$set_hasbit$\n"
|
||||
"$name$_.AssignWithDefault($default_variable$, from.$name$_);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
|
@ -251,7 +251,7 @@ TEST(GeneratedMessageTest, ReleaseString) {
|
||||
|
||||
message.set_default_string("blah");
|
||||
EXPECT_TRUE(message.has_default_string());
|
||||
scoped_ptr<string> str(message.release_default_string());
|
||||
google::protobuf::scoped_ptr<string> str(message.release_default_string());
|
||||
EXPECT_FALSE(message.has_default_string());
|
||||
ASSERT_TRUE(str != NULL);
|
||||
EXPECT_EQ("blah", *str);
|
||||
@ -270,7 +270,7 @@ TEST(GeneratedMessageTest, ReleaseMessage) {
|
||||
EXPECT_FALSE(message.has_optional_nested_message());
|
||||
|
||||
message.mutable_optional_nested_message()->set_bb(1);
|
||||
scoped_ptr<unittest::TestAllTypes::NestedMessage> nest(
|
||||
google::protobuf::scoped_ptr<unittest::TestAllTypes::NestedMessage> nest(
|
||||
message.release_optional_nested_message());
|
||||
EXPECT_FALSE(message.has_optional_nested_message());
|
||||
ASSERT_TRUE(nest != NULL);
|
||||
@ -534,7 +534,7 @@ TEST(GeneratedMessageTest, DynamicMessageCopyFrom) {
|
||||
|
||||
// Construct a new version of the dynamic message via the factory.
|
||||
DynamicMessageFactory factory;
|
||||
scoped_ptr<Message> message1;
|
||||
google::protobuf::scoped_ptr<Message> message1;
|
||||
message1.reset(factory.GetPrototype(
|
||||
unittest::TestAllTypes::descriptor())->New());
|
||||
|
||||
@ -581,9 +581,9 @@ TEST(GeneratedMessageTest, NonEmptyMergeFrom) {
|
||||
|
||||
TEST(GeneratedMessageTest, MergeFromSelf) {
|
||||
unittest::TestAllTypes message;
|
||||
EXPECT_DEATH(message.MergeFrom(message), "&from");
|
||||
EXPECT_DEATH(message.MergeFrom(message), "Check failed:.*pb[.]cc");
|
||||
EXPECT_DEATH(message.MergeFrom(implicit_cast<const Message&>(message)),
|
||||
"&from");
|
||||
"Check failed:.*pb[.]cc");
|
||||
}
|
||||
|
||||
#endif // PROTOBUF_HAS_DEATH_TEST
|
||||
@ -1221,7 +1221,7 @@ class GeneratedServiceTest : public testing::Test {
|
||||
unittest::FooResponse foo_response_;
|
||||
unittest::BarRequest bar_request_;
|
||||
unittest::BarResponse bar_response_;
|
||||
scoped_ptr<Closure> done_;
|
||||
google::protobuf::scoped_ptr<Closure> done_;
|
||||
};
|
||||
|
||||
TEST_F(GeneratedServiceTest, GetDescriptor) {
|
||||
@ -1519,7 +1519,7 @@ TEST_F(OneofTest, ReleaseString) {
|
||||
|
||||
message.set_foo_string("blah");
|
||||
EXPECT_TRUE(message.has_foo_string());
|
||||
scoped_ptr<string> str(message.release_foo_string());
|
||||
google::protobuf::scoped_ptr<string> str(message.release_foo_string());
|
||||
EXPECT_FALSE(message.has_foo_string());
|
||||
ASSERT_TRUE(str != NULL);
|
||||
EXPECT_EQ("blah", *str);
|
||||
@ -1573,7 +1573,7 @@ TEST_F(OneofTest, ReleaseMessage) {
|
||||
|
||||
message.mutable_foo_message()->set_qux_int(1);
|
||||
EXPECT_TRUE(message.has_foo_message());
|
||||
scoped_ptr<unittest::TestOneof2_NestedMessage> mes(
|
||||
google::protobuf::scoped_ptr<unittest::TestOneof2_NestedMessage> mes(
|
||||
message.release_foo_message());
|
||||
EXPECT_FALSE(message.has_foo_message());
|
||||
ASSERT_TRUE(mes != NULL);
|
||||
|
@ -125,7 +125,7 @@ SourceTreeDescriptorDatabase::~SourceTreeDescriptorDatabase() {}
|
||||
|
||||
bool SourceTreeDescriptorDatabase::FindFileByName(
|
||||
const string& filename, FileDescriptorProto* output) {
|
||||
scoped_ptr<io::ZeroCopyInputStream> input(source_tree_->Open(filename));
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyInputStream> input(source_tree_->Open(filename));
|
||||
if (input == NULL) {
|
||||
if (error_collector_ != NULL) {
|
||||
error_collector_->AddError(filename, -1, 0,
|
||||
@ -403,7 +403,7 @@ DiskSourceTree::DiskFileToVirtualFile(
|
||||
// Verify that we can open the file. Note that this also has the side-effect
|
||||
// of verifying that we are not canonicalizing away any non-existent
|
||||
// directories.
|
||||
scoped_ptr<io::ZeroCopyInputStream> stream(OpenDiskFile(disk_file));
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyInputStream> stream(OpenDiskFile(disk_file));
|
||||
if (stream == NULL) {
|
||||
return CANNOT_OPEN;
|
||||
}
|
||||
@ -413,7 +413,7 @@ DiskSourceTree::DiskFileToVirtualFile(
|
||||
|
||||
bool DiskSourceTree::VirtualFileToDiskFile(const string& virtual_file,
|
||||
string* disk_file) {
|
||||
scoped_ptr<io::ZeroCopyInputStream> stream(
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyInputStream> stream(
|
||||
OpenVirtualFile(virtual_file, disk_file));
|
||||
return stream != NULL;
|
||||
}
|
||||
|
@ -242,7 +242,7 @@ class DiskSourceTreeTest : public testing::Test {
|
||||
|
||||
virtual void TearDown() {
|
||||
for (int i = 0; i < dirnames_.size(); i++) {
|
||||
if (File::Exists(dirnames_[i])) {
|
||||
if (FileExists(dirnames_[i])) {
|
||||
File::DeleteRecursively(dirnames_[i], NULL, NULL);
|
||||
}
|
||||
}
|
||||
@ -258,7 +258,7 @@ class DiskSourceTreeTest : public testing::Test {
|
||||
|
||||
void ExpectFileContents(const string& filename,
|
||||
const char* expected_contents) {
|
||||
scoped_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
|
||||
|
||||
ASSERT_FALSE(input == NULL);
|
||||
|
||||
@ -275,7 +275,7 @@ class DiskSourceTreeTest : public testing::Test {
|
||||
|
||||
void ExpectCannotOpenFile(const string& filename,
|
||||
const string& error_message) {
|
||||
scoped_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyInputStream> input(source_tree_.Open(filename));
|
||||
EXPECT_TRUE(input == NULL);
|
||||
EXPECT_EQ(error_message, source_tree_.GetLastErrorMessage());
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ class Context {
|
||||
void InitializeFieldGeneratorInfoForFields(
|
||||
const vector<const FieldDescriptor*>& fields);
|
||||
|
||||
scoped_ptr<ClassNameResolver> name_resolver_;
|
||||
google::protobuf::scoped_ptr<ClassNameResolver> name_resolver_;
|
||||
map<const FieldDescriptor*, FieldGeneratorInfo> field_generator_info_map_;
|
||||
map<const OneofDescriptor*, OneofGeneratorInfo> oneof_generator_info_map_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Context);
|
||||
|
@ -159,7 +159,7 @@ template <>
|
||||
FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap(
|
||||
const Descriptor* descriptor, Context* context)
|
||||
: descriptor_(descriptor),
|
||||
field_generators_(new scoped_ptr<
|
||||
field_generators_(new google::protobuf::scoped_ptr<
|
||||
ImmutableFieldGenerator>[descriptor->field_count()]) {
|
||||
|
||||
// Construct all the FieldGenerators and assign them bit indices for their
|
||||
|
@ -108,7 +108,7 @@ class FieldGeneratorMap {
|
||||
const Descriptor* descriptor_;
|
||||
Context* context_;
|
||||
ClassNameResolver* name_resolver_;
|
||||
scoped_array<scoped_ptr<FieldGeneratorType> > field_generators_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<FieldGeneratorType> > field_generators_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
|
||||
};
|
||||
|
@ -121,7 +121,7 @@ void CollectExtensions(const FileDescriptorProto& file_proto,
|
||||
"descriptor.proto is not in the transitive dependencies. "
|
||||
"This normally should not happen. Please report a bug.";
|
||||
DynamicMessageFactory factory;
|
||||
scoped_ptr<Message> dynamic_file_proto(
|
||||
google::protobuf::scoped_ptr<Message> dynamic_file_proto(
|
||||
factory.GetPrototype(file_proto_desc)->New());
|
||||
GOOGLE_CHECK(dynamic_file_proto.get() != NULL);
|
||||
GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data));
|
||||
@ -146,9 +146,9 @@ FileGenerator::FileGenerator(const FileDescriptor* file, bool immutable_api)
|
||||
: file_(file),
|
||||
java_package_(FileJavaPackage(file, immutable_api)),
|
||||
message_generators_(
|
||||
new scoped_ptr<MessageGenerator>[file->message_type_count()]),
|
||||
new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
|
||||
extension_generators_(
|
||||
new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
|
||||
new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]),
|
||||
context_(new Context(file)),
|
||||
name_resolver_(context_->GetNameResolver()),
|
||||
immutable_api_(immutable_api) {
|
||||
@ -240,7 +240,7 @@ void FileGenerator::Generate(io::Printer* printer) {
|
||||
}
|
||||
if (HasGenericServices(file_)) {
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
scoped_ptr<ServiceGenerator> generator(
|
||||
google::protobuf::scoped_ptr<ServiceGenerator> generator(
|
||||
generator_factory_->NewServiceGenerator(file_->service(i)));
|
||||
generator->Generate(printer);
|
||||
}
|
||||
@ -340,7 +340,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
|
||||
"com.google.protobuf.ExtensionRegistry registry =\n"
|
||||
" com.google.protobuf.ExtensionRegistry.newInstance();\n");
|
||||
for (int i = 0; i < extensions.size(); i++) {
|
||||
scoped_ptr<ExtensionGenerator> generator(
|
||||
google::protobuf::scoped_ptr<ExtensionGenerator> generator(
|
||||
generator_factory_->NewExtensionGenerator(extensions[i]));
|
||||
generator->GenerateRegistrationCode(printer);
|
||||
}
|
||||
@ -444,7 +444,7 @@ static void GenerateSibling(const string& package_dir,
|
||||
string filename = package_dir + descriptor->name() + name_suffix + ".java";
|
||||
file_list->push_back(filename);
|
||||
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
|
||||
io::Printer printer(output.get(), '$');
|
||||
|
||||
printer.Print(
|
||||
@ -492,7 +492,7 @@ void FileGenerator::GenerateSiblings(const string& package_dir,
|
||||
}
|
||||
if (HasGenericServices(file_)) {
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
scoped_ptr<ServiceGenerator> generator(
|
||||
google::protobuf::scoped_ptr<ServiceGenerator> generator(
|
||||
generator_factory_->NewServiceGenerator(file_->service(i)));
|
||||
GenerateSibling<ServiceGenerator>(package_dir, java_package_,
|
||||
file_->service(i),
|
||||
|
@ -99,10 +99,10 @@ class FileGenerator {
|
||||
string java_package_;
|
||||
string classname_;
|
||||
|
||||
scoped_array<scoped_ptr<MessageGenerator> > message_generators_;
|
||||
scoped_array<scoped_ptr<ExtensionGenerator> > extension_generators_;
|
||||
scoped_ptr<GeneratorFactory> generator_factory_;
|
||||
scoped_ptr<Context> context_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > message_generators_;
|
||||
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
|
||||
google::protobuf::scoped_ptr<GeneratorFactory> generator_factory_;
|
||||
google::protobuf::scoped_ptr<Context> context_;
|
||||
ClassNameResolver* name_resolver_;
|
||||
bool immutable_api_;
|
||||
|
||||
|
@ -130,7 +130,7 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
|
||||
all_files.push_back(java_filename);
|
||||
|
||||
// Generate main java file.
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
context->Open(java_filename));
|
||||
io::Printer printer(output.get(), '$');
|
||||
file_generator->Generate(&printer);
|
||||
@ -148,7 +148,7 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
|
||||
if (!output_list_file.empty()) {
|
||||
// Generate output list. This is just a simple text file placed in a
|
||||
// deterministic location which lists the .java files being generated.
|
||||
scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
|
||||
context->Open(output_list_file));
|
||||
io::Printer srclist_printer(srclist_raw_output.get(), '$');
|
||||
for (int i = 0; i < all_files.size(); i++) {
|
||||
|
@ -70,6 +70,13 @@ bool GenerateHasBits(const Descriptor* descriptor) {
|
||||
return SupportFieldPresence(descriptor->file()) ||
|
||||
HasRepeatedFields(descriptor);
|
||||
}
|
||||
|
||||
string MapValueImmutableClassdName(const Descriptor* descriptor,
|
||||
ClassNameResolver* name_resolver) {
|
||||
const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
|
||||
GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
|
||||
return name_resolver->GetImmutableClassName(value_field->message_type());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// ===================================================================
|
||||
@ -323,18 +330,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n"
|
||||
"\n"
|
||||
"private static final $classname$ defaultInstance;\n"
|
||||
"public static $classname$ getDefaultInstance() {\n"
|
||||
" return defaultInstance;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"public $classname$ getDefaultInstanceForType() {\n"
|
||||
" return defaultInstance;\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", descriptor_->name(),
|
||||
"lite", variables["lite"]);
|
||||
"\n");
|
||||
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
printer->Print(
|
||||
@ -479,18 +475,25 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
|
||||
GenerateParseFromMethods(printer);
|
||||
GenerateBuilder(printer);
|
||||
|
||||
// Carefully initialize the default instance in such a way that it doesn't
|
||||
// conflict with other initialization.
|
||||
printer->Print(
|
||||
"\n"
|
||||
"static {\n"
|
||||
" defaultInstance = new $classname$();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"// @@protoc_insertion_point(class_scope:$full_name$)\n",
|
||||
"classname", descriptor_->name(),
|
||||
"full_name", descriptor_->full_name());
|
||||
|
||||
// Carefully initialize the default instance in such a way that it doesn't
|
||||
// conflict with other initialization.
|
||||
printer->Print("private static final $classname$ defaultInstance =\n"
|
||||
" new $classname$();\n"
|
||||
"public static $classname$ getDefaultInstance() {\n"
|
||||
" return defaultInstance;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"public $classname$ getDefaultInstanceForType() {\n"
|
||||
" return defaultInstance;\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", descriptor_->name());
|
||||
|
||||
// Extensions must be declared after the defaultInstance is initialized
|
||||
// because the defaultInstance is used by the extension to lazily retrieve
|
||||
// the outer class's FileDescriptor.
|
||||
@ -508,7 +511,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
|
||||
|
||||
void ImmutableMessageGenerator::
|
||||
GenerateMessageSerializationMethods(io::Printer* printer) {
|
||||
scoped_array<const FieldDescriptor*> sorted_fields(
|
||||
google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
|
||||
SortFieldsByNumber(descriptor_));
|
||||
|
||||
vector<const Descriptor::ExtensionRange*> sorted_extensions;
|
||||
@ -913,15 +916,15 @@ GenerateDescriptorMethods(io::Printer* printer) {
|
||||
|
||||
void ImmutableMessageGenerator::
|
||||
GenerateCommonBuilderMethods(io::Printer* printer) {
|
||||
printer->Print(
|
||||
"// Construct using $classname$.newBuilder()\n"
|
||||
"private Builder() {\n"
|
||||
" maybeForceBuilderInitialization();\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", name_resolver_->GetImmutableClassName(descriptor_));
|
||||
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
printer->Print(
|
||||
"// Construct using $classname$.newBuilder()\n"
|
||||
"private Builder() {\n"
|
||||
" maybeForceBuilderInitialization();\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", name_resolver_->GetImmutableClassName(descriptor_));
|
||||
|
||||
printer->Print(
|
||||
"private Builder(\n"
|
||||
" com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
|
||||
@ -929,6 +932,17 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
|
||||
" maybeForceBuilderInitialization();\n"
|
||||
"}\n",
|
||||
"classname", name_resolver_->GetImmutableClassName(descriptor_));
|
||||
} else {
|
||||
// LITE runtime passes along the default instance to implement
|
||||
// getDefaultInstanceForType() at the GneratedMessageLite level.
|
||||
printer->Print(
|
||||
"// Construct using $classname$.newBuilder()\n"
|
||||
"private Builder() {\n"
|
||||
" super(defaultInstance);\n"
|
||||
" maybeForceBuilderInitialization();\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", name_resolver_->GetImmutableClassName(descriptor_));
|
||||
}
|
||||
|
||||
|
||||
@ -994,25 +1008,33 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
|
||||
"\n",
|
||||
"fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
|
||||
"identifier", UniqueFileScopeIdentifier(descriptor_));
|
||||
|
||||
// LITE runtime implements this in GeneratedMessageLite.
|
||||
printer->Print(
|
||||
"public $classname$ getDefaultInstanceForType() {\n"
|
||||
" return $classname$.getDefaultInstance();\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", name_resolver_->GetImmutableClassName(descriptor_));
|
||||
}
|
||||
printer->Print(
|
||||
"public $classname$ getDefaultInstanceForType() {\n"
|
||||
" return $classname$.getDefaultInstance();\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", name_resolver_->GetImmutableClassName(descriptor_));
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
// LITE implements build in GeneratedMessageLite to save methods.
|
||||
printer->Print(
|
||||
"public $classname$ build() {\n"
|
||||
" $classname$ result = buildPartial();\n"
|
||||
" if (!result.isInitialized()) {\n"
|
||||
" throw newUninitializedMessageException(result);\n"
|
||||
" }\n"
|
||||
" return result;\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", name_resolver_->GetImmutableClassName(descriptor_));
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"public $classname$ build() {\n"
|
||||
" $classname$ result = buildPartial();\n"
|
||||
" if (!result.isInitialized()) {\n"
|
||||
" throw newUninitializedMessageException(result);\n"
|
||||
" }\n"
|
||||
" return result;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"public $classname$ buildPartial() {\n"
|
||||
" $classname$ result = new $classname$(this);\n",
|
||||
"classname", name_resolver_->GetImmutableClassName(descriptor_));
|
||||
@ -1255,17 +1277,31 @@ void ImmutableMessageGenerator::GenerateIsInitialized(
|
||||
"memoize", memoization ? "memoizedIsInitialized = 0;" : "");
|
||||
break;
|
||||
case FieldDescriptor::LABEL_REPEATED:
|
||||
printer->Print(
|
||||
"for (int i = 0; i < get$name$Count(); i++) {\n"
|
||||
" if (!get$name$(i).isInitialized()) {\n"
|
||||
" $memoize$\n"
|
||||
" return false;\n"
|
||||
" }\n"
|
||||
"}\n",
|
||||
"type", name_resolver_->GetImmutableClassName(
|
||||
field->message_type()),
|
||||
"name", info->capitalized_name,
|
||||
"memoize", memoization ? "memoizedIsInitialized = 0;" : "");
|
||||
if (IsMapEntry(field->message_type())) {
|
||||
printer->Print(
|
||||
"for ($type$ item : get$name$().values()) {\n"
|
||||
" if (!item.isInitialized()) {\n"
|
||||
" $memoize$\n"
|
||||
" return false;\n"
|
||||
" }\n"
|
||||
"}\n",
|
||||
"type", MapValueImmutableClassdName(field->message_type(),
|
||||
name_resolver_),
|
||||
"name", info->capitalized_name,
|
||||
"memoize", memoization ? "memoizedIsInitialized = 0;" : "");
|
||||
} else {
|
||||
printer->Print(
|
||||
"for (int i = 0; i < get$name$Count(); i++) {\n"
|
||||
" if (!get$name$(i).isInitialized()) {\n"
|
||||
" $memoize$\n"
|
||||
" return false;\n"
|
||||
" }\n"
|
||||
"}\n",
|
||||
"type", name_resolver_->GetImmutableClassName(
|
||||
field->message_type()),
|
||||
"name", info->capitalized_name,
|
||||
"memoize", memoization ? "memoizedIsInitialized = 0;" : "");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1440,7 +1476,7 @@ GenerateExtensionRegistrationCode(io::Printer* printer) {
|
||||
// ===================================================================
|
||||
void ImmutableMessageGenerator::
|
||||
GenerateParsingConstructor(io::Printer* printer) {
|
||||
scoped_array<const FieldDescriptor*> sorted_fields(
|
||||
google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
|
||||
SortFieldsByNumber(descriptor_));
|
||||
|
||||
printer->Print(
|
||||
@ -1596,9 +1632,18 @@ GenerateParsingConstructor(io::Printer* printer) {
|
||||
printer->Print("this.unknownFields = unknownFields.build();\n");
|
||||
}
|
||||
|
||||
// Make extensions immutable.
|
||||
printer->Print(
|
||||
"makeExtensionsImmutable();\n");
|
||||
if (!HasDescriptorMethods(descriptor_)) {
|
||||
// LITE runtime uses a static method to reduce method count.
|
||||
if (descriptor_->extension_range_count() > 0) {
|
||||
// Make extensions immutable.
|
||||
printer->Print(
|
||||
"makeExtensionsImmutable(extensions);\n");
|
||||
}
|
||||
} else {
|
||||
// Make extensions immutable.
|
||||
printer->Print(
|
||||
"makeExtensionsImmutable();\n");
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Outdent();
|
||||
|
@ -75,7 +75,7 @@ class TestGenerator : public CodeGenerator {
|
||||
|
||||
void TryInsert(const string& filename, const string& insertion_point,
|
||||
GeneratorContext* context) const {
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
context->OpenForInsert(filename, insertion_point));
|
||||
io::Printer printer(output.get(), '$');
|
||||
printer.Print("// inserted $name$\n", "name", insertion_point);
|
||||
|
@ -68,8 +68,8 @@ void SharedCodeGenerator::Generate(GeneratorContext* context,
|
||||
string classname = name_resolver_->GetDescriptorClassName(file_);
|
||||
string filename = package_dir + classname + ".java";
|
||||
file_list->push_back(filename);
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
|
||||
scoped_ptr<io::Printer> printer(new io::Printer(output.get(), '$'));
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
|
||||
google::protobuf::scoped_ptr<io::Printer> printer(new io::Printer(output.get(), '$'));
|
||||
|
||||
printer->Print(
|
||||
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
||||
|
@ -80,7 +80,7 @@ class SharedCodeGenerator {
|
||||
// improve compatibility with version 1 of protocol buffers.
|
||||
bool ShouldIncludeDependency(const FileDescriptor* descriptor);
|
||||
|
||||
scoped_ptr<ClassNameResolver> name_resolver_;
|
||||
google::protobuf::scoped_ptr<ClassNameResolver> name_resolver_;
|
||||
const FileDescriptor* file_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SharedCodeGenerator);
|
||||
};
|
||||
|
@ -160,7 +160,7 @@ bool MockCodeGenerator::Generate(
|
||||
|
||||
for (int i = 0; i < insert_into.size(); i++) {
|
||||
{
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(context->OpenForInsert(
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->OpenForInsert(
|
||||
GetOutputFileName(insert_into[i], file), kFirstInsertionPointName));
|
||||
io::Printer printer(output.get(), '$');
|
||||
printer.PrintRaw(GetOutputFileContent(name_, "first_insert",
|
||||
@ -172,7 +172,7 @@ bool MockCodeGenerator::Generate(
|
||||
}
|
||||
|
||||
{
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
context->OpenForInsert(GetOutputFileName(insert_into[i], file),
|
||||
kSecondInsertionPointName));
|
||||
io::Printer printer(output.get(), '$');
|
||||
@ -185,7 +185,7 @@ bool MockCodeGenerator::Generate(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
context->Open(GetOutputFileName(name_, file)));
|
||||
|
||||
io::Printer printer(output.get(), '$');
|
||||
|
@ -178,9 +178,9 @@ class ParserTest : public testing::Test {
|
||||
MockErrorCollector error_collector_;
|
||||
DescriptorPool pool_;
|
||||
|
||||
scoped_ptr<io::ZeroCopyInputStream> raw_input_;
|
||||
scoped_ptr<io::Tokenizer> input_;
|
||||
scoped_ptr<Parser> parser_;
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyInputStream> raw_input_;
|
||||
google::protobuf::scoped_ptr<io::Tokenizer> input_;
|
||||
google::protobuf::scoped_ptr<Parser> parser_;
|
||||
bool require_syntax_identifier_;
|
||||
};
|
||||
|
||||
|
@ -48,15 +48,13 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, proto_file_),
|
||||
};
|
||||
CodeGeneratorRequest_reflection_ =
|
||||
new ::google::protobuf::internal::GeneratedMessageReflection(
|
||||
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
|
||||
CodeGeneratorRequest_descriptor_,
|
||||
CodeGeneratorRequest::default_instance_,
|
||||
CodeGeneratorRequest_offsets_,
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _has_bits_[0]),
|
||||
-1,
|
||||
-1,
|
||||
::google::protobuf::DescriptorPool::generated_pool(),
|
||||
::google::protobuf::MessageFactory::generated_factory(),
|
||||
sizeof(CodeGeneratorRequest),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _internal_metadata_));
|
||||
CodeGeneratorResponse_descriptor_ = file->message_type(1);
|
||||
@ -65,15 +63,13 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, file_),
|
||||
};
|
||||
CodeGeneratorResponse_reflection_ =
|
||||
new ::google::protobuf::internal::GeneratedMessageReflection(
|
||||
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
|
||||
CodeGeneratorResponse_descriptor_,
|
||||
CodeGeneratorResponse::default_instance_,
|
||||
CodeGeneratorResponse_offsets_,
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _has_bits_[0]),
|
||||
-1,
|
||||
-1,
|
||||
::google::protobuf::DescriptorPool::generated_pool(),
|
||||
::google::protobuf::MessageFactory::generated_factory(),
|
||||
sizeof(CodeGeneratorResponse),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _internal_metadata_));
|
||||
CodeGeneratorResponse_File_descriptor_ = CodeGeneratorResponse_descriptor_->nested_type(0);
|
||||
@ -83,15 +79,13 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, content_),
|
||||
};
|
||||
CodeGeneratorResponse_File_reflection_ =
|
||||
new ::google::protobuf::internal::GeneratedMessageReflection(
|
||||
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
|
||||
CodeGeneratorResponse_File_descriptor_,
|
||||
CodeGeneratorResponse_File::default_instance_,
|
||||
CodeGeneratorResponse_File_offsets_,
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _has_bits_[0]),
|
||||
-1,
|
||||
-1,
|
||||
::google::protobuf::DescriptorPool::generated_pool(),
|
||||
::google::protobuf::MessageFactory::generated_factory(),
|
||||
sizeof(CodeGeneratorResponse_File),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _internal_metadata_));
|
||||
}
|
||||
@ -107,11 +101,11 @@ inline void protobuf_AssignDescriptorsOnce() {
|
||||
void protobuf_RegisterTypes(const ::std::string&) {
|
||||
protobuf_AssignDescriptorsOnce();
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
|
||||
CodeGeneratorRequest_descriptor_, &CodeGeneratorRequest::default_instance());
|
||||
CodeGeneratorRequest_descriptor_, &CodeGeneratorRequest::default_instance());
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
|
||||
CodeGeneratorResponse_descriptor_, &CodeGeneratorResponse::default_instance());
|
||||
CodeGeneratorResponse_descriptor_, &CodeGeneratorResponse::default_instance());
|
||||
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
|
||||
CodeGeneratorResponse_File_descriptor_, &CodeGeneratorResponse_File::default_instance());
|
||||
CodeGeneratorResponse_File_descriptor_, &CodeGeneratorResponse_File::default_instance());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -163,6 +157,16 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto
|
||||
}
|
||||
} static_descriptor_initializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto_;
|
||||
|
||||
namespace {
|
||||
|
||||
static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
|
||||
static void MergeFromFail(int line) {
|
||||
GOOGLE_CHECK(false) << __FILE__ << ":" << line;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
#ifndef _MSC_VER
|
||||
@ -177,16 +181,6 @@ CodeGeneratorRequest::CodeGeneratorRequest()
|
||||
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest)
|
||||
}
|
||||
|
||||
CodeGeneratorRequest::CodeGeneratorRequest(::google::protobuf::Arena* arena)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(arena),
|
||||
file_to_generate_(arena),
|
||||
proto_file_(arena) {
|
||||
SharedCtor();
|
||||
RegisterArenaDtor(arena);
|
||||
// @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorRequest)
|
||||
}
|
||||
|
||||
void CodeGeneratorRequest::InitAsDefaultInstance() {
|
||||
}
|
||||
|
||||
@ -211,21 +205,11 @@ CodeGeneratorRequest::~CodeGeneratorRequest() {
|
||||
}
|
||||
|
||||
void CodeGeneratorRequest::SharedDtor() {
|
||||
if (GetArenaNoVirtual() != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
parameter_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
parameter_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
if (this != default_instance_) {
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGeneratorRequest::ArenaDtor(void* object) {
|
||||
CodeGeneratorRequest* _this = reinterpret_cast< CodeGeneratorRequest* >(object);
|
||||
(void)_this;
|
||||
}
|
||||
void CodeGeneratorRequest::RegisterArenaDtor(::google::protobuf::Arena* arena) {
|
||||
}
|
||||
void CodeGeneratorRequest::SetCachedSize(int size) const {
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = size;
|
||||
@ -244,12 +228,16 @@ const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
|
||||
CodeGeneratorRequest* CodeGeneratorRequest::default_instance_ = NULL;
|
||||
|
||||
CodeGeneratorRequest* CodeGeneratorRequest::New(::google::protobuf::Arena* arena) const {
|
||||
return ::google::protobuf::Arena::CreateMessage<CodeGeneratorRequest>(arena);
|
||||
CodeGeneratorRequest* n = new CodeGeneratorRequest;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void CodeGeneratorRequest::Clear() {
|
||||
if (has_parameter()) {
|
||||
parameter_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
file_to_generate_.Clear();
|
||||
proto_file_.Clear();
|
||||
@ -365,7 +353,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
|
||||
}
|
||||
|
||||
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
||||
for (int i = 0; i < this->proto_file_size(); i++) {
|
||||
for (unsigned int i = 0, n = this->proto_file_size(); i < n; i++) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
||||
15, this->proto_file(i), output);
|
||||
}
|
||||
@ -402,7 +390,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
|
||||
}
|
||||
|
||||
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
||||
for (int i = 0; i < this->proto_file_size(); i++) {
|
||||
for (unsigned int i = 0, n = this->proto_file_size(); i < n; i++) {
|
||||
target = ::google::protobuf::internal::WireFormatLite::
|
||||
WriteMessageNoVirtualToArray(
|
||||
15, this->proto_file(i), target);
|
||||
@ -453,7 +441,7 @@ int CodeGeneratorRequest::ByteSize() const {
|
||||
}
|
||||
|
||||
void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
GOOGLE_CHECK_NE(&from, this);
|
||||
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
|
||||
const CodeGeneratorRequest* source =
|
||||
::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorRequest*>(
|
||||
&from);
|
||||
@ -465,12 +453,13 @@ void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
}
|
||||
|
||||
void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
|
||||
GOOGLE_CHECK_NE(&from, this);
|
||||
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
|
||||
file_to_generate_.MergeFrom(from.file_to_generate_);
|
||||
proto_file_.MergeFrom(from.proto_file_);
|
||||
if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
|
||||
if (from.has_parameter()) {
|
||||
set_parameter(from.parameter());
|
||||
set_has_parameter();
|
||||
parameter_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.parameter_);
|
||||
}
|
||||
}
|
||||
if (from._internal_metadata_.have_unknown_fields()) {
|
||||
@ -498,18 +487,6 @@ bool CodeGeneratorRequest::IsInitialized() const {
|
||||
|
||||
void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) {
|
||||
if (other == this) return;
|
||||
if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
CodeGeneratorRequest temp;
|
||||
temp.MergeFrom(*this);
|
||||
CopyFrom(*other);
|
||||
other->CopyFrom(temp);
|
||||
}
|
||||
}
|
||||
void CodeGeneratorRequest::UnsafeArenaSwap(CodeGeneratorRequest* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
|
||||
InternalSwap(other);
|
||||
}
|
||||
void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
|
||||
@ -544,14 +521,6 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File()
|
||||
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
|
||||
}
|
||||
|
||||
CodeGeneratorResponse_File::CodeGeneratorResponse_File(::google::protobuf::Arena* arena)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(arena) {
|
||||
SharedCtor();
|
||||
RegisterArenaDtor(arena);
|
||||
// @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
|
||||
}
|
||||
|
||||
void CodeGeneratorResponse_File::InitAsDefaultInstance() {
|
||||
}
|
||||
|
||||
@ -578,23 +547,13 @@ CodeGeneratorResponse_File::~CodeGeneratorResponse_File() {
|
||||
}
|
||||
|
||||
void CodeGeneratorResponse_File::SharedDtor() {
|
||||
if (GetArenaNoVirtual() != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
insertion_point_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
content_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
insertion_point_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
content_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
if (this != default_instance_) {
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGeneratorResponse_File::ArenaDtor(void* object) {
|
||||
CodeGeneratorResponse_File* _this = reinterpret_cast< CodeGeneratorResponse_File* >(object);
|
||||
(void)_this;
|
||||
}
|
||||
void CodeGeneratorResponse_File::RegisterArenaDtor(::google::protobuf::Arena* arena) {
|
||||
}
|
||||
void CodeGeneratorResponse_File::SetCachedSize(int size) const {
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = size;
|
||||
@ -613,19 +572,23 @@ const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance()
|
||||
CodeGeneratorResponse_File* CodeGeneratorResponse_File::default_instance_ = NULL;
|
||||
|
||||
CodeGeneratorResponse_File* CodeGeneratorResponse_File::New(::google::protobuf::Arena* arena) const {
|
||||
return ::google::protobuf::Arena::CreateMessage<CodeGeneratorResponse_File>(arena);
|
||||
CodeGeneratorResponse_File* n = new CodeGeneratorResponse_File;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void CodeGeneratorResponse_File::Clear() {
|
||||
if (_has_bits_[0 / 32] & 7) {
|
||||
if (has_name()) {
|
||||
name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
if (has_insertion_point()) {
|
||||
insertion_point_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
if (has_content()) {
|
||||
content_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
}
|
||||
::memset(_has_bits_, 0, sizeof(_has_bits_));
|
||||
@ -838,7 +801,7 @@ int CodeGeneratorResponse_File::ByteSize() const {
|
||||
}
|
||||
|
||||
void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
GOOGLE_CHECK_NE(&from, this);
|
||||
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
|
||||
const CodeGeneratorResponse_File* source =
|
||||
::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorResponse_File*>(
|
||||
&from);
|
||||
@ -850,16 +813,19 @@ void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& fr
|
||||
}
|
||||
|
||||
void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
|
||||
GOOGLE_CHECK_NE(&from, this);
|
||||
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
|
||||
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
|
||||
if (from.has_name()) {
|
||||
set_name(from.name());
|
||||
set_has_name();
|
||||
name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
|
||||
}
|
||||
if (from.has_insertion_point()) {
|
||||
set_insertion_point(from.insertion_point());
|
||||
set_has_insertion_point();
|
||||
insertion_point_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.insertion_point_);
|
||||
}
|
||||
if (from.has_content()) {
|
||||
set_content(from.content());
|
||||
set_has_content();
|
||||
content_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.content_);
|
||||
}
|
||||
}
|
||||
if (from._internal_metadata_.have_unknown_fields()) {
|
||||
@ -886,18 +852,6 @@ bool CodeGeneratorResponse_File::IsInitialized() const {
|
||||
|
||||
void CodeGeneratorResponse_File::Swap(CodeGeneratorResponse_File* other) {
|
||||
if (other == this) return;
|
||||
if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
CodeGeneratorResponse_File temp;
|
||||
temp.MergeFrom(*this);
|
||||
CopyFrom(*other);
|
||||
other->CopyFrom(temp);
|
||||
}
|
||||
}
|
||||
void CodeGeneratorResponse_File::UnsafeArenaSwap(CodeGeneratorResponse_File* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
|
||||
InternalSwap(other);
|
||||
}
|
||||
void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) {
|
||||
@ -931,15 +885,6 @@ CodeGeneratorResponse::CodeGeneratorResponse()
|
||||
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse)
|
||||
}
|
||||
|
||||
CodeGeneratorResponse::CodeGeneratorResponse(::google::protobuf::Arena* arena)
|
||||
: ::google::protobuf::Message(),
|
||||
_internal_metadata_(arena),
|
||||
file_(arena) {
|
||||
SharedCtor();
|
||||
RegisterArenaDtor(arena);
|
||||
// @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse)
|
||||
}
|
||||
|
||||
void CodeGeneratorResponse::InitAsDefaultInstance() {
|
||||
}
|
||||
|
||||
@ -964,21 +909,11 @@ CodeGeneratorResponse::~CodeGeneratorResponse() {
|
||||
}
|
||||
|
||||
void CodeGeneratorResponse::SharedDtor() {
|
||||
if (GetArenaNoVirtual() != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
error_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
error_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
if (this != default_instance_) {
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGeneratorResponse::ArenaDtor(void* object) {
|
||||
CodeGeneratorResponse* _this = reinterpret_cast< CodeGeneratorResponse* >(object);
|
||||
(void)_this;
|
||||
}
|
||||
void CodeGeneratorResponse::RegisterArenaDtor(::google::protobuf::Arena* arena) {
|
||||
}
|
||||
void CodeGeneratorResponse::SetCachedSize(int size) const {
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
_cached_size_ = size;
|
||||
@ -997,12 +932,16 @@ const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
|
||||
CodeGeneratorResponse* CodeGeneratorResponse::default_instance_ = NULL;
|
||||
|
||||
CodeGeneratorResponse* CodeGeneratorResponse::New(::google::protobuf::Arena* arena) const {
|
||||
return ::google::protobuf::Arena::CreateMessage<CodeGeneratorResponse>(arena);
|
||||
CodeGeneratorResponse* n = new CodeGeneratorResponse;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void CodeGeneratorResponse::Clear() {
|
||||
if (has_error()) {
|
||||
error_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
file_.Clear();
|
||||
::memset(_has_bits_, 0, sizeof(_has_bits_));
|
||||
@ -1087,7 +1026,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
|
||||
}
|
||||
|
||||
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
||||
for (int i = 0; i < this->file_size(); i++) {
|
||||
for (unsigned int i = 0, n = this->file_size(); i < n; i++) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
||||
15, this->file(i), output);
|
||||
}
|
||||
@ -1114,7 +1053,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
|
||||
}
|
||||
|
||||
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
||||
for (int i = 0; i < this->file_size(); i++) {
|
||||
for (unsigned int i = 0, n = this->file_size(); i < n; i++) {
|
||||
target = ::google::protobuf::internal::WireFormatLite::
|
||||
WriteMessageNoVirtualToArray(
|
||||
15, this->file(i), target);
|
||||
@ -1158,7 +1097,7 @@ int CodeGeneratorResponse::ByteSize() const {
|
||||
}
|
||||
|
||||
void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
GOOGLE_CHECK_NE(&from, this);
|
||||
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
|
||||
const CodeGeneratorResponse* source =
|
||||
::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorResponse*>(
|
||||
&from);
|
||||
@ -1170,11 +1109,12 @@ void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
|
||||
}
|
||||
|
||||
void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
|
||||
GOOGLE_CHECK_NE(&from, this);
|
||||
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
|
||||
file_.MergeFrom(from.file_);
|
||||
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
|
||||
if (from.has_error()) {
|
||||
set_error(from.error());
|
||||
set_has_error();
|
||||
error_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.error_);
|
||||
}
|
||||
}
|
||||
if (from._internal_metadata_.have_unknown_fields()) {
|
||||
@ -1201,18 +1141,6 @@ bool CodeGeneratorResponse::IsInitialized() const {
|
||||
|
||||
void CodeGeneratorResponse::Swap(CodeGeneratorResponse* other) {
|
||||
if (other == this) return;
|
||||
if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
CodeGeneratorResponse temp;
|
||||
temp.MergeFrom(*this);
|
||||
CopyFrom(*other);
|
||||
other->CopyFrom(temp);
|
||||
}
|
||||
}
|
||||
void CodeGeneratorResponse::UnsafeArenaSwap(CodeGeneratorResponse* other) {
|
||||
if (other == this) return;
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
|
||||
InternalSwap(other);
|
||||
}
|
||||
void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
|
||||
|
@ -5,7 +5,6 @@
|
||||
#define PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
@ -66,14 +65,9 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
|
||||
return _internal_metadata_.mutable_unknown_fields();
|
||||
}
|
||||
|
||||
inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
|
||||
inline void* GetMaybeArenaPointer() const {
|
||||
return MaybeArenaPtr();
|
||||
}
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const CodeGeneratorRequest& default_instance();
|
||||
|
||||
void UnsafeArenaSwap(CodeGeneratorRequest* other);
|
||||
void Swap(CodeGeneratorRequest* other);
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
@ -100,11 +94,6 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const;
|
||||
void InternalSwap(CodeGeneratorRequest* other);
|
||||
protected:
|
||||
explicit CodeGeneratorRequest(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return _internal_metadata_.arena();
|
||||
@ -147,9 +136,6 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
|
||||
inline ::std::string* mutable_parameter();
|
||||
inline ::std::string* release_parameter();
|
||||
inline void set_allocated_parameter(::std::string* parameter);
|
||||
inline ::std::string* unsafe_arena_release_parameter();
|
||||
inline void unsafe_arena_set_allocated_parameter(
|
||||
::std::string* parameter);
|
||||
|
||||
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
||||
inline int proto_file_size() const;
|
||||
@ -169,9 +155,6 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
|
||||
inline void clear_has_parameter();
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
friend class ::google::protobuf::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
::google::protobuf::uint32 _has_bits_[1];
|
||||
mutable int _cached_size_;
|
||||
::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
|
||||
@ -206,14 +189,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
|
||||
return _internal_metadata_.mutable_unknown_fields();
|
||||
}
|
||||
|
||||
inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
|
||||
inline void* GetMaybeArenaPointer() const {
|
||||
return MaybeArenaPtr();
|
||||
}
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const CodeGeneratorResponse_File& default_instance();
|
||||
|
||||
void UnsafeArenaSwap(CodeGeneratorResponse_File* other);
|
||||
void Swap(CodeGeneratorResponse_File* other);
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
@ -240,11 +218,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const;
|
||||
void InternalSwap(CodeGeneratorResponse_File* other);
|
||||
protected:
|
||||
explicit CodeGeneratorResponse_File(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return _internal_metadata_.arena();
|
||||
@ -271,9 +244,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
|
||||
inline ::std::string* mutable_name();
|
||||
inline ::std::string* release_name();
|
||||
inline void set_allocated_name(::std::string* name);
|
||||
inline ::std::string* unsafe_arena_release_name();
|
||||
inline void unsafe_arena_set_allocated_name(
|
||||
::std::string* name);
|
||||
|
||||
// optional string insertion_point = 2;
|
||||
inline bool has_insertion_point() const;
|
||||
@ -286,9 +256,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
|
||||
inline ::std::string* mutable_insertion_point();
|
||||
inline ::std::string* release_insertion_point();
|
||||
inline void set_allocated_insertion_point(::std::string* insertion_point);
|
||||
inline ::std::string* unsafe_arena_release_insertion_point();
|
||||
inline void unsafe_arena_set_allocated_insertion_point(
|
||||
::std::string* insertion_point);
|
||||
|
||||
// optional string content = 15;
|
||||
inline bool has_content() const;
|
||||
@ -301,9 +268,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
|
||||
inline ::std::string* mutable_content();
|
||||
inline ::std::string* release_content();
|
||||
inline void set_allocated_content(::std::string* content);
|
||||
inline ::std::string* unsafe_arena_release_content();
|
||||
inline void unsafe_arena_set_allocated_content(
|
||||
::std::string* content);
|
||||
|
||||
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
|
||||
private:
|
||||
@ -315,9 +279,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
|
||||
inline void clear_has_content();
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
friend class ::google::protobuf::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
::google::protobuf::uint32 _has_bits_[1];
|
||||
mutable int _cached_size_;
|
||||
::google::protobuf::internal::ArenaStringPtr name_;
|
||||
@ -352,14 +313,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
|
||||
return _internal_metadata_.mutable_unknown_fields();
|
||||
}
|
||||
|
||||
inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
|
||||
inline void* GetMaybeArenaPointer() const {
|
||||
return MaybeArenaPtr();
|
||||
}
|
||||
static const ::google::protobuf::Descriptor* descriptor();
|
||||
static const CodeGeneratorResponse& default_instance();
|
||||
|
||||
void UnsafeArenaSwap(CodeGeneratorResponse* other);
|
||||
void Swap(CodeGeneratorResponse* other);
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
@ -386,11 +342,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
|
||||
void SharedDtor();
|
||||
void SetCachedSize(int size) const;
|
||||
void InternalSwap(CodeGeneratorResponse* other);
|
||||
protected:
|
||||
explicit CodeGeneratorResponse(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
static void ArenaDtor(void* object);
|
||||
inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
|
||||
private:
|
||||
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
|
||||
return _internal_metadata_.arena();
|
||||
@ -419,9 +370,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
|
||||
inline ::std::string* mutable_error();
|
||||
inline ::std::string* release_error();
|
||||
inline void set_allocated_error(::std::string* error);
|
||||
inline ::std::string* unsafe_arena_release_error();
|
||||
inline void unsafe_arena_set_allocated_error(
|
||||
::std::string* error);
|
||||
|
||||
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
|
||||
inline int file_size() const;
|
||||
@ -441,9 +389,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
|
||||
inline void clear_has_error();
|
||||
|
||||
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
|
||||
friend class ::google::protobuf::Arena;
|
||||
typedef void InternalArenaConstructable_;
|
||||
typedef void DestructorSkippable_;
|
||||
::google::protobuf::uint32 _has_bits_[1];
|
||||
mutable int _cached_size_;
|
||||
::google::protobuf::internal::ArenaStringPtr error_;
|
||||
@ -527,45 +472,37 @@ inline void CodeGeneratorRequest::clear_has_parameter() {
|
||||
_has_bits_[0] &= ~0x00000002u;
|
||||
}
|
||||
inline void CodeGeneratorRequest::clear_parameter() {
|
||||
parameter_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
clear_has_parameter();
|
||||
}
|
||||
inline const ::std::string& CodeGeneratorRequest::parameter() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
|
||||
return parameter_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
return parameter_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
|
||||
set_has_parameter();
|
||||
parameter_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
|
||||
parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
|
||||
}
|
||||
inline void CodeGeneratorRequest::set_parameter(const char* value) {
|
||||
set_has_parameter();
|
||||
parameter_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
|
||||
GetArenaNoVirtual());
|
||||
parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
|
||||
}
|
||||
inline void CodeGeneratorRequest::set_parameter(const char* value,
|
||||
size_t size) {
|
||||
inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
|
||||
set_has_parameter();
|
||||
parameter_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
|
||||
reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
|
||||
parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter)
|
||||
}
|
||||
inline ::std::string* CodeGeneratorRequest::mutable_parameter() {
|
||||
set_has_parameter();
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter)
|
||||
return parameter_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* CodeGeneratorRequest::release_parameter() {
|
||||
clear_has_parameter();
|
||||
return parameter_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline ::std::string* CodeGeneratorRequest::unsafe_arena_release_parameter() {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
clear_has_parameter();
|
||||
return parameter_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
|
||||
if (parameter != NULL) {
|
||||
@ -573,21 +510,7 @@ inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* paramet
|
||||
} else {
|
||||
clear_has_parameter();
|
||||
}
|
||||
parameter_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter,
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
|
||||
}
|
||||
inline void CodeGeneratorRequest::unsafe_arena_set_allocated_parameter(
|
||||
::std::string* parameter) {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
if (parameter != NULL) {
|
||||
set_has_parameter();
|
||||
} else {
|
||||
clear_has_parameter();
|
||||
}
|
||||
set_has_parameter();
|
||||
parameter_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
parameter, GetArenaNoVirtual());
|
||||
parameter_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter);
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
|
||||
}
|
||||
|
||||
@ -636,45 +559,37 @@ inline void CodeGeneratorResponse_File::clear_has_name() {
|
||||
_has_bits_[0] &= ~0x00000001u;
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::clear_name() {
|
||||
name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
clear_has_name();
|
||||
}
|
||||
inline const ::std::string& CodeGeneratorResponse_File::name() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
|
||||
return name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
|
||||
set_has_name();
|
||||
name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
|
||||
name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_name(const char* value) {
|
||||
set_has_name();
|
||||
name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
|
||||
GetArenaNoVirtual());
|
||||
name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_name(const char* value,
|
||||
size_t size) {
|
||||
inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
|
||||
set_has_name();
|
||||
name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
|
||||
reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
|
||||
name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name)
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse_File::mutable_name() {
|
||||
set_has_name();
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name)
|
||||
return name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse_File::release_name() {
|
||||
clear_has_name();
|
||||
return name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse_File::unsafe_arena_release_name() {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
clear_has_name();
|
||||
return name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
|
||||
if (name != NULL) {
|
||||
@ -682,21 +597,7 @@ inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name)
|
||||
} else {
|
||||
clear_has_name();
|
||||
}
|
||||
name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name,
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_name(
|
||||
::std::string* name) {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
if (name != NULL) {
|
||||
set_has_name();
|
||||
} else {
|
||||
clear_has_name();
|
||||
}
|
||||
set_has_name();
|
||||
name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
name, GetArenaNoVirtual());
|
||||
name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
|
||||
}
|
||||
|
||||
@ -711,45 +612,37 @@ inline void CodeGeneratorResponse_File::clear_has_insertion_point() {
|
||||
_has_bits_[0] &= ~0x00000002u;
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::clear_insertion_point() {
|
||||
insertion_point_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
clear_has_insertion_point();
|
||||
}
|
||||
inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
|
||||
return insertion_point_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
return insertion_point_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
|
||||
set_has_insertion_point();
|
||||
insertion_point_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
|
||||
insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
|
||||
set_has_insertion_point();
|
||||
insertion_point_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
|
||||
GetArenaNoVirtual());
|
||||
insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_insertion_point(const char* value,
|
||||
size_t size) {
|
||||
inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
|
||||
set_has_insertion_point();
|
||||
insertion_point_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
|
||||
reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
|
||||
insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
|
||||
set_has_insertion_point();
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
|
||||
return insertion_point_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
|
||||
clear_has_insertion_point();
|
||||
return insertion_point_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse_File::unsafe_arena_release_insertion_point() {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
clear_has_insertion_point();
|
||||
return insertion_point_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
|
||||
if (insertion_point != NULL) {
|
||||
@ -757,21 +650,7 @@ inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::str
|
||||
} else {
|
||||
clear_has_insertion_point();
|
||||
}
|
||||
insertion_point_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point,
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_insertion_point(
|
||||
::std::string* insertion_point) {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
if (insertion_point != NULL) {
|
||||
set_has_insertion_point();
|
||||
} else {
|
||||
clear_has_insertion_point();
|
||||
}
|
||||
set_has_insertion_point();
|
||||
insertion_point_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
insertion_point, GetArenaNoVirtual());
|
||||
insertion_point_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point);
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
|
||||
}
|
||||
|
||||
@ -786,45 +665,37 @@ inline void CodeGeneratorResponse_File::clear_has_content() {
|
||||
_has_bits_[0] &= ~0x00000004u;
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::clear_content() {
|
||||
content_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
clear_has_content();
|
||||
}
|
||||
inline const ::std::string& CodeGeneratorResponse_File::content() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
|
||||
return content_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
return content_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
|
||||
set_has_content();
|
||||
content_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
|
||||
content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_content(const char* value) {
|
||||
set_has_content();
|
||||
content_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
|
||||
GetArenaNoVirtual());
|
||||
content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_content(const char* value,
|
||||
size_t size) {
|
||||
inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
|
||||
set_has_content();
|
||||
content_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
|
||||
reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
|
||||
content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content)
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
|
||||
set_has_content();
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content)
|
||||
return content_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse_File::release_content() {
|
||||
clear_has_content();
|
||||
return content_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse_File::unsafe_arena_release_content() {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
clear_has_content();
|
||||
return content_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
|
||||
if (content != NULL) {
|
||||
@ -832,21 +703,7 @@ inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* con
|
||||
} else {
|
||||
clear_has_content();
|
||||
}
|
||||
content_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content,
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
|
||||
}
|
||||
inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_content(
|
||||
::std::string* content) {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
if (content != NULL) {
|
||||
set_has_content();
|
||||
} else {
|
||||
clear_has_content();
|
||||
}
|
||||
set_has_content();
|
||||
content_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
content, GetArenaNoVirtual());
|
||||
content_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content);
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
|
||||
}
|
||||
|
||||
@ -865,45 +722,37 @@ inline void CodeGeneratorResponse::clear_has_error() {
|
||||
_has_bits_[0] &= ~0x00000001u;
|
||||
}
|
||||
inline void CodeGeneratorResponse::clear_error() {
|
||||
error_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
clear_has_error();
|
||||
}
|
||||
inline const ::std::string& CodeGeneratorResponse::error() const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
|
||||
return error_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
return error_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void CodeGeneratorResponse::set_error(const ::std::string& value) {
|
||||
set_has_error();
|
||||
error_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
|
||||
error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
|
||||
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
|
||||
}
|
||||
inline void CodeGeneratorResponse::set_error(const char* value) {
|
||||
set_has_error();
|
||||
error_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
|
||||
GetArenaNoVirtual());
|
||||
error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
|
||||
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
|
||||
}
|
||||
inline void CodeGeneratorResponse::set_error(const char* value,
|
||||
size_t size) {
|
||||
inline void CodeGeneratorResponse::set_error(const char* value, size_t size) {
|
||||
set_has_error();
|
||||
error_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
|
||||
reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
|
||||
error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
::std::string(reinterpret_cast<const char*>(value), size));
|
||||
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error)
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse::mutable_error() {
|
||||
set_has_error();
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error)
|
||||
return error_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse::release_error() {
|
||||
clear_has_error();
|
||||
return error_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
|
||||
}
|
||||
inline ::std::string* CodeGeneratorResponse::unsafe_arena_release_error() {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
clear_has_error();
|
||||
return error_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
GetArenaNoVirtual());
|
||||
return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
|
||||
}
|
||||
inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
|
||||
if (error != NULL) {
|
||||
@ -911,21 +760,7 @@ inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
|
||||
} else {
|
||||
clear_has_error();
|
||||
}
|
||||
error_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error,
|
||||
GetArenaNoVirtual());
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
|
||||
}
|
||||
inline void CodeGeneratorResponse::unsafe_arena_set_allocated_error(
|
||||
::std::string* error) {
|
||||
GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
|
||||
if (error != NULL) {
|
||||
set_has_error();
|
||||
} else {
|
||||
clear_has_error();
|
||||
}
|
||||
set_has_error();
|
||||
error_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
|
||||
error, GetArenaNoVirtual());
|
||||
error_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error);
|
||||
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
|
||||
}
|
||||
|
||||
|
@ -73,41 +73,6 @@ namespace python {
|
||||
|
||||
namespace {
|
||||
|
||||
const char* const kKeywordList[] = {
|
||||
"and", "as", "break", "class", "continue", "def", "elif", "else", "except",
|
||||
"False", "for", "from", "if", "import", "not", "or", "raise", "return",
|
||||
"True", "try", "with", "while", "yield"
|
||||
};
|
||||
|
||||
hash_set<string> MakeKeywordsMap() {
|
||||
hash_set<string> result;
|
||||
for (int i = 0; i < GOOGLE_ARRAYSIZE(kKeywordList); ++i) {
|
||||
result.insert(kKeywordList[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
hash_set<string>* keywords_ = NULL;
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(keywords_once_);
|
||||
|
||||
void InitKeywords() {
|
||||
keywords_ = new hash_set<string>();
|
||||
*keywords_ = MakeKeywordsMap();
|
||||
}
|
||||
|
||||
hash_set<string>& GetKeywords() {
|
||||
::google::protobuf::GoogleOnceInit(&keywords_once_, &InitKeywords);
|
||||
return *keywords_;
|
||||
}
|
||||
|
||||
string FieldName(const FieldDescriptor& field) {
|
||||
string result = field.name();
|
||||
if (GetKeywords().count(result) > 0) {
|
||||
result.append("_");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns a copy of |filename| with any trailing ".protodevel" or ".proto
|
||||
// suffix stripped.
|
||||
// TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc.
|
||||
@ -343,7 +308,7 @@ bool Generator::Generate(const FileDescriptor* file,
|
||||
fdp.SerializeToString(&file_descriptor_serialized_);
|
||||
|
||||
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
|
||||
GOOGLE_CHECK(output.get());
|
||||
io::Printer printer(output.get(), '$');
|
||||
printer_ = &printer;
|
||||
@ -531,7 +496,7 @@ void Generator::PrintTopLevelExtensions() const {
|
||||
printer_->Print("$constant_name$ = $number$\n",
|
||||
"constant_name", constant_name,
|
||||
"number", SimpleItoa(extension_field.number()));
|
||||
printer_->Print("$name$ = ", "name", FieldName(extension_field));
|
||||
printer_->Print("$name$ = ", "name", extension_field.name());
|
||||
PrintFieldDescriptor(extension_field, is_extension);
|
||||
printer_->Print("\n");
|
||||
}
|
||||
@ -878,7 +843,7 @@ void Generator::AddExtensionToFileDescriptor(
|
||||
const FieldDescriptor& descriptor) const {
|
||||
map<string, string> m;
|
||||
m["descriptor_name"] = kDescriptorKey;
|
||||
m["field_name"] = FieldName(descriptor);
|
||||
m["field_name"] = descriptor.name();
|
||||
const char file_descriptor_template[] =
|
||||
"$descriptor_name$.extensions_by_name['$field_name$'] = "
|
||||
"$field_name$\n";
|
||||
@ -931,12 +896,12 @@ string Generator::FieldReferencingExpression(
|
||||
GOOGLE_CHECK_EQ(field.file(), file_) << field.file()->name() << " vs. "
|
||||
<< file_->name();
|
||||
if (!containing_type) {
|
||||
return FieldName(field);
|
||||
return field.name();
|
||||
}
|
||||
return strings::Substitute(
|
||||
"$0.$1['$2']",
|
||||
ModuleLevelDescriptorName(*containing_type),
|
||||
python_dict_name, FieldName(field));
|
||||
python_dict_name, field.name());
|
||||
}
|
||||
|
||||
// Prints containing_type for nested descriptors or enum descriptors.
|
||||
@ -1065,7 +1030,7 @@ void Generator::PrintFieldDescriptor(
|
||||
string options_string;
|
||||
field.options().SerializeToString(&options_string);
|
||||
map<string, string> m;
|
||||
m["name"] = FieldName(field);
|
||||
m["name"] = field.name();
|
||||
m["full_name"] = field.full_name();
|
||||
m["index"] = SimpleItoa(field.index());
|
||||
m["number"] = SimpleItoa(field.number());
|
||||
@ -1285,7 +1250,7 @@ void Generator::FixOptionsForField(
|
||||
if (field.is_extension()) {
|
||||
if (field.extension_scope() == NULL) {
|
||||
// Top level extensions.
|
||||
field_name = FieldName(field);
|
||||
field_name = field.name();
|
||||
} else {
|
||||
field_name = FieldReferencingExpression(
|
||||
field.extension_scope(), field, "extensions_by_name");
|
||||
|
@ -72,7 +72,7 @@ class TestGenerator : public CodeGenerator {
|
||||
|
||||
void TryInsert(const string& filename, const string& insertion_point,
|
||||
GeneratorContext* context) const {
|
||||
scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
context->OpenForInsert(filename, insertion_point));
|
||||
io::Printer printer(output.get(), '$');
|
||||
printer.Print("// inserted $name$\n", "name", insertion_point);
|
||||
|
@ -1617,6 +1617,10 @@ bool DescriptorPool::TryFindExtensionInFallbackDatabase(
|
||||
|
||||
// ===================================================================
|
||||
|
||||
bool FieldDescriptor::is_map() const {
|
||||
return type() == TYPE_MESSAGE && message_type()->options().map_entry();
|
||||
}
|
||||
|
||||
string FieldDescriptor::DefaultValueAsString(bool quote_string_type) const {
|
||||
GOOGLE_CHECK(has_default_value()) << "No default value";
|
||||
switch (cpp_type()) {
|
||||
@ -2184,9 +2188,7 @@ void FieldDescriptor::DebugString(int depth,
|
||||
string field_type;
|
||||
|
||||
// Special case map fields.
|
||||
bool is_map = false;
|
||||
if (type() == TYPE_MESSAGE && message_type()->options().map_entry()) {
|
||||
is_map = true;
|
||||
if (is_map()) {
|
||||
strings::SubstituteAndAppend(
|
||||
&field_type, "map<$0, $1>",
|
||||
message_type()->field(0)->FieldTypeNameDebugString(),
|
||||
@ -2196,7 +2198,7 @@ void FieldDescriptor::DebugString(int depth,
|
||||
}
|
||||
|
||||
string label;
|
||||
if (print_label_flag == PRINT_LABEL && !is_map) {
|
||||
if (print_label_flag == PRINT_LABEL && !is_map()) {
|
||||
label = kLabelToName[this->label()];
|
||||
label.push_back(' ');
|
||||
}
|
||||
@ -4964,8 +4966,7 @@ void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field,
|
||||
}
|
||||
|
||||
// Validate map types.
|
||||
if (field->type() == FieldDescriptor::TYPE_MESSAGE &&
|
||||
field->message_type()->options().map_entry()) {
|
||||
if (field->is_map()) {
|
||||
if (!ValidateMapEntry(field, proto)) {
|
||||
AddError(field->full_name(), proto,
|
||||
DescriptorPool::ErrorCollector::OTHER,
|
||||
|
@ -117,8 +117,6 @@ struct SourceLocation {
|
||||
int end_column;
|
||||
|
||||
// Doc comments found at the source location.
|
||||
// TODO(kenton): Maybe this struct should have been named SourceInfo or
|
||||
// something instead. Oh well.
|
||||
string leading_comments;
|
||||
string trailing_comments;
|
||||
};
|
||||
@ -477,6 +475,8 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
|
||||
// IsTypePackable(type())
|
||||
bool is_packed() const; // shorthand for is_packable() &&
|
||||
// options().packed()
|
||||
bool is_map() const; // shorthand for type() == TYPE_MESSAGE &&
|
||||
// message_type()->options().map_entry()
|
||||
|
||||
// Index of this field within the message's field array, or the file or
|
||||
// extension scope's extensions array.
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -340,6 +340,11 @@ message FileOptions {
|
||||
optional bool deprecated = 23 [default=false];
|
||||
|
||||
|
||||
// Enables the use of arenas for the proto messages in this file. This applies
|
||||
// only to generated classes for C++.
|
||||
optional bool cc_enable_arenas = 31 [default=false];
|
||||
|
||||
|
||||
// The parser stores options it doesn't recognize here. See above.
|
||||
repeated UninterpretedOption uninterpreted_option = 999;
|
||||
|
||||
|
@ -415,6 +415,11 @@ class DescriptorTest : public testing::Test {
|
||||
// required string quux = 6;
|
||||
// }
|
||||
//
|
||||
// // in "map.proto"
|
||||
// message TestMessage3 {
|
||||
// map<int32, int32> map_int32_int32 = 1;
|
||||
// }
|
||||
//
|
||||
// We cheat and use TestForeign as the type for qux rather than create
|
||||
// an actual nested type.
|
||||
//
|
||||
@ -462,6 +467,24 @@ class DescriptorTest : public testing::Test {
|
||||
FieldDescriptorProto::LABEL_REQUIRED,
|
||||
FieldDescriptorProto::TYPE_STRING);
|
||||
|
||||
FileDescriptorProto map_file;
|
||||
map_file.set_name("map.proto");
|
||||
DescriptorProto* message3 = AddMessage(&map_file, "TestMessage3");
|
||||
|
||||
DescriptorProto* entry = AddNestedMessage(message3, "MapInt32Int32Entry");
|
||||
AddField(entry, "key", 1,
|
||||
FieldDescriptorProto::LABEL_OPTIONAL,
|
||||
FieldDescriptorProto::TYPE_INT32);
|
||||
AddField(entry, "value", 2,
|
||||
FieldDescriptorProto::LABEL_OPTIONAL,
|
||||
FieldDescriptorProto::TYPE_INT32);
|
||||
entry->mutable_options()->set_map_entry(true);
|
||||
|
||||
AddField(message3, "map_int32_int32", 1,
|
||||
FieldDescriptorProto::LABEL_REPEATED,
|
||||
FieldDescriptorProto::TYPE_MESSAGE)
|
||||
->set_type_name("MapInt32Int32Entry");
|
||||
|
||||
// Build the descriptors and get the pointers.
|
||||
foo_file_ = pool_.BuildFile(foo_file);
|
||||
ASSERT_TRUE(foo_file_ != NULL);
|
||||
@ -469,6 +492,9 @@ class DescriptorTest : public testing::Test {
|
||||
bar_file_ = pool_.BuildFile(bar_file);
|
||||
ASSERT_TRUE(bar_file_ != NULL);
|
||||
|
||||
map_file_ = pool_.BuildFile(map_file);
|
||||
ASSERT_TRUE(map_file_ != NULL);
|
||||
|
||||
ASSERT_EQ(1, foo_file_->enum_type_count());
|
||||
enum_ = foo_file_->enum_type(0);
|
||||
|
||||
@ -489,15 +515,23 @@ class DescriptorTest : public testing::Test {
|
||||
foo2_ = message2_->field(0);
|
||||
bar2_ = message2_->field(1);
|
||||
quux2_ = message2_->field(2);
|
||||
|
||||
ASSERT_EQ(1, map_file_->message_type_count());
|
||||
message3_ = map_file_->message_type(0);
|
||||
|
||||
ASSERT_EQ(1, message3_->field_count());
|
||||
map_ = message3_->field(0);
|
||||
}
|
||||
|
||||
DescriptorPool pool_;
|
||||
|
||||
const FileDescriptor* foo_file_;
|
||||
const FileDescriptor* bar_file_;
|
||||
const FileDescriptor* map_file_;
|
||||
|
||||
const Descriptor* message_;
|
||||
const Descriptor* message2_;
|
||||
const Descriptor* message3_;
|
||||
const Descriptor* foreign_;
|
||||
const EnumDescriptor* enum_;
|
||||
|
||||
@ -509,6 +543,8 @@ class DescriptorTest : public testing::Test {
|
||||
const FieldDescriptor* foo2_;
|
||||
const FieldDescriptor* bar2_;
|
||||
const FieldDescriptor* quux2_;
|
||||
|
||||
const FieldDescriptor* map_;
|
||||
};
|
||||
|
||||
TEST_F(DescriptorTest, Name) {
|
||||
@ -638,6 +674,12 @@ TEST_F(DescriptorTest, FieldLabel) {
|
||||
EXPECT_TRUE (baz_->is_repeated());
|
||||
}
|
||||
|
||||
TEST_F(DescriptorTest, IsMap) {
|
||||
EXPECT_TRUE(map_->is_map());
|
||||
EXPECT_FALSE(baz_->is_map());
|
||||
EXPECT_TRUE(map_->message_type()->options().map_entry());
|
||||
}
|
||||
|
||||
TEST_F(DescriptorTest, FieldHasDefault) {
|
||||
EXPECT_FALSE(foo_->has_default_value());
|
||||
EXPECT_FALSE(bar_->has_default_value());
|
||||
|
@ -72,7 +72,7 @@ TEST(DropUnknownFieldsTest, DynamicMessage) {
|
||||
foo_with_extra_fields.set_extra_int32_value(2);
|
||||
|
||||
google::protobuf::DynamicMessageFactory factory;
|
||||
scoped_ptr<google::protobuf::Message> foo(
|
||||
google::protobuf::scoped_ptr<google::protobuf::Message> foo(
|
||||
factory.GetPrototype(Foo::descriptor())->New());
|
||||
ASSERT_TRUE(foo->ParseFromString(foo_with_extra_fields.SerializeAsString()));
|
||||
EXPECT_TRUE(foo->GetReflection()->GetUnknownFields(*foo).empty());
|
||||
|
@ -73,8 +73,10 @@
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/arenastring.h>
|
||||
#include <google/protobuf/map_field_inl.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/map_type_handler.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
|
||||
@ -84,6 +86,8 @@ namespace protobuf {
|
||||
using internal::WireFormat;
|
||||
using internal::ExtensionSet;
|
||||
using internal::GeneratedMessageReflection;
|
||||
using internal::MapField;
|
||||
using internal::MapFieldBase;
|
||||
|
||||
|
||||
using internal::ArenaStringPtr;
|
||||
@ -93,6 +97,10 @@ using internal::ArenaStringPtr;
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsMapFieldInApi(const FieldDescriptor* field) {
|
||||
return field->is_map();
|
||||
}
|
||||
|
||||
// Compute the byte size of the in-memory representation of the field.
|
||||
int FieldSpaceUsed(const FieldDescriptor* field) {
|
||||
typedef FieldDescriptor FD; // avoid line wrapping
|
||||
@ -106,7 +114,12 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
|
||||
case FD::CPPTYPE_FLOAT : return sizeof(RepeatedField<float >);
|
||||
case FD::CPPTYPE_BOOL : return sizeof(RepeatedField<bool >);
|
||||
case FD::CPPTYPE_ENUM : return sizeof(RepeatedField<int >);
|
||||
case FD::CPPTYPE_MESSAGE: return sizeof(RepeatedPtrField<Message>);
|
||||
case FD::CPPTYPE_MESSAGE:
|
||||
if (IsMapFieldInApi(field)) {
|
||||
return sizeof(MapFieldBase);
|
||||
} else {
|
||||
return sizeof(RepeatedPtrField<Message>);
|
||||
}
|
||||
|
||||
case FD::CPPTYPE_STRING:
|
||||
switch (field->options().ctype()) {
|
||||
@ -369,7 +382,11 @@ void DynamicMessage::SharedCtor() {
|
||||
if (!field->is_repeated()) {
|
||||
new(field_ptr) Message*(NULL);
|
||||
} else {
|
||||
new(field_ptr) RepeatedPtrField<Message>();
|
||||
if (IsMapFieldInApi(field)) {
|
||||
new (field_ptr) MapFieldBase();
|
||||
} else {
|
||||
new (field_ptr) RepeatedPtrField<Message>();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -456,8 +473,12 @@ DynamicMessage::~DynamicMessage() {
|
||||
break;
|
||||
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
|
||||
->~RepeatedPtrField<Message>();
|
||||
if (IsMapFieldInApi(field)) {
|
||||
reinterpret_cast<MapFieldBase*>(field_ptr)->~MapFieldBase();
|
||||
} else {
|
||||
reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
|
||||
->~RepeatedPtrField<Message>();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
|
||||
// public header (for good reason), but dynamic_message.h is, and public
|
||||
// headers may only #include other public headers.
|
||||
struct PrototypeMap;
|
||||
scoped_ptr<PrototypeMap> prototypes_;
|
||||
google::protobuf::scoped_ptr<PrototypeMap> prototypes_;
|
||||
mutable Mutex prototypes_mutex_;
|
||||
|
||||
friend class DynamicMessage;
|
||||
|
@ -375,7 +375,7 @@ TEST(ExtensionSetTest, ArenaSetAllocatedMessageAndRelease) {
|
||||
|
||||
TEST(ExtensionSetTest, SwapExtensionBothFullWithArena) {
|
||||
::google::protobuf::Arena arena1;
|
||||
scoped_ptr<google::protobuf::Arena> arena2(new ::google::protobuf::Arena());
|
||||
google::protobuf::scoped_ptr<google::protobuf::Arena> arena2(new ::google::protobuf::Arena());
|
||||
|
||||
unittest::TestAllExtensions* message1 =
|
||||
Arena::CreateMessage<unittest::TestAllExtensions>(&arena1);
|
||||
|
@ -34,13 +34,16 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/map_field.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
|
||||
|
||||
#define GOOGLE_PROTOBUF_HAS_ONEOF
|
||||
|
||||
@ -48,6 +51,12 @@ namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
namespace {
|
||||
bool IsMapFieldInApi(const FieldDescriptor* field) {
|
||||
return field->is_map();
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
int StringSpaceUsedExcludingSelf(const string& str) {
|
||||
const void* start = &str;
|
||||
const void* end = &str + 1;
|
||||
@ -76,14 +85,7 @@ const string& NameOfEnum(const EnumDescriptor* descriptor, int value) {
|
||||
|
||||
namespace {
|
||||
inline bool SupportsArenas(const Descriptor* descriptor) {
|
||||
// In open-source release we enable arena support by default but as we also
|
||||
// down-integrate descriptor.pb.(h|cc) from our internal code base which
|
||||
// hasn't enabled arena support yet, here we need to be able to handle both
|
||||
// cases for descriptor protos.
|
||||
if (!Arena::is_arena_constructable<FileDescriptorProto>::type::value) {
|
||||
return descriptor->name() != "google/protobuf/descriptor.proto";
|
||||
}
|
||||
return true;
|
||||
return descriptor->file()->options().cc_enable_arenas();
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
@ -318,11 +320,17 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
|
||||
break;
|
||||
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
// We don't know which subclass of RepeatedPtrFieldBase the type is,
|
||||
// so we use RepeatedPtrFieldBase directly.
|
||||
total_size +=
|
||||
GetRaw<RepeatedPtrFieldBase>(message, field)
|
||||
.SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
|
||||
if (IsMapFieldInApi(field)) {
|
||||
total_size +=
|
||||
GetRaw<MapFieldBase>(message, field).SpaceUsedExcludingSelf();
|
||||
} else {
|
||||
// We don't know which subclass of RepeatedPtrFieldBase the type is,
|
||||
// so we use RepeatedPtrFieldBase directly.
|
||||
total_size +=
|
||||
GetRaw<RepeatedPtrFieldBase>(message, field)
|
||||
.SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -406,9 +414,17 @@ void GeneratedMessageReflection::SwapField(
|
||||
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
MutableRaw<RepeatedPtrFieldBase>(message1, field)->
|
||||
if (IsMapFieldInApi(field)) {
|
||||
MutableRaw<MapFieldBase>(message1, field)->
|
||||
MutableRepeatedField()->
|
||||
Swap<GenericTypeHandler<google::protobuf::Message> >(
|
||||
MutableRaw<MapFieldBase>(message2, field)->
|
||||
MutableRepeatedField());
|
||||
} else {
|
||||
MutableRaw<RepeatedPtrFieldBase>(message1, field)->
|
||||
Swap<GenericTypeHandler<google::protobuf::Message> >(
|
||||
MutableRaw<RepeatedPtrFieldBase>(message2, field));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -728,7 +744,11 @@ int GeneratedMessageReflection::FieldSize(const Message& message,
|
||||
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return GetRaw<RepeatedPtrFieldBase>(message, field).size();
|
||||
if (IsMapFieldInApi(field)) {
|
||||
return GetRaw<MapFieldBase>(message, field).GetRepeatedField().size();
|
||||
} else {
|
||||
return GetRaw<RepeatedPtrFieldBase>(message, field).size();
|
||||
}
|
||||
}
|
||||
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
@ -820,10 +840,16 @@ void GeneratedMessageReflection::ClearField(
|
||||
}
|
||||
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE: {
|
||||
// We don't know which subclass of RepeatedPtrFieldBase the type is,
|
||||
// so we use RepeatedPtrFieldBase directly.
|
||||
MutableRaw<RepeatedPtrFieldBase>(message, field)
|
||||
->Clear<GenericTypeHandler<Message> >();
|
||||
if (IsMapFieldInApi(field)) {
|
||||
MutableRaw<MapFieldBase>(message, field)
|
||||
->MutableRepeatedField()
|
||||
->Clear<GenericTypeHandler<Message> >();
|
||||
} else {
|
||||
// We don't know which subclass of RepeatedPtrFieldBase the type is,
|
||||
// so we use RepeatedPtrFieldBase directly.
|
||||
MutableRaw<RepeatedPtrFieldBase>(message, field)
|
||||
->Clear<GenericTypeHandler<Message> >();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -865,8 +891,14 @@ void GeneratedMessageReflection::RemoveLast(
|
||||
break;
|
||||
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
MutableRaw<RepeatedPtrFieldBase>(message, field)
|
||||
if (IsMapFieldInApi(field)) {
|
||||
MutableRaw<MapFieldBase>(message, field)
|
||||
->MutableRepeatedField()
|
||||
->RemoveLast<GenericTypeHandler<Message> >();
|
||||
} else {
|
||||
MutableRaw<RepeatedPtrFieldBase>(message, field)
|
||||
->RemoveLast<GenericTypeHandler<Message> >();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -881,8 +913,14 @@ Message* GeneratedMessageReflection::ReleaseLast(
|
||||
return static_cast<Message*>(
|
||||
MutableExtensionSet(message)->ReleaseLast(field->number()));
|
||||
} else {
|
||||
return MutableRaw<RepeatedPtrFieldBase>(message, field)
|
||||
if (IsMapFieldInApi(field)) {
|
||||
return MutableRaw<MapFieldBase>(message, field)
|
||||
->MutableRepeatedField()
|
||||
->ReleaseLast<GenericTypeHandler<Message> >();
|
||||
} else {
|
||||
return MutableRaw<RepeatedPtrFieldBase>(message, field)
|
||||
->ReleaseLast<GenericTypeHandler<Message> >();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -916,8 +954,14 @@ void GeneratedMessageReflection::SwapElements(
|
||||
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
MutableRaw<RepeatedPtrFieldBase>(message, field)
|
||||
if (IsMapFieldInApi(field)) {
|
||||
MutableRaw<MapFieldBase>(message, field)
|
||||
->MutableRepeatedField()
|
||||
->SwapElements(index1, index2);
|
||||
} else {
|
||||
MutableRaw<RepeatedPtrFieldBase>(message, field)
|
||||
->SwapElements(index1, index2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1519,8 +1563,14 @@ const Message& GeneratedMessageReflection::GetRepeatedMessage(
|
||||
return static_cast<const Message&>(
|
||||
GetExtensionSet(message).GetRepeatedMessage(field->number(), index));
|
||||
} else {
|
||||
return GetRaw<RepeatedPtrFieldBase>(message, field)
|
||||
.Get<GenericTypeHandler<Message> >(index);
|
||||
if (IsMapFieldInApi(field)) {
|
||||
return GetRaw<MapFieldBase>(message, field)
|
||||
.GetRepeatedField()
|
||||
.Get<GenericTypeHandler<Message> >(index);
|
||||
} else {
|
||||
return GetRaw<RepeatedPtrFieldBase>(message, field)
|
||||
.Get<GenericTypeHandler<Message> >(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1533,8 +1583,14 @@ Message* GeneratedMessageReflection::MutableRepeatedMessage(
|
||||
MutableExtensionSet(message)->MutableRepeatedMessage(
|
||||
field->number(), index));
|
||||
} else {
|
||||
return MutableRaw<RepeatedPtrFieldBase>(message, field)
|
||||
if (IsMapFieldInApi(field)) {
|
||||
return MutableRaw<MapFieldBase>(message, field)
|
||||
->MutableRepeatedField()
|
||||
->Mutable<GenericTypeHandler<Message> >(index);
|
||||
} else {
|
||||
return MutableRaw<RepeatedPtrFieldBase>(message, field)
|
||||
->Mutable<GenericTypeHandler<Message> >(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1549,11 +1605,18 @@ Message* GeneratedMessageReflection::AddMessage(
|
||||
return static_cast<Message*>(
|
||||
MutableExtensionSet(message)->AddMessage(field, factory));
|
||||
} else {
|
||||
Message* result = NULL;
|
||||
|
||||
// We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
|
||||
// know how to allocate one.
|
||||
RepeatedPtrFieldBase* repeated =
|
||||
MutableRaw<RepeatedPtrFieldBase>(message, field);
|
||||
Message* result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
|
||||
RepeatedPtrFieldBase* repeated = NULL;
|
||||
if (IsMapFieldInApi(field)) {
|
||||
repeated =
|
||||
MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField();
|
||||
} else {
|
||||
repeated = MutableRaw<RepeatedPtrFieldBase>(message, field);
|
||||
}
|
||||
result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
|
||||
if (result == NULL) {
|
||||
// We must allocate a new object.
|
||||
const Message* prototype;
|
||||
@ -1568,6 +1631,7 @@ Message* GeneratedMessageReflection::AddMessage(
|
||||
// of AddAllocated.
|
||||
repeated->UnsafeArenaAddAllocated<GenericTypeHandler<Message> >(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1584,11 +1648,18 @@ void* GeneratedMessageReflection::MutableRawRepeatedField(
|
||||
GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
|
||||
if (desc != NULL)
|
||||
GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
|
||||
if (field->is_extension())
|
||||
if (field->is_extension()) {
|
||||
return MutableExtensionSet(message)->MutableRawRepeatedField(
|
||||
field->number(), field->type(), field->is_packed(), field);
|
||||
else
|
||||
} else {
|
||||
// Trigger transform for MapField
|
||||
if (IsMapFieldInApi(field)) {
|
||||
return reinterpret_cast<MapFieldBase*>(reinterpret_cast<uint8*>(message) +
|
||||
offsets_[field->index()])
|
||||
->MutableRepeatedField();
|
||||
}
|
||||
return reinterpret_cast<uint8*>(message) + offsets_[field->index()];
|
||||
}
|
||||
}
|
||||
|
||||
const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor(
|
||||
@ -2000,6 +2071,54 @@ void* GeneratedMessageReflection::RepeatedFieldData(
|
||||
}
|
||||
}
|
||||
|
||||
GeneratedMessageReflection*
|
||||
GeneratedMessageReflection::NewGeneratedMessageReflection(
|
||||
const Descriptor* descriptor,
|
||||
const Message* default_instance,
|
||||
const int offsets[],
|
||||
int has_bits_offset,
|
||||
int unknown_fields_offset,
|
||||
int extensions_offset,
|
||||
const void* default_oneof_instance,
|
||||
int oneof_case_offset,
|
||||
int object_size,
|
||||
int arena_offset) {
|
||||
return new GeneratedMessageReflection(descriptor,
|
||||
default_instance,
|
||||
offsets,
|
||||
has_bits_offset,
|
||||
unknown_fields_offset,
|
||||
extensions_offset,
|
||||
default_oneof_instance,
|
||||
oneof_case_offset,
|
||||
DescriptorPool::generated_pool(),
|
||||
MessageFactory::generated_factory(),
|
||||
object_size,
|
||||
arena_offset);
|
||||
}
|
||||
|
||||
GeneratedMessageReflection*
|
||||
GeneratedMessageReflection::NewGeneratedMessageReflection(
|
||||
const Descriptor* descriptor,
|
||||
const Message* default_instance,
|
||||
const int offsets[],
|
||||
int has_bits_offset,
|
||||
int unknown_fields_offset,
|
||||
int extensions_offset,
|
||||
int object_size,
|
||||
int arena_offset) {
|
||||
return new GeneratedMessageReflection(descriptor,
|
||||
default_instance,
|
||||
offsets,
|
||||
has_bits_offset,
|
||||
unknown_fields_offset,
|
||||
extensions_offset,
|
||||
DescriptorPool::generated_pool(),
|
||||
MessageFactory::generated_factory(),
|
||||
object_size,
|
||||
arena_offset);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
@ -176,6 +176,32 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
|
||||
int arena_offset);
|
||||
~GeneratedMessageReflection();
|
||||
|
||||
// Shorter-to-call helpers for the above two constructions that work if the
|
||||
// pool and factory are the usual, namely, DescriptorPool::generated_pool()
|
||||
// and MessageFactory::generated_factory().
|
||||
|
||||
static GeneratedMessageReflection* NewGeneratedMessageReflection(
|
||||
const Descriptor* descriptor,
|
||||
const Message* default_instance,
|
||||
const int offsets[],
|
||||
int has_bits_offset,
|
||||
int unknown_fields_offset,
|
||||
int extensions_offset,
|
||||
const void* default_oneof_instance,
|
||||
int oneof_case_offset,
|
||||
int object_size,
|
||||
int arena_offset);
|
||||
|
||||
static GeneratedMessageReflection* NewGeneratedMessageReflection(
|
||||
const Descriptor* descriptor,
|
||||
const Message* default_instance,
|
||||
const int offsets[],
|
||||
int has_bits_offset,
|
||||
int unknown_fields_offset,
|
||||
int extensions_offset,
|
||||
int object_size,
|
||||
int arena_offset);
|
||||
|
||||
// implements Reflection -------------------------------------------
|
||||
|
||||
const UnknownFieldSet& GetUnknownFields(const Message& message) const;
|
||||
|
@ -36,6 +36,7 @@
|
||||
|
||||
#include <limits>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
282
src/google/protobuf/map.h
Normal file
282
src/google/protobuf/map.h
Normal file
@ -0,0 +1,282 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_H__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/map_type_handler.h>
|
||||
#include <google/protobuf/stubs/hash.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
template <typename Key, typename T>
|
||||
class Map;
|
||||
|
||||
template <typename Enum> struct is_proto_enum;
|
||||
|
||||
namespace internal {
|
||||
template <typename K, typename V, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
class MapField;
|
||||
}
|
||||
|
||||
// This is the class for google::protobuf::Map's internal value_type. Instead of using
|
||||
// std::pair as value_type, we use this class which provides us more control of
|
||||
// its process of construction and destruction.
|
||||
template <typename Key, typename T>
|
||||
class MapPair {
|
||||
public:
|
||||
typedef Key first_type;
|
||||
typedef T second_type;
|
||||
|
||||
MapPair(const Key& other_first, const T& other_second)
|
||||
: first(other_first), second(other_second) {}
|
||||
|
||||
MapPair(const Key& other_first) : first(other_first), second() {}
|
||||
|
||||
MapPair(const MapPair& other)
|
||||
: first(other.first), second(other.second) {}
|
||||
|
||||
MapPair& operator=(const MapPair& other) {
|
||||
first = other.first;
|
||||
second = other.second;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~MapPair() {}
|
||||
|
||||
const Key first;
|
||||
T second;
|
||||
|
||||
private:
|
||||
friend class Map<Key, T>;
|
||||
};
|
||||
|
||||
// STL-like iterator implementation for google::protobuf::Map. Users should not refer to
|
||||
// this class directly; use google::protobuf::Map<Key, T>::iterator instead.
|
||||
template <typename Key, typename T>
|
||||
class MapIterator {
|
||||
public:
|
||||
typedef MapPair<Key, T> value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
typedef MapIterator iterator;
|
||||
|
||||
// constructor
|
||||
MapIterator(const typename hash_map<Key, value_type*>::iterator& it)
|
||||
: it_(it) {}
|
||||
MapIterator(const MapIterator& other) : it_(other.it_) {}
|
||||
MapIterator& operator=(const MapIterator& other) {
|
||||
it_ = other.it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// deferenceable
|
||||
reference operator*() const { return *it_->second; }
|
||||
pointer operator->() const { return it_->second; }
|
||||
|
||||
// incrementable
|
||||
iterator& operator++() {
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
iterator operator++(int) { return iterator(it_++); }
|
||||
|
||||
// equality_comparable
|
||||
bool operator==(const iterator& x) const { return it_ == x.it_; }
|
||||
bool operator!=(const iterator& x) const { return it_ != x.it_; }
|
||||
|
||||
private:
|
||||
typename hash_map<Key, value_type*>::iterator it_;
|
||||
|
||||
friend Map<Key, T>;
|
||||
};
|
||||
|
||||
// google::protobuf::Map is an associative container type used to store protobuf map
|
||||
// fields. Its interface is similar to std::unordered_map. Users should use this
|
||||
// interface directly to visit or change map fields.
|
||||
template <typename Key, typename T>
|
||||
class Map {
|
||||
typedef internal::MapCppTypeHandler<T> ValueTypeHandler;
|
||||
public:
|
||||
typedef Key key_type;
|
||||
typedef T mapped_type;
|
||||
typedef MapPair<Key, T> value_type;
|
||||
|
||||
typedef value_type* pointer;
|
||||
typedef const value_type* const_pointer;
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
|
||||
typedef MapIterator<Key, T> iterator;
|
||||
typedef MapIterator<Key, T> const_iterator;
|
||||
|
||||
typedef size_t size_type;
|
||||
typedef hash<Key> hasher;
|
||||
|
||||
Map() : default_enum_value_(0) {}
|
||||
|
||||
Map(const Map& other) {
|
||||
insert(other.begin(), other.end());
|
||||
}
|
||||
|
||||
~Map() { clear(); }
|
||||
|
||||
// Iterators
|
||||
iterator begin() { return iterator(elements_.begin()); }
|
||||
iterator end() { return iterator(elements_.end()); }
|
||||
const_iterator begin() const {
|
||||
return const_iterator(
|
||||
const_cast<hash_map<Key, value_type*>&>(elements_).begin());
|
||||
}
|
||||
const_iterator end() const {
|
||||
return const_iterator(
|
||||
const_cast<hash_map<Key, value_type*>&>(elements_).end());
|
||||
}
|
||||
const_iterator cbegin() const { return begin(); }
|
||||
const_iterator cend() const { return end(); }
|
||||
|
||||
// Capacity
|
||||
size_type size() const { return elements_.size(); }
|
||||
bool empty() const { return elements_.empty(); }
|
||||
|
||||
// Element access
|
||||
T& operator[](const key_type& key) {
|
||||
value_type** value = &elements_[key];
|
||||
if (*value == NULL) {
|
||||
*value = new value_type(key);
|
||||
internal::MapValueInitializer<google::protobuf::is_proto_enum<T>::value,
|
||||
T>::Initialize((*value)->second,
|
||||
default_enum_value_);
|
||||
}
|
||||
return (*value)->second;
|
||||
}
|
||||
const T& at(const key_type& key) const {
|
||||
const_iterator it = find(key);
|
||||
GOOGLE_CHECK(it != end());
|
||||
return it->second;
|
||||
}
|
||||
T& at(const key_type& key) {
|
||||
iterator it = find(key);
|
||||
GOOGLE_CHECK(it != end());
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Lookup
|
||||
size_type count(const key_type& key) const {
|
||||
return elements_.count(key);
|
||||
}
|
||||
const_iterator find(const key_type& key) const {
|
||||
// When elements_ is a const instance, find(key) returns a const iterator.
|
||||
// However, to reduce code complexity, we use MapIterator for Map's both
|
||||
// const and non-const iterator, which only takes non-const iterator to
|
||||
// construct.
|
||||
return const_iterator(
|
||||
const_cast<hash_map<Key, value_type*>&>(elements_).find(key));
|
||||
}
|
||||
iterator find(const key_type& key) {
|
||||
return iterator(elements_.find(key));
|
||||
}
|
||||
|
||||
// insert
|
||||
std::pair<iterator, bool> insert(const value_type& value) {
|
||||
iterator it = find(value.first);
|
||||
if (it != end()) {
|
||||
return std::pair<iterator, bool>(it, false);
|
||||
} else {
|
||||
return elements_.insert(
|
||||
std::pair<Key, value_type*>(value.first, new value_type(value)));
|
||||
}
|
||||
}
|
||||
template <class InputIt>
|
||||
void insert(InputIt first, InputIt last) {
|
||||
for (InputIt it = first; it != last; ++it) {
|
||||
iterator exist_it = find(it->first);
|
||||
if (exist_it == end()) {
|
||||
operator[](it->first) = it->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Erase
|
||||
size_type erase(const key_type& key) {
|
||||
typename hash_map<Key, value_type*>::iterator it = elements_.find(key);
|
||||
if (it == elements_.end()) {
|
||||
return 0;
|
||||
} else {
|
||||
delete it->second;
|
||||
elements_.erase(it);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
void erase(iterator pos) {
|
||||
delete pos.it_->second;
|
||||
elements_.erase(pos.it_);
|
||||
}
|
||||
void erase(iterator first, iterator last) {
|
||||
for (iterator it = first; it != last;) {
|
||||
delete it.it_->second;
|
||||
elements_.erase((it++).it_);
|
||||
}
|
||||
}
|
||||
void clear() {
|
||||
for (iterator it = begin(); it != end(); ++it) {
|
||||
delete it.it_->second;
|
||||
}
|
||||
elements_.clear();
|
||||
}
|
||||
|
||||
// Assign
|
||||
Map& operator=(const Map& other) {
|
||||
insert(other.begin(), other.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
// Set default enum value only for proto2 map field whose value is enum type.
|
||||
void SetDefaultEnumValue(int default_enum_value) {
|
||||
default_enum_value_ = default_enum_value;
|
||||
}
|
||||
|
||||
hash_map<Key, value_type*> elements_;
|
||||
int default_enum_value_;
|
||||
|
||||
template <typename K, typename V, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum>
|
||||
friend class LIBPROTOBUF_EXPORT internal::MapField;
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_MAP_H__
|
449
src/google/protobuf/map_entry.h
Normal file
449
src/google/protobuf/map_entry.h
Normal file
@ -0,0 +1,449 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_ENTRY_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_ENTRY_H__
|
||||
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/map_type_handler.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
class Arena;
|
||||
}
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// This is the common base class for MapEntry. It is used by MapFieldBase in
|
||||
// reflection api, in which the static type of key and value is unknown.
|
||||
class LIBPROTOBUF_EXPORT MapEntryBase : public Message {
|
||||
public:
|
||||
::google::protobuf::Metadata GetMetadata() const {
|
||||
::google::protobuf::Metadata metadata;
|
||||
metadata.descriptor = descriptor_;
|
||||
metadata.reflection = reflection_;
|
||||
return metadata;
|
||||
}
|
||||
|
||||
protected:
|
||||
MapEntryBase() : descriptor_(NULL), reflection_(NULL) { }
|
||||
virtual ~MapEntryBase() {}
|
||||
|
||||
const Descriptor* descriptor_;
|
||||
const Reflection* reflection_;
|
||||
};
|
||||
|
||||
// MapEntry is the returned google::protobuf::Message when calling AddMessage of
|
||||
// google::protobuf::Reflection. In order to let it work with generated message
|
||||
// reflection, its internal layout is the same as generated message with the
|
||||
// same fields. However, in order to decide the internal layout of key/value, we
|
||||
// need to know both their cpp type in generated api and proto type.
|
||||
//
|
||||
// cpp type | proto type | internal layout
|
||||
// int32 TYPE_INT32 int32
|
||||
// int32 TYPE_FIXED32 int32
|
||||
// FooEnum TYPE_ENUM int
|
||||
// FooMessage TYPE_MESSAGE FooMessage*
|
||||
//
|
||||
// The internal layouts of primitive types can be inferred from its proto type,
|
||||
// while we need to explicitly tell cpp type if proto type is TYPE_MESSAGE to
|
||||
// get internal layout.
|
||||
// Moreover, default_enum_value is used to initialize enum field in proto2.
|
||||
template <typename Key, typename Value, FieldDescriptor::Type KeyProtoType,
|
||||
FieldDescriptor::Type ValueProtoType, int default_enum_value>
|
||||
class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase {
|
||||
// Handlers for key/value's proto field type. Used to infer internal layout
|
||||
// and provide parsing/serialization support.
|
||||
typedef MapProtoTypeHandler<KeyProtoType> KeyProtoHandler;
|
||||
typedef MapProtoTypeHandler<ValueProtoType> ValueProtoHandler;
|
||||
|
||||
// Define key/value's internal stored type. Message is the only one whose
|
||||
// internal stored type cannot be inferred from its proto type.
|
||||
typedef typename KeyProtoHandler::CppType KeyProtoHandlerCppType;
|
||||
typedef typename ValueProtoHandler::CppType ValueProtoHandlerCppType;
|
||||
static const bool kIsKeyMessage = KeyProtoHandler::kIsMessage;
|
||||
static const bool kIsValueMessage = ValueProtoHandler::kIsMessage;
|
||||
typedef typename MapIf<kIsKeyMessage, Key, KeyProtoHandlerCppType>::type
|
||||
KeyCppType;
|
||||
typedef typename MapIf<kIsValueMessage, Value, ValueProtoHandlerCppType>::type
|
||||
ValCppType;
|
||||
|
||||
// Handlers for key/value's internal stored type. Provide utilities to
|
||||
// manipulate internal stored type. We need it because some types are stored
|
||||
// as values and others are stored as pointers (Message and string), but we
|
||||
// need to keep the code in MapEntry unified instead of providing different
|
||||
// codes for each type.
|
||||
typedef MapCppTypeHandler<KeyCppType> KeyCppHandler;
|
||||
typedef MapCppTypeHandler<ValCppType> ValueCppHandler;
|
||||
|
||||
// Define internal memory layout. Strings and messages are stored as
|
||||
// pointers, while other types are stored as values.
|
||||
static const bool kKeyIsStringOrMessage = KeyCppHandler::kIsStringOrMessage;
|
||||
static const bool kValIsStringOrMessage = ValueCppHandler::kIsStringOrMessage;
|
||||
typedef typename MapIf<kKeyIsStringOrMessage, KeyCppType*, KeyCppType>::type
|
||||
KeyBase;
|
||||
typedef typename MapIf<kValIsStringOrMessage, ValCppType*, ValCppType>::type
|
||||
ValueBase;
|
||||
|
||||
// Abbreviation for MapEntry
|
||||
typedef typename google::protobuf::internal::MapEntry<
|
||||
Key, Value, KeyProtoType, ValueProtoType, default_enum_value> EntryType;
|
||||
|
||||
// Constants for field number.
|
||||
static const int kKeyFieldNumber = 1;
|
||||
static const int kValueFieldNumber = 2;
|
||||
|
||||
// Constants for field tag.
|
||||
static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
|
||||
kKeyFieldNumber, KeyProtoHandler::kWireType);
|
||||
static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
|
||||
kValueFieldNumber, ValueProtoHandler::kWireType);
|
||||
static const int kTagSize = 1;
|
||||
|
||||
public:
|
||||
~MapEntry() {
|
||||
if (this == default_instance_) {
|
||||
delete reflection_;
|
||||
} else {
|
||||
KeyCppHandler::Delete(key_);
|
||||
ValueCppHandler::Delete(value_);
|
||||
}
|
||||
}
|
||||
|
||||
// accessors ======================================================
|
||||
|
||||
inline void set_key(const KeyCppType& key) {
|
||||
KeyCppHandler::EnsureMutable(&key_);
|
||||
KeyCppHandler::Merge(key, &key_);
|
||||
set_has_key();
|
||||
}
|
||||
virtual inline const KeyCppType& key() const {
|
||||
return KeyCppHandler::Reference(key_);
|
||||
}
|
||||
inline KeyCppType* mutable_key() {
|
||||
set_has_key();
|
||||
KeyCppHandler::EnsureMutable(&key_);
|
||||
return KeyCppHandler::Pointer(key_);
|
||||
}
|
||||
inline void set_value(const ValCppType& value) {
|
||||
ValueCppHandler::EnsureMutable(&value_);
|
||||
ValueCppHandler::Merge(value, &value_);
|
||||
set_has_value();
|
||||
}
|
||||
virtual inline const ValCppType& value() const {
|
||||
GOOGLE_CHECK(default_instance_ != NULL);
|
||||
return ValueCppHandler::DefaultIfNotInitialized(value_,
|
||||
default_instance_->value_);
|
||||
}
|
||||
inline ValCppType* mutable_value() {
|
||||
set_has_value();
|
||||
ValueCppHandler::EnsureMutable(&value_);
|
||||
return ValueCppHandler::Pointer(value_);
|
||||
}
|
||||
|
||||
// implements Message =============================================
|
||||
|
||||
bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
|
||||
uint32 tag;
|
||||
|
||||
for (;;) {
|
||||
// 1) corrupted data: return false;
|
||||
// 2) unknown field: skip without putting into unknown field set;
|
||||
// 3) unknown enum value: keep it in parsing. In proto2, caller should
|
||||
// check the value and put this entry into containing message's unknown
|
||||
// field set if the value is an unknown enum. In proto3, caller doesn't
|
||||
// need to care whether the value is unknown enum;
|
||||
// 4) missing key/value: missed key/value will have default value. caller
|
||||
// should take this entry as if key/value is set to default value.
|
||||
tag = input->ReadTag();
|
||||
switch (tag) {
|
||||
case kKeyTag:
|
||||
if (!KeyProtoHandler::Read(input, mutable_key())) return false;
|
||||
set_has_key();
|
||||
if (!input->ExpectTag(kValueTag)) break;
|
||||
GOOGLE_FALLTHROUGH_INTENDED;
|
||||
|
||||
case kValueTag:
|
||||
if (!ValueProtoHandler::Read(input, mutable_value())) return false;
|
||||
set_has_value();
|
||||
if (input->ExpectAtEnd()) return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (tag == 0 ||
|
||||
WireFormatLite::GetTagWireType(tag) ==
|
||||
WireFormatLite::WIRETYPE_END_GROUP) {
|
||||
return true;
|
||||
}
|
||||
if (!WireFormatLite::SkipField(input, tag)) return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ByteSize() const {
|
||||
int size = 0;
|
||||
size += has_key() ? kTagSize + KeyProtoHandler::ByteSize(key()) : 0;
|
||||
size += has_value() ? kTagSize + ValueProtoHandler::ByteSize(value()) : 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
|
||||
KeyProtoHandler::Write(kKeyFieldNumber, key(), output);
|
||||
ValueProtoHandler::Write(kValueFieldNumber, value(), output);
|
||||
}
|
||||
|
||||
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
|
||||
output = KeyProtoHandler::WriteToArray(kKeyFieldNumber, key(), output);
|
||||
output =
|
||||
ValueProtoHandler::WriteToArray(kValueFieldNumber, value(), output);
|
||||
return output;
|
||||
}
|
||||
|
||||
int GetCachedSize() const {
|
||||
int size = 0;
|
||||
size += has_key() ? kTagSize + KeyProtoHandler::GetCachedSize(key()) : 0;
|
||||
size +=
|
||||
has_value() ? kTagSize + ValueProtoHandler::GetCachedSize(value()) : 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); }
|
||||
|
||||
Message* New() const {
|
||||
MapEntry* entry = new MapEntry;
|
||||
entry->descriptor_ = descriptor_;
|
||||
entry->reflection_ = reflection_;
|
||||
entry->default_instance_ = default_instance_;
|
||||
return entry;
|
||||
}
|
||||
|
||||
int SpaceUsed() const {
|
||||
int size = sizeof(MapEntry);
|
||||
size += KeyCppHandler::SpaceUsedInMapEntry(key_);
|
||||
size += ValueCppHandler::SpaceUsedInMapEntry(value_);
|
||||
return size;
|
||||
}
|
||||
|
||||
void CopyFrom(const ::google::protobuf::Message& from) {
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
void MergeFrom(const ::google::protobuf::Message& from) {
|
||||
GOOGLE_CHECK_NE(&from, this);
|
||||
const MapEntry* source = dynamic_cast_if_available<const MapEntry*>(&from);
|
||||
if (source == NULL) {
|
||||
ReflectionOps::Merge(from, this);
|
||||
} else {
|
||||
MergeFrom(*source);
|
||||
}
|
||||
}
|
||||
|
||||
void CopyFrom(const MapEntry& from) {
|
||||
Clear();
|
||||
MergeFrom(from);
|
||||
}
|
||||
|
||||
void MergeFrom(const MapEntry& from) {
|
||||
if (from._has_bits_[0]) {
|
||||
if (from.has_key()) {
|
||||
KeyCppHandler::EnsureMutable(&key_);
|
||||
KeyCppHandler::Merge(from.key(), &key_);
|
||||
set_has_key();
|
||||
}
|
||||
if (from.has_value()) {
|
||||
ValueCppHandler::EnsureMutable(&value_);
|
||||
ValueCppHandler::Merge(from.value(), &value_);
|
||||
set_has_value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
KeyCppHandler::Clear(&key_);
|
||||
ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value);
|
||||
clear_has_key();
|
||||
clear_has_value();
|
||||
}
|
||||
|
||||
void InitAsDefaultInstance() {
|
||||
KeyCppHandler::AssignDefaultValue(&key_);
|
||||
ValueCppHandler::AssignDefaultValue(&value_);
|
||||
}
|
||||
|
||||
// Create default MapEntry instance for given descriptor. Descriptor has to be
|
||||
// given when creating default MapEntry instance because different map field
|
||||
// may have the same type and MapEntry class. The given descriptor is needed
|
||||
// to distinguish instances of the same MapEntry class.
|
||||
static MapEntry* CreateDefaultInstance(const Descriptor* descriptor) {
|
||||
MapEntry* entry = new MapEntry();
|
||||
const Reflection* reflection = new GeneratedMessageReflection(
|
||||
descriptor, entry, offsets_,
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _has_bits_),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _unknown_fields_), -1,
|
||||
DescriptorPool::generated_pool(),
|
||||
::google::protobuf::MessageFactory::generated_factory(), sizeof(MapEntry), -1);
|
||||
entry->descriptor_ = descriptor;
|
||||
entry->reflection_ = reflection;
|
||||
entry->default_instance_ = entry;
|
||||
entry->InitAsDefaultInstance();
|
||||
return entry;
|
||||
}
|
||||
|
||||
// Create a MapEntry for given key and value from google::protobuf::Map in
|
||||
// serialization. This function is only called when value is enum. Enum is
|
||||
// treated differently because its type in MapEntry is int and its type in
|
||||
// google::protobuf::Map is enum. We cannot create a reference to int from an enum.
|
||||
static MapEntry* EnumWrap(const Key& key, const Value value) {
|
||||
return new MapEnumEntryWrapper<Key, Value, KeyProtoType, ValueProtoType,
|
||||
default_enum_value>(key, value);
|
||||
}
|
||||
|
||||
// Like above, but for all the other types. This avoids value copy to create
|
||||
// MapEntry from google::protobuf::Map in serialization.
|
||||
static MapEntry* Wrap(const Key& key, const Value& value) {
|
||||
return new MapEntryWrapper<Key, Value, KeyProtoType, ValueProtoType,
|
||||
default_enum_value>(key, value);
|
||||
}
|
||||
|
||||
protected:
|
||||
void set_has_key() { _has_bits_[0] |= 0x00000001u; }
|
||||
bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
|
||||
void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
|
||||
void set_has_value() { _has_bits_[0] |= 0x00000002u; }
|
||||
bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
|
||||
void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
|
||||
|
||||
private:
|
||||
// Serializing a generated message containing map field involves serializing
|
||||
// key-value pairs from google::protobuf::Map. The wire format of each key-value pair
|
||||
// after serialization should be the same as that of a MapEntry message
|
||||
// containing the same key and value inside it. However, google::protobuf::Map doesn't
|
||||
// store key and value as MapEntry message, which disables us to use existing
|
||||
// code to serialize message. In order to use existing code to serialize
|
||||
// message, we need to construct a MapEntry from key-value pair. But it
|
||||
// involves copy of key and value to construct a MapEntry. In order to avoid
|
||||
// this copy in constructing a MapEntry, we need the following class which
|
||||
// only takes references of given key and value.
|
||||
template <typename KeyNested, typename ValueNested,
|
||||
FieldDescriptor::Type KeyProtoNested,
|
||||
FieldDescriptor::Type ValueProtoNested, int default_enum>
|
||||
class LIBPROTOBUF_EXPORT MapEntryWrapper
|
||||
: public MapEntry<KeyNested, ValueNested, KeyProtoNested,
|
||||
ValueProtoNested, default_enum> {
|
||||
typedef MapEntry<KeyNested, ValueNested, KeyProtoNested, ValueProtoNested,
|
||||
default_enum_value> Base;
|
||||
typedef typename Base::KeyCppType KeyCppType;
|
||||
typedef typename Base::ValCppType ValCppType;
|
||||
|
||||
public:
|
||||
MapEntryWrapper(const KeyNested& key, const ValueNested& value)
|
||||
: key_(key), value_(value) {
|
||||
Base::set_has_key();
|
||||
Base::set_has_value();
|
||||
}
|
||||
inline const KeyCppType& key() const { return key_; }
|
||||
inline const ValCppType& value() const { return value_; }
|
||||
|
||||
private:
|
||||
const Key& key_;
|
||||
const Value& value_;
|
||||
};
|
||||
|
||||
// Like above, but for enum value only, which stores value instead of
|
||||
// reference of value field inside. This is needed because the type of value
|
||||
// field in constructor is an enum, while we need to store it as an int. If we
|
||||
// initialize a reference to int with a reference to enum, compiler will
|
||||
// generate a temporary int from enum and initialize the reference to int with
|
||||
// the temporary.
|
||||
template <typename KeyNested, typename ValueNested,
|
||||
FieldDescriptor::Type KeyProtoNested,
|
||||
FieldDescriptor::Type ValueProtoNested, int default_enum>
|
||||
class LIBPROTOBUF_EXPORT MapEnumEntryWrapper
|
||||
: public MapEntry<KeyNested, ValueNested, KeyProtoNested,
|
||||
ValueProtoNested, default_enum> {
|
||||
typedef MapEntry<KeyNested, ValueNested, KeyProtoNested, ValueProtoNested,
|
||||
default_enum> Base;
|
||||
typedef typename Base::KeyCppType KeyCppType;
|
||||
typedef typename Base::ValCppType ValCppType;
|
||||
|
||||
public:
|
||||
MapEnumEntryWrapper(const KeyNested& key, const ValueNested& value)
|
||||
: key_(key), value_(value) {
|
||||
Base::set_has_key();
|
||||
Base::set_has_value();
|
||||
}
|
||||
inline const KeyCppType& key() const { return key_; }
|
||||
inline const ValCppType& value() const { return value_; }
|
||||
|
||||
private:
|
||||
const KeyCppType& key_;
|
||||
const ValCppType value_;
|
||||
};
|
||||
|
||||
MapEntry() : default_instance_(NULL) {
|
||||
KeyCppHandler::Initialize(&key_);
|
||||
ValueCppHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value);
|
||||
_has_bits_[0] = 0;
|
||||
}
|
||||
|
||||
KeyBase key_;
|
||||
ValueBase value_;
|
||||
static int offsets_[2];
|
||||
UnknownFieldSet _unknown_fields_;
|
||||
uint32 _has_bits_[1];
|
||||
MapEntry* default_instance_;
|
||||
|
||||
friend class ::google::protobuf::Arena;
|
||||
template <typename K, typename V,
|
||||
FieldDescriptor::Type KType,
|
||||
FieldDescriptor::Type VType, int default_enum>
|
||||
friend class LIBPROTOBUF_EXPORT internal::MapField;
|
||||
friend class LIBPROTOBUF_EXPORT internal::GeneratedMessageReflection;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
|
||||
};
|
||||
|
||||
template <typename Key, typename Value, FieldDescriptor::Type KeyProtoType,
|
||||
FieldDescriptor::Type ValueProtoType, int default_enum_value>
|
||||
int MapEntry<Key, Value, KeyProtoType, ValueProtoType,
|
||||
default_enum_value>::offsets_[2] = {
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, key_),
|
||||
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, value_),
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_MAP_ENTRY_H__
|
113
src/google/protobuf/map_field.cc
Normal file
113
src/google/protobuf/map_field.cc
Normal file
@ -0,0 +1,113 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <google/protobuf/map_field.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
MapFieldBase::~MapFieldBase() {
|
||||
if (repeated_field_ != NULL) delete repeated_field_;
|
||||
}
|
||||
|
||||
const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const {
|
||||
SyncRepeatedFieldWithMap();
|
||||
return *repeated_field_;
|
||||
}
|
||||
|
||||
RepeatedPtrFieldBase* MapFieldBase::MutableRepeatedField() {
|
||||
SyncRepeatedFieldWithMap();
|
||||
SetRepeatedDirty();
|
||||
return repeated_field_;
|
||||
}
|
||||
|
||||
int MapFieldBase::SpaceUsedExcludingSelf() const {
|
||||
mutex_.Lock();
|
||||
int size = SpaceUsedExcludingSelfNoLock();
|
||||
mutex_.Unlock();
|
||||
return size;
|
||||
}
|
||||
|
||||
int MapFieldBase::SpaceUsedExcludingSelfNoLock() const {
|
||||
if (repeated_field_ != NULL) {
|
||||
return repeated_field_->SpaceUsedExcludingSelf();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MapFieldBase::InitMetadataOnce() const {
|
||||
GOOGLE_CHECK(entry_descriptor_ != NULL);
|
||||
GOOGLE_CHECK(assign_descriptor_callback_ != NULL);
|
||||
(*assign_descriptor_callback_)();
|
||||
}
|
||||
|
||||
void MapFieldBase::SetMapDirty() { state_ = STATE_MODIFIED_MAP; }
|
||||
|
||||
void MapFieldBase::SetRepeatedDirty() { state_ = STATE_MODIFIED_REPEATED; }
|
||||
|
||||
void* MapFieldBase::MutableRepeatedPtrField() const { return repeated_field_; }
|
||||
|
||||
void MapFieldBase::SyncRepeatedFieldWithMap() const {
|
||||
Atomic32 state = google::protobuf::internal::NoBarrier_Load(&state_);
|
||||
if (state == STATE_MODIFIED_MAP) {
|
||||
mutex_.Lock();
|
||||
// Double check state, because another thread may have seen the same state
|
||||
// and done the synchronization before the current thread.
|
||||
if (state_ == STATE_MODIFIED_MAP) {
|
||||
SyncRepeatedFieldWithMapNoLock();
|
||||
google::protobuf::internal::NoBarrier_Store(&state_, CLEAN);
|
||||
}
|
||||
mutex_.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const {
|
||||
if (repeated_field_ == NULL) repeated_field_ = new RepeatedPtrField<Message>;
|
||||
}
|
||||
|
||||
void MapFieldBase::SyncMapWithRepeatedField() const {
|
||||
Atomic32 state = google::protobuf::internal::NoBarrier_Load(&state_);
|
||||
if (state == STATE_MODIFIED_REPEATED) {
|
||||
mutex_.Lock();
|
||||
// Double check state, because another thread may have seen the same state
|
||||
// and done the synchronization before the current thread.
|
||||
if (state_ == STATE_MODIFIED_REPEATED) {
|
||||
SyncMapWithRepeatedFieldNoLock();
|
||||
google::protobuf::internal::NoBarrier_Store(&state_, CLEAN);
|
||||
}
|
||||
mutex_.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
220
src/google/protobuf/map_field.h
Normal file
220
src/google/protobuf/map_field.h
Normal file
@ -0,0 +1,220 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_FIELD_H__
|
||||
|
||||
#include <google/protobuf/stubs/atomicops.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/map.h>
|
||||
#include <google/protobuf/map_entry.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/unknown_field_set.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace internal {
|
||||
|
||||
class ContendedMapCleanTest;
|
||||
class GeneratedMessageReflection;
|
||||
class MapFieldAccessor;
|
||||
|
||||
// This class provides accesss to map field using reflection, which is the same
|
||||
// as those provided for RepeatedPtrField<Message>. It is used for internal
|
||||
// reflection implentation only. Users should never use this directly.
|
||||
class LIBPROTOBUF_EXPORT MapFieldBase {
|
||||
public:
|
||||
MapFieldBase()
|
||||
: base_map_(NULL),
|
||||
repeated_field_(NULL),
|
||||
entry_descriptor_(NULL),
|
||||
assign_descriptor_callback_(NULL),
|
||||
state_(STATE_MODIFIED_MAP) {}
|
||||
virtual ~MapFieldBase();
|
||||
|
||||
// Returns reference to internal repeated field. Data written using
|
||||
// google::protobuf::Map's api prior to calling this function is guarantted to be
|
||||
// included in repeated field.
|
||||
const RepeatedPtrFieldBase& GetRepeatedField() const;
|
||||
|
||||
// Like above. Returns mutable pointer to the internal repeated field.
|
||||
RepeatedPtrFieldBase* MutableRepeatedField();
|
||||
|
||||
// Returns the number of bytes used by the repeated field, excluding
|
||||
// sizeof(*this)
|
||||
int SpaceUsedExcludingSelf() const;
|
||||
|
||||
protected:
|
||||
// Gets the size of space used by map field.
|
||||
virtual int SpaceUsedExcludingSelfNoLock() const;
|
||||
|
||||
// Synchronizes the content in Map to RepeatedPtrField if there is any change
|
||||
// to Map after last synchronization.
|
||||
void SyncRepeatedFieldWithMap() const;
|
||||
virtual void SyncRepeatedFieldWithMapNoLock() const;
|
||||
|
||||
// Synchronizes the content in RepeatedPtrField to Map if there is any change
|
||||
// to RepeatedPtrField after last synchronization.
|
||||
void SyncMapWithRepeatedField() const;
|
||||
virtual void SyncMapWithRepeatedFieldNoLock() const {}
|
||||
|
||||
// Tells MapFieldBase that there is new change to Map.
|
||||
void SetMapDirty();
|
||||
|
||||
// Tells MapFieldBase that there is new change to RepeatedPTrField.
|
||||
void SetRepeatedDirty();
|
||||
|
||||
// Provides derived class the access to repeated field.
|
||||
void* MutableRepeatedPtrField() const;
|
||||
|
||||
// Creates descriptor for only one time.
|
||||
void InitMetadataOnce() const;
|
||||
|
||||
enum State {
|
||||
STATE_MODIFIED_MAP = 0, // map has newly added data that has not been
|
||||
// synchronized to repeated field
|
||||
STATE_MODIFIED_REPEATED = 1, // repeated field has newly added data that
|
||||
// has not been synchronized to map
|
||||
CLEAN = 2, // data in map and repeated field are same
|
||||
};
|
||||
|
||||
mutable void* base_map_;
|
||||
mutable RepeatedPtrField<Message>* repeated_field_;
|
||||
// MapEntry can only be created from MapField. To create MapEntry, MapField
|
||||
// needs to know its descriptor, because MapEntry is not generated class which
|
||||
// cannot initialize its own descriptor by calling generated
|
||||
// descriptor-assign-function. Thus, we need to register a callback to
|
||||
// initialize MapEntry's descriptor.
|
||||
const Descriptor** entry_descriptor_;
|
||||
void (*assign_descriptor_callback_)();
|
||||
|
||||
mutable Mutex mutex_; // The thread to synchronize map and repeated field
|
||||
// needs to get lock first;
|
||||
mutable volatile Atomic32 state_; // 0: STATE_MODIFIED_MAP
|
||||
// 1: STATE_MODIFIED_REPEATED
|
||||
// 2: CLEAN
|
||||
|
||||
private:
|
||||
friend class ContendedMapCleanTest;
|
||||
friend class GeneratedMessageReflection;
|
||||
friend class MapFieldAccessor;
|
||||
};
|
||||
|
||||
// This class provides accesss to map field using generated api. It is used for
|
||||
// internal generated message implentation only. Users should never use this
|
||||
// directly.
|
||||
template<typename Key, typename T,
|
||||
FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value = 0>
|
||||
class LIBPROTOBUF_EXPORT MapField : public MapFieldBase {
|
||||
// Handlers for key/value's proto field type.
|
||||
typedef MapProtoTypeHandler<KeyProto> KeyProtoHandler;
|
||||
typedef MapProtoTypeHandler<ValueProto> ValueProtoHandler;
|
||||
|
||||
// Define key/value's internal stored type.
|
||||
typedef typename KeyProtoHandler::CppType KeyHandlerCpp;
|
||||
typedef typename ValueProtoHandler::CppType ValHandlerCpp;
|
||||
static const bool kIsKeyMessage = KeyProtoHandler::kIsMessage;
|
||||
static const bool kIsValMessage = ValueProtoHandler::kIsMessage;
|
||||
typedef typename MapIf<kIsKeyMessage, Key, KeyHandlerCpp>::type KeyCpp;
|
||||
typedef typename MapIf<kIsValMessage, T , ValHandlerCpp>::type ValCpp;
|
||||
|
||||
// Handlers for key/value's internal stored type.
|
||||
typedef MapCppTypeHandler<KeyCpp> KeyHandler;
|
||||
typedef MapCppTypeHandler<ValCpp> ValHandler;
|
||||
|
||||
// Define message type for internal repeated field.
|
||||
typedef MapEntry<Key, T, KeyProto, ValueProto, default_enum_value> EntryType;
|
||||
|
||||
// Enum needs to be handled differently from other types because it has
|
||||
// different exposed type in google::protobuf::Map's api and repeated field's api. For
|
||||
// details see the comment in the implementation of
|
||||
// SyncMapWithRepeatedFieldNoLocki.
|
||||
static const bool kIsValueEnum = ValueProtoHandler::kIsEnum;
|
||||
typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType;
|
||||
|
||||
public:
|
||||
MapField();
|
||||
// MapField doesn't own the default_entry, which means default_entry must
|
||||
// outlive the lifetime of MapField.
|
||||
MapField(const Message* default_entry);
|
||||
~MapField();
|
||||
|
||||
// Accessors
|
||||
const Map<Key, T>& GetMap() const;
|
||||
Map<Key, T>* MutableMap();
|
||||
|
||||
// Convenient methods for generated message implementation.
|
||||
int size() const;
|
||||
void Clear();
|
||||
void MergeFrom(const MapField& other);
|
||||
void Swap(MapField* other);
|
||||
|
||||
// Allocates metadata only if this MapField is part of a generated message.
|
||||
void SetEntryDescriptor(const Descriptor** descriptor);
|
||||
void SetAssignDescriptorCallback(void (*callback)());
|
||||
|
||||
// Set default enum value only for proto2 map field whose value is enum type.
|
||||
void SetDefaultEnumValue();
|
||||
|
||||
// Used in the implementation of parsing. Caller should take the ownership.
|
||||
EntryType* NewEntry() const;
|
||||
// Used in the implementation of serializing enum value type. Caller should
|
||||
// take the ownership.
|
||||
EntryType* NewEnumEntryWrapper(const Key& key, const T t) const;
|
||||
// Used in the implementation of serializing other value types. Caller should
|
||||
// take the ownership.
|
||||
EntryType* NewEntryWrapper(const Key& key, const T& t) const;
|
||||
|
||||
private:
|
||||
// MapField needs MapEntry's default instance to create new MapEntry.
|
||||
void InitDefaultEntryOnce() const;
|
||||
|
||||
// Convenient methods to get internal google::protobuf::Map
|
||||
const Map<Key, T>& GetInternalMap() const;
|
||||
Map<Key, T>* MutableInternalMap();
|
||||
|
||||
// Implements MapFieldBase
|
||||
void SyncRepeatedFieldWithMapNoLock() const;
|
||||
void SyncMapWithRepeatedFieldNoLock() const;
|
||||
int SpaceUsedExcludingSelfNoLock() const;
|
||||
|
||||
mutable const EntryType* default_entry_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_MAP_FIELD_H__
|
269
src/google/protobuf/map_field_inl.h
Normal file
269
src/google/protobuf/map_field_inl.h
Normal file
@ -0,0 +1,269 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_FIELD_INL_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_FIELD_INL_H__
|
||||
|
||||
#include <memory>
|
||||
#ifndef _SHARED_PTR_H
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/map_field.h>
|
||||
#include <google/protobuf/map_type_handler.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MapField()
|
||||
: default_entry_(NULL) {
|
||||
MapFieldBase::base_map_ = new Map<Key, T>;
|
||||
SetDefaultEnumValue();
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MapField(
|
||||
const Message* default_entry)
|
||||
: default_entry_(down_cast<const EntryType*>(default_entry)) {
|
||||
MapFieldBase::base_map_ = new Map<Key, T>;
|
||||
SetDefaultEnumValue();
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
MapField<Key, T, KeyProto, ValueProto, default_enum_value>::~MapField() {
|
||||
delete reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
int MapField<Key, T, KeyProto, ValueProto, default_enum_value>::size() const {
|
||||
SyncMapWithRepeatedField();
|
||||
return GetInternalMap().size();
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::Clear() {
|
||||
SyncMapWithRepeatedField();
|
||||
MutableInternalMap()->clear();
|
||||
SetMapDirty();
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
const Map<Key, T>&
|
||||
MapField<Key, T, KeyProto, ValueProto, default_enum_value>::GetMap() const {
|
||||
SyncMapWithRepeatedField();
|
||||
return GetInternalMap();
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
Map<Key, T>*
|
||||
MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MutableMap() {
|
||||
SyncMapWithRepeatedField();
|
||||
Map<Key, T>* result = MutableInternalMap();
|
||||
SetMapDirty();
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MergeFrom(
|
||||
const MapField& other) {
|
||||
SyncMapWithRepeatedField();
|
||||
other.SyncMapWithRepeatedField();
|
||||
|
||||
Map<Key, T>* map = MutableInternalMap();
|
||||
const Map<Key, T>& other_map = other.GetInternalMap();
|
||||
for (typename Map<Key, T>::const_iterator it = other_map.begin();
|
||||
it != other_map.end(); ++it) {
|
||||
(*map)[it->first] = it->second;
|
||||
}
|
||||
SetMapDirty();
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::Swap(
|
||||
MapField* other) {
|
||||
std::swap(repeated_field_, other->repeated_field_);
|
||||
std::swap(base_map_, other->base_map_);
|
||||
std::swap(state_, other->state_);
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
void
|
||||
MapField<Key, T, KeyProto, ValueProto, default_enum_value>::SetEntryDescriptor(
|
||||
const Descriptor** descriptor) {
|
||||
entry_descriptor_ = descriptor;
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
void
|
||||
MapField<Key, T, KeyProto, ValueProto,
|
||||
default_enum_value>::SetAssignDescriptorCallback(void (*callback)()) {
|
||||
assign_descriptor_callback_ = callback;
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
void MapField<Key, T, KeyProto, ValueProto,
|
||||
default_enum_value>::SetDefaultEnumValue() {
|
||||
MutableInternalMap()->SetDefaultEnumValue(default_enum_value);
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>*
|
||||
MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEntry() const {
|
||||
// The MapEntry instance created here is only used in generated code for
|
||||
// parsing. It doesn't have default instance, descriptor or reflection,
|
||||
// because these are not needed in parsing and will prevent us from using it
|
||||
// for parsing MessageLite.
|
||||
return new EntryType();
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>*
|
||||
MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEntryWrapper(
|
||||
const Key& key, const T& t) const {
|
||||
return EntryType::Wrap(key, t);
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>*
|
||||
MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEnumEntryWrapper(
|
||||
const Key& key, const T t) const {
|
||||
return EntryType::EnumWrap(key, t);
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
const Map<Key, T>& MapField<Key, T, KeyProto, ValueProto,
|
||||
default_enum_value>::GetInternalMap() const {
|
||||
return *reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
Map<Key, T>* MapField<Key, T, KeyProto, ValueProto,
|
||||
default_enum_value>::MutableInternalMap() {
|
||||
return reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
void MapField<Key, T, KeyProto, ValueProto,
|
||||
default_enum_value>::SyncRepeatedFieldWithMapNoLock() const {
|
||||
if (repeated_field_ == NULL) {
|
||||
repeated_field_ = new RepeatedPtrField<Message>();
|
||||
}
|
||||
const Map<Key, T>& map =
|
||||
*static_cast<const Map<Key, T>*>(MapFieldBase::base_map_);
|
||||
RepeatedPtrField<EntryType>* repeated_field =
|
||||
reinterpret_cast<RepeatedPtrField<EntryType>*>(repeated_field_);
|
||||
|
||||
repeated_field->Clear();
|
||||
|
||||
for (typename Map<Key, T>::const_iterator it = map.begin();
|
||||
it != map.end(); ++it) {
|
||||
InitDefaultEntryOnce();
|
||||
GOOGLE_CHECK(default_entry_ != NULL);
|
||||
EntryType* new_entry = down_cast<EntryType*>(default_entry_->New());
|
||||
repeated_field->AddAllocated(new_entry);
|
||||
new_entry->set_key(it->first);
|
||||
new_entry->set_value(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
void MapField<Key, T, KeyProto, ValueProto,
|
||||
default_enum_value>::SyncMapWithRepeatedFieldNoLock() const {
|
||||
Map<Key, T>* map = reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
|
||||
RepeatedPtrField<EntryType>* repeated_field =
|
||||
reinterpret_cast<RepeatedPtrField<EntryType>*>(repeated_field_);
|
||||
map->clear();
|
||||
for (typename RepeatedPtrField<EntryType>::iterator it =
|
||||
repeated_field->begin(); it != repeated_field->end(); ++it) {
|
||||
// Cast is needed because Map's api and internal storage is different when
|
||||
// value is enum. For enum, we cannot cast an int to enum. Thus, we have to
|
||||
// copy value. For other types, they have same exposed api type and internal
|
||||
// stored type. We should not introduce value copy for them. We achieve this
|
||||
// by casting to value for enum while casting to reference for other types.
|
||||
(*map)[it->key()] = static_cast<CastValueType>(it->value());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
int MapField<Key, T, KeyProto, ValueProto,
|
||||
default_enum_value>::SpaceUsedExcludingSelfNoLock() const {
|
||||
int size = 0;
|
||||
if (repeated_field_ != NULL) {
|
||||
size += repeated_field_->SpaceUsedExcludingSelf();
|
||||
}
|
||||
Map<Key, T>* map = reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
|
||||
size += sizeof(*map);
|
||||
for (typename Map<Key, T>::iterator it = map->begin();
|
||||
it != map->end(); ++it) {
|
||||
size += KeyHandler::SpaceUsedInMap(it->first);
|
||||
size += ValHandler::SpaceUsedInMap(it->second);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
template <typename Key, typename T, FieldDescriptor::Type KeyProto,
|
||||
FieldDescriptor::Type ValueProto, int default_enum_value>
|
||||
void MapField<Key, T, KeyProto, ValueProto,
|
||||
default_enum_value>::InitDefaultEntryOnce() const {
|
||||
if (default_entry_ == NULL) {
|
||||
InitMetadataOnce();
|
||||
GOOGLE_CHECK(*entry_descriptor_ != NULL);
|
||||
default_entry_ = down_cast<const EntryType*>(
|
||||
MessageFactory::generated_factory()->GetPrototype(*entry_descriptor_));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_MAP_FIELD_INL_H__
|
470
src/google/protobuf/map_field_test.cc
Normal file
470
src/google/protobuf/map_field_test.cc
Normal file
@ -0,0 +1,470 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#ifndef _SHARED_PTR_H
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/map.h>
|
||||
#include <google/protobuf/map_unittest.pb.h>
|
||||
#include <google/protobuf/map_test_util.h>
|
||||
#include <google/protobuf/unittest.pb.h>
|
||||
#include <google/protobuf/map_field_inl.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace internal {
|
||||
|
||||
using unittest::TestAllTypes;
|
||||
|
||||
class MapFieldBaseStub : public MapFieldBase {
|
||||
public:
|
||||
void SyncRepeatedFieldWithMap() const {
|
||||
MapFieldBase::SyncRepeatedFieldWithMap();
|
||||
}
|
||||
void SyncMapWithRepeatedField() const {
|
||||
MapFieldBase::SyncMapWithRepeatedField();
|
||||
}
|
||||
// Get underlined repeated field without synchronizing map.
|
||||
RepeatedPtrField<Message>* InternalRepeatedField() {
|
||||
return repeated_field_;
|
||||
}
|
||||
// Get underlined map without synchronizing repeated field.
|
||||
template <typename MapType>
|
||||
const MapType& GetMap() {
|
||||
return *reinterpret_cast<MapType*>(base_map_);
|
||||
}
|
||||
// Get underlined map without synchronizing repeated field.
|
||||
template <typename MapType>
|
||||
MapType* MutableMap() {
|
||||
return reinterpret_cast<MapType*>(base_map_);
|
||||
}
|
||||
bool IsMapClean() { return state_ != 0; }
|
||||
bool IsRepeatedClean() { return state_ != 1; }
|
||||
void SetMapDirty() { state_ = 0; }
|
||||
void SetRepeatedDirty() { state_ = 1; }
|
||||
};
|
||||
|
||||
class MapFieldBasePrimitiveTest : public ::testing::Test {
|
||||
protected:
|
||||
typedef MapField<int32, int32, FieldDescriptor::TYPE_INT32,
|
||||
FieldDescriptor::TYPE_INT32> MapFieldType;
|
||||
|
||||
MapFieldBasePrimitiveTest() {
|
||||
// Get descriptors
|
||||
map_descriptor_ = unittest::TestMap::descriptor()
|
||||
->FindFieldByName("map_int32_int32")
|
||||
->message_type();
|
||||
key_descriptor_ = map_descriptor_->FindFieldByName("key");
|
||||
value_descriptor_ = map_descriptor_->FindFieldByName("value");
|
||||
|
||||
// Build map field
|
||||
default_entry_ =
|
||||
MessageFactory::generated_factory()->GetPrototype(map_descriptor_);
|
||||
map_field_.reset(new MapFieldType(default_entry_));
|
||||
map_field_base_ = map_field_.get();
|
||||
map_ = map_field_->MutableMap();
|
||||
initial_value_map_[0] = 100;
|
||||
initial_value_map_[1] = 101;
|
||||
map_->insert(initial_value_map_.begin(), initial_value_map_.end());
|
||||
EXPECT_EQ(2, map_->size());
|
||||
}
|
||||
|
||||
google::protobuf::scoped_ptr<MapFieldType> map_field_;
|
||||
MapFieldBase* map_field_base_;
|
||||
Map<int32, int32>* map_;
|
||||
const Descriptor* map_descriptor_;
|
||||
const FieldDescriptor* key_descriptor_;
|
||||
const FieldDescriptor* value_descriptor_;
|
||||
const Message* default_entry_;
|
||||
std::map<int32, int32> initial_value_map_; // copy of initial values inserted
|
||||
};
|
||||
|
||||
TEST_F(MapFieldBasePrimitiveTest, SpaceUsedExcludingSelf) {
|
||||
EXPECT_LT(0, map_field_base_->SpaceUsedExcludingSelf());
|
||||
}
|
||||
|
||||
TEST_F(MapFieldBasePrimitiveTest, GetRepeatedField) {
|
||||
const RepeatedPtrField<Message>& repeated =
|
||||
reinterpret_cast<const RepeatedPtrField<Message>&>(
|
||||
map_field_base_->GetRepeatedField());
|
||||
EXPECT_EQ(2, repeated.size());
|
||||
for (int i = 0; i < repeated.size(); i++) {
|
||||
const Message& message = repeated.Get(i);
|
||||
int key = message.GetReflection()->GetInt32(message, key_descriptor_);
|
||||
int value = message.GetReflection()->GetInt32(message, value_descriptor_);
|
||||
EXPECT_EQ(value, initial_value_map_[key]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(MapFieldBasePrimitiveTest, MutableRepeatedField) {
|
||||
RepeatedPtrField<Message>* repeated =
|
||||
reinterpret_cast<RepeatedPtrField<Message>*>(
|
||||
map_field_base_->MutableRepeatedField());
|
||||
EXPECT_EQ(2, repeated->size());
|
||||
for (int i = 0; i < repeated->size(); i++) {
|
||||
const Message& message = repeated->Get(i);
|
||||
int key = message.GetReflection()->GetInt32(message, key_descriptor_);
|
||||
int value = message.GetReflection()->GetInt32(message, value_descriptor_);
|
||||
EXPECT_EQ(value, initial_value_map_[key]);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
enum State { CLEAN, MAP_DIRTY, REPEATED_DIRTY };
|
||||
} // anonymous namespace
|
||||
|
||||
class MapFieldStateTest
|
||||
: public testing::TestWithParam<State> {
|
||||
public:
|
||||
protected:
|
||||
typedef MapField<int32, int32, FieldDescriptor::TYPE_INT32,
|
||||
FieldDescriptor::TYPE_INT32> MapFieldType;
|
||||
MapFieldStateTest() : state_(GetParam()) {
|
||||
// Build map field
|
||||
const Descriptor* map_descriptor =
|
||||
unittest::TestMap::descriptor()
|
||||
->FindFieldByName("map_int32_int32")
|
||||
->message_type();
|
||||
default_entry_ =
|
||||
MessageFactory::generated_factory()->GetPrototype(map_descriptor);
|
||||
map_field_.reset(new MapFieldType(default_entry_));
|
||||
map_field_base_ = map_field_.get();
|
||||
|
||||
Expect(map_field_.get(), MAP_DIRTY, 0, 0, true);
|
||||
switch (state_) {
|
||||
case CLEAN:
|
||||
AddOneStillClean(map_field_.get());
|
||||
break;
|
||||
case MAP_DIRTY:
|
||||
MakeMapDirty(map_field_.get());
|
||||
break;
|
||||
case REPEATED_DIRTY:
|
||||
MakeRepeatedDirty(map_field_.get());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AddOneStillClean(MapFieldType* map_field) {
|
||||
MapFieldBase* map_field_base = map_field;
|
||||
Map<int32, int32>* map = map_field->MutableMap();
|
||||
(*map)[0] = 0;
|
||||
map_field_base->GetRepeatedField();
|
||||
Expect(map_field, CLEAN, 1, 1, false);
|
||||
}
|
||||
|
||||
void MakeMapDirty(MapFieldType* map_field) {
|
||||
Map<int32, int32>* map = map_field->MutableMap();
|
||||
(*map)[0] = 0;
|
||||
Expect(map_field, MAP_DIRTY, 1, 0, true);
|
||||
}
|
||||
|
||||
void MakeRepeatedDirty(MapFieldType* map_field) {
|
||||
MakeMapDirty(map_field);
|
||||
MapFieldBase* map_field_base = map_field;
|
||||
map_field_base->MutableRepeatedField();
|
||||
MapFieldBaseStub* stub =
|
||||
reinterpret_cast<MapFieldBaseStub*>(map_field_base);
|
||||
Map<int32, int32>* map = stub->MutableMap<Map<int32, int32> >();
|
||||
map->clear();
|
||||
|
||||
Expect(map_field, REPEATED_DIRTY, 0, 1, false);
|
||||
}
|
||||
|
||||
void Expect(MapFieldType* map_field, State state, int map_size,
|
||||
int repeated_size, bool is_repeated_null) {
|
||||
MapFieldBase* map_field_base = map_field;
|
||||
MapFieldBaseStub* stub =
|
||||
reinterpret_cast<MapFieldBaseStub*>(map_field_base);
|
||||
|
||||
Map<int32, int32>* map = stub->MutableMap<Map<int32, int32> >();
|
||||
RepeatedPtrField<Message>* repeated_field = stub->InternalRepeatedField();
|
||||
|
||||
switch (state) {
|
||||
case MAP_DIRTY:
|
||||
EXPECT_FALSE(stub->IsMapClean());
|
||||
EXPECT_TRUE(stub->IsRepeatedClean());
|
||||
break;
|
||||
case REPEATED_DIRTY:
|
||||
EXPECT_TRUE(stub->IsMapClean());
|
||||
EXPECT_FALSE(stub->IsRepeatedClean());
|
||||
break;
|
||||
case CLEAN:
|
||||
EXPECT_TRUE(stub->IsMapClean());
|
||||
EXPECT_TRUE(stub->IsRepeatedClean());
|
||||
break;
|
||||
default:
|
||||
FAIL();
|
||||
}
|
||||
|
||||
EXPECT_EQ(map_size, map->size());
|
||||
if (is_repeated_null) {
|
||||
EXPECT_TRUE(repeated_field == NULL);
|
||||
} else {
|
||||
EXPECT_EQ(repeated_size, repeated_field->size());
|
||||
}
|
||||
}
|
||||
|
||||
google::protobuf::scoped_ptr<MapFieldType> map_field_;
|
||||
MapFieldBase* map_field_base_;
|
||||
State state_;
|
||||
const Message* default_entry_;
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(MapFieldStateTestInstance, MapFieldStateTest,
|
||||
::testing::Values(CLEAN, MAP_DIRTY, REPEATED_DIRTY));
|
||||
|
||||
TEST_P(MapFieldStateTest, GetMap) {
|
||||
map_field_->GetMap();
|
||||
if (state_ != MAP_DIRTY) {
|
||||
Expect(map_field_.get(), CLEAN, 1, 1, false);
|
||||
} else {
|
||||
Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(MapFieldStateTest, MutableMap) {
|
||||
map_field_->MutableMap();
|
||||
if (state_ != MAP_DIRTY) {
|
||||
Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
|
||||
} else {
|
||||
Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(MapFieldStateTest, MergeFromClean) {
|
||||
MapFieldType other(default_entry_);
|
||||
AddOneStillClean(&other);
|
||||
|
||||
map_field_->MergeFrom(other);
|
||||
|
||||
if (state_ != MAP_DIRTY) {
|
||||
Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
|
||||
} else {
|
||||
Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
|
||||
}
|
||||
|
||||
Expect(&other, CLEAN, 1, 1, false);
|
||||
}
|
||||
|
||||
TEST_P(MapFieldStateTest, MergeFromMapDirty) {
|
||||
MapFieldType other(default_entry_);
|
||||
MakeMapDirty(&other);
|
||||
|
||||
map_field_->MergeFrom(other);
|
||||
|
||||
if (state_ != MAP_DIRTY) {
|
||||
Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
|
||||
} else {
|
||||
Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
|
||||
}
|
||||
|
||||
Expect(&other, MAP_DIRTY, 1, 0, true);
|
||||
}
|
||||
|
||||
TEST_P(MapFieldStateTest, MergeFromRepeatedDirty) {
|
||||
MapFieldType other(default_entry_);
|
||||
MakeRepeatedDirty(&other);
|
||||
|
||||
map_field_->MergeFrom(other);
|
||||
|
||||
if (state_ != MAP_DIRTY) {
|
||||
Expect(map_field_.get(), MAP_DIRTY, 1, 1, false);
|
||||
} else {
|
||||
Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
|
||||
}
|
||||
|
||||
Expect(&other, CLEAN, 1, 1, false);
|
||||
}
|
||||
|
||||
TEST_P(MapFieldStateTest, SwapClean) {
|
||||
MapFieldType other(default_entry_);
|
||||
AddOneStillClean(&other);
|
||||
|
||||
map_field_->Swap(&other);
|
||||
|
||||
Expect(map_field_.get(), CLEAN, 1, 1, false);
|
||||
|
||||
switch (state_) {
|
||||
case CLEAN:
|
||||
Expect(&other, CLEAN, 1, 1, false);
|
||||
break;
|
||||
case MAP_DIRTY:
|
||||
Expect(&other, MAP_DIRTY, 1, 0, true);
|
||||
break;
|
||||
case REPEATED_DIRTY:
|
||||
Expect(&other, REPEATED_DIRTY, 0, 1, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(MapFieldStateTest, SwapMapDirty) {
|
||||
MapFieldType other(default_entry_);
|
||||
MakeMapDirty(&other);
|
||||
|
||||
map_field_->Swap(&other);
|
||||
|
||||
Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
|
||||
|
||||
switch (state_) {
|
||||
case CLEAN:
|
||||
Expect(&other, CLEAN, 1, 1, false);
|
||||
break;
|
||||
case MAP_DIRTY:
|
||||
Expect(&other, MAP_DIRTY, 1, 0, true);
|
||||
break;
|
||||
case REPEATED_DIRTY:
|
||||
Expect(&other, REPEATED_DIRTY, 0, 1, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(MapFieldStateTest, SwapRepeatedDirty) {
|
||||
MapFieldType other(default_entry_);
|
||||
MakeRepeatedDirty(&other);
|
||||
|
||||
map_field_->Swap(&other);
|
||||
|
||||
Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
|
||||
|
||||
switch (state_) {
|
||||
case CLEAN:
|
||||
Expect(&other, CLEAN, 1, 1, false);
|
||||
break;
|
||||
case MAP_DIRTY:
|
||||
Expect(&other, MAP_DIRTY, 1, 0, true);
|
||||
break;
|
||||
case REPEATED_DIRTY:
|
||||
Expect(&other, REPEATED_DIRTY, 0, 1, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(MapFieldStateTest, Clear) {
|
||||
map_field_->Clear();
|
||||
|
||||
if (state_ != MAP_DIRTY) {
|
||||
Expect(map_field_.get(), MAP_DIRTY, 0, 1, false);
|
||||
} else {
|
||||
Expect(map_field_.get(), MAP_DIRTY, 0, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(MapFieldStateTest, SpaceUsedExcludingSelf) {
|
||||
map_field_base_->SpaceUsedExcludingSelf();
|
||||
|
||||
switch (state_) {
|
||||
case CLEAN:
|
||||
Expect(map_field_.get(), CLEAN, 1, 1, false);
|
||||
break;
|
||||
case MAP_DIRTY:
|
||||
Expect(map_field_.get(), MAP_DIRTY, 1, 0, true);
|
||||
break;
|
||||
case REPEATED_DIRTY:
|
||||
Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(MapFieldStateTest, GetMapField) {
|
||||
map_field_base_->GetRepeatedField();
|
||||
|
||||
if (state_ != REPEATED_DIRTY) {
|
||||
Expect(map_field_.get(), CLEAN, 1, 1, false);
|
||||
} else {
|
||||
Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(MapFieldStateTest, MutableMapField) {
|
||||
map_field_base_->MutableRepeatedField();
|
||||
|
||||
if (state_ != REPEATED_DIRTY) {
|
||||
Expect(map_field_.get(), REPEATED_DIRTY, 1, 1, false);
|
||||
} else {
|
||||
Expect(map_field_.get(), REPEATED_DIRTY, 0, 1, false);
|
||||
}
|
||||
}
|
||||
|
||||
class MapFieldBaseStateStub : public MapFieldBaseStub {
|
||||
public:
|
||||
MapFieldBaseStateStub(Mutex* mutex, int* clean_counter,
|
||||
int* completed_counter)
|
||||
: mutex_(mutex),
|
||||
clean_counter_(clean_counter),
|
||||
completed_counter_(completed_counter) {}
|
||||
~MapFieldBaseStateStub() {}
|
||||
|
||||
protected:
|
||||
void SyncRepeatedFieldWithMapNoLock() const { Clean(); }
|
||||
void SyncMapWithRepeatedFieldNoLock() const { Clean(); }
|
||||
|
||||
private:
|
||||
void Clean() const {
|
||||
{
|
||||
MutexLock lock(mutex_);
|
||||
++(*clean_counter_);
|
||||
}
|
||||
struct timespec tm;
|
||||
tm.tv_sec = 0;
|
||||
tm.tv_nsec = 100000000; // 100ms
|
||||
nanosleep(&tm, NULL);
|
||||
{
|
||||
MutexLock lock(mutex_);
|
||||
// No other thread should have completed while this one was initializing.
|
||||
EXPECT_EQ(0, *completed_counter_);
|
||||
}
|
||||
}
|
||||
Mutex* mutex_;
|
||||
int* clean_counter_;
|
||||
int* completed_counter_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
39
src/google/protobuf/map_lite_unittest.proto
Normal file
39
src/google/protobuf/map_lite_unittest.proto
Normal file
@ -0,0 +1,39 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
package protobuf_unittest;
|
||||
|
||||
message MapLite {
|
||||
map<int32, int32> map_field = 1;
|
||||
}
|
68
src/google/protobuf/map_proto2_unittest.proto
Normal file
68
src/google/protobuf/map_proto2_unittest.proto
Normal file
@ -0,0 +1,68 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
|
||||
// We don't put this in a package within proto2 because we need to make sure
|
||||
// that the generated code doesn't depend on being in the proto2 namespace.
|
||||
// In map_test_util.h we do "using namespace unittest = protobuf_unittest".
|
||||
package protobuf_unittest;
|
||||
|
||||
enum Proto2MapEnum {
|
||||
PROTO2_MAP_ENUM_FOO = 0;
|
||||
PROTO2_MAP_ENUM_BAR = 1;
|
||||
PROTO2_MAP_ENUM_BAZ = 2;
|
||||
}
|
||||
|
||||
enum Proto2MapEnumPlusExtra {
|
||||
E_PROTO2_MAP_ENUM_FOO = 0;
|
||||
E_PROTO2_MAP_ENUM_BAR = 1;
|
||||
E_PROTO2_MAP_ENUM_BAZ = 2;
|
||||
E_PROTO2_MAP_ENUM_EXTRA = 3;
|
||||
}
|
||||
|
||||
enum Proto2MapEnumStartWithNonZero {
|
||||
PROTO2_NON_ZERO_MAP_ENUM_FOO = 1;
|
||||
}
|
||||
|
||||
message TestEnumMap {
|
||||
map<int32, Proto2MapEnum> known_map_field = 101;
|
||||
map<int32, Proto2MapEnum> unknown_map_field = 102;
|
||||
}
|
||||
|
||||
message TestEnumMapPlusExtra {
|
||||
map<int32, Proto2MapEnumPlusExtra> known_map_field = 101;
|
||||
map<int32, Proto2MapEnumPlusExtra> unknown_map_field = 102;
|
||||
}
|
||||
|
||||
message TestEnumStartWithNonZeroMap {
|
||||
map<int32, Proto2MapEnumStartWithNonZero> map_field = 101;
|
||||
}
|
2143
src/google/protobuf/map_test.cc
Normal file
2143
src/google/protobuf/map_test.cc
Normal file
File diff suppressed because it is too large
Load Diff
1479
src/google/protobuf/map_test_util.cc
Normal file
1479
src/google/protobuf/map_test_util.cc
Normal file
File diff suppressed because it is too large
Load Diff
149
src/google/protobuf/map_test_util.h
Normal file
149
src/google/protobuf/map_test_util.h
Normal file
@ -0,0 +1,149 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MAP_TEST_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_MAP_TEST_UTIL_H__
|
||||
|
||||
#include <google/protobuf/map_unittest.pb.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace unittest = ::protobuf_unittest;
|
||||
|
||||
class MapTestUtil {
|
||||
public:
|
||||
// Set every field in the message to a unique value.
|
||||
static void SetMapFields(unittest::TestMap* message);
|
||||
|
||||
// Set every field in the message to a default value.
|
||||
static void SetMapFieldsInitialized(unittest::TestMap* message);
|
||||
|
||||
// Modify all the map fields of the messsage (which should already have been
|
||||
// initialized with SetMapFields()).
|
||||
static void ModifyMapFields(unittest::TestMap* message);
|
||||
|
||||
// Check that all fields have the values that they should have after
|
||||
// SetMapFields() is called.
|
||||
static void ExpectMapFieldsSet(const unittest::TestMap& message);
|
||||
|
||||
// Check that all fields have the values that they should have after
|
||||
// SetMapFieldsInitialized() is called.
|
||||
static void ExpectMapFieldsSetInitialized(
|
||||
const unittest::TestMap& message);
|
||||
|
||||
// Expect that the message is modified as would be expected from
|
||||
// ModifyMapFields().
|
||||
static void ExpectMapFieldsModified(const unittest::TestMap& message);
|
||||
|
||||
// Check that all fields are empty.
|
||||
static void ExpectClear(const unittest::TestMap& message);
|
||||
|
||||
// Check that all map fields have the given size.
|
||||
static void ExpectMapsSize(const unittest::TestMap& message, int size);
|
||||
|
||||
// Get pointers of map entries at given index.
|
||||
static std::vector<const Message*> GetMapEntries(
|
||||
const unittest::TestMap& message, int index);
|
||||
|
||||
// Get pointers of map entries from release.
|
||||
static std::vector<const Message*> GetMapEntriesFromRelease(
|
||||
unittest::TestMap* message);
|
||||
|
||||
// Like above, but use the reflection interface.
|
||||
class MapReflectionTester {
|
||||
public:
|
||||
// base_descriptor must be a descriptor for TestMap, which is used for
|
||||
// MapReflectionTester to fetch the FieldDescriptors needed to use the
|
||||
// reflection interface.
|
||||
explicit MapReflectionTester(const Descriptor* base_descriptor);
|
||||
|
||||
void SetMapFieldsViaReflection(Message* message);
|
||||
void ClearMapFieldsViaReflection(Message* message);
|
||||
void ModifyMapFieldsViaReflection(Message* message);
|
||||
void RemoveLastMapsViaReflection(Message* message);
|
||||
void ReleaseLastMapsViaReflection(Message* message);
|
||||
void SwapMapsViaReflection(Message* message);
|
||||
void MutableUnknownFieldsOfMapFieldsViaReflection(Message* message);
|
||||
void ExpectMapFieldsSetViaReflection(const Message& message);
|
||||
void ExpectClearViaReflection(const Message& message);
|
||||
void ExpectMapEntryClearViaReflection(Message* message);
|
||||
|
||||
private:
|
||||
const FieldDescriptor* F(const string& name);
|
||||
|
||||
const Descriptor* base_descriptor_;
|
||||
|
||||
const EnumValueDescriptor* map_enum_bar_;
|
||||
const EnumValueDescriptor* map_enum_baz_;
|
||||
const EnumValueDescriptor* map_enum_foo_;
|
||||
|
||||
const FieldDescriptor* foreign_c_;
|
||||
const FieldDescriptor* map_int32_int32_key_;
|
||||
const FieldDescriptor* map_int32_int32_val_;
|
||||
const FieldDescriptor* map_int64_int64_key_;
|
||||
const FieldDescriptor* map_int64_int64_val_;
|
||||
const FieldDescriptor* map_uint32_uint32_key_;
|
||||
const FieldDescriptor* map_uint32_uint32_val_;
|
||||
const FieldDescriptor* map_uint64_uint64_key_;
|
||||
const FieldDescriptor* map_uint64_uint64_val_;
|
||||
const FieldDescriptor* map_sint32_sint32_key_;
|
||||
const FieldDescriptor* map_sint32_sint32_val_;
|
||||
const FieldDescriptor* map_sint64_sint64_key_;
|
||||
const FieldDescriptor* map_sint64_sint64_val_;
|
||||
const FieldDescriptor* map_fixed32_fixed32_key_;
|
||||
const FieldDescriptor* map_fixed32_fixed32_val_;
|
||||
const FieldDescriptor* map_fixed64_fixed64_key_;
|
||||
const FieldDescriptor* map_fixed64_fixed64_val_;
|
||||
const FieldDescriptor* map_sfixed32_sfixed32_key_;
|
||||
const FieldDescriptor* map_sfixed32_sfixed32_val_;
|
||||
const FieldDescriptor* map_sfixed64_sfixed64_key_;
|
||||
const FieldDescriptor* map_sfixed64_sfixed64_val_;
|
||||
const FieldDescriptor* map_int32_float_key_;
|
||||
const FieldDescriptor* map_int32_float_val_;
|
||||
const FieldDescriptor* map_int32_double_key_;
|
||||
const FieldDescriptor* map_int32_double_val_;
|
||||
const FieldDescriptor* map_bool_bool_key_;
|
||||
const FieldDescriptor* map_bool_bool_val_;
|
||||
const FieldDescriptor* map_string_string_key_;
|
||||
const FieldDescriptor* map_string_string_val_;
|
||||
const FieldDescriptor* map_int32_bytes_key_;
|
||||
const FieldDescriptor* map_int32_bytes_val_;
|
||||
const FieldDescriptor* map_int32_enum_key_;
|
||||
const FieldDescriptor* map_int32_enum_val_;
|
||||
const FieldDescriptor* map_int32_foreign_message_key_;
|
||||
const FieldDescriptor* map_int32_foreign_message_val_;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_MAP_TEST_UTIL_H__
|
486
src/google/protobuf/map_type_handler.h
Normal file
486
src/google/protobuf/map_type_handler.h
Normal file
@ -0,0 +1,486 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_TYPE_HANDLER_H__
|
||||
#define GOOGLE_PROTOBUF_TYPE_HANDLER_H__
|
||||
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Used for compile time type selection. MapIf::type will be TrueType if Flag is
|
||||
// true and FalseType otherwise.
|
||||
template<bool Flag, typename TrueType, typename FalseType>
|
||||
struct MapIf;
|
||||
|
||||
template<typename TrueType, typename FalseType>
|
||||
struct MapIf<true, TrueType, FalseType> {
|
||||
typedef TrueType type;
|
||||
};
|
||||
|
||||
template<typename TrueType, typename FalseType>
|
||||
struct MapIf<false, TrueType, FalseType> {
|
||||
typedef FalseType type;
|
||||
};
|
||||
|
||||
// In MapField, string and message are stored as pointer while others are stored
|
||||
// as object. However, google::protobuf::Map has unified api. Functions in this class
|
||||
// convert key/value to type wanted in api regardless how it's stored
|
||||
// internally.
|
||||
template <typename Type>
|
||||
class MapCommonTypeHandler {
|
||||
public:
|
||||
static inline Type& Reference(Type* x) { return *x; }
|
||||
static inline Type& Reference(Type& x) { return x; }
|
||||
static inline const Type& Reference(const Type& x) { return x; }
|
||||
static inline Type* Pointer(Type* x) { return x; }
|
||||
static inline Type* Pointer(Type& x) { return &x; }
|
||||
static inline const Type* Pointer(const Type* x) { return x; }
|
||||
static inline const Type* Pointer(const Type& x) { return &x; }
|
||||
};
|
||||
|
||||
// In proto2 Map, enum needs to be initialized to given default value, while
|
||||
// other types' default value can be inferred from the type.
|
||||
template <bool IsEnum, typename Type>
|
||||
class MapValueInitializer {
|
||||
public:
|
||||
static inline void Initialize(Type& type, int default_enum_value);
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
class MapValueInitializer<true, Type> {
|
||||
public:
|
||||
static inline void Initialize(Type& value, int default_enum_value) {
|
||||
value = static_cast<Type>(default_enum_value);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
class MapValueInitializer<false, Type> {
|
||||
public:
|
||||
static inline void Initialize(Type& value, int default_enum_value) {}
|
||||
};
|
||||
|
||||
// Handlers for key/value stored type in MapField. ==================
|
||||
|
||||
// Handler for message
|
||||
template <typename Type>
|
||||
class MapCppTypeHandler : public MapCommonTypeHandler<Type> {
|
||||
public:
|
||||
static const bool kIsStringOrMessage = true;
|
||||
// SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding
|
||||
// those already calculate in sizeof(MapField).
|
||||
static int SpaceUsedInMapEntry(const Type* value) {
|
||||
return value->SpaceUsed();
|
||||
}
|
||||
// Return bytes used by value in Map.
|
||||
static int SpaceUsedInMap(const Type& value) { return value.SpaceUsed(); }
|
||||
static inline void Clear(Type** value) {
|
||||
if (*value != NULL) (*value)->Type::Clear();
|
||||
}
|
||||
static inline void ClearMaybeByDefaultEnum(Type** value,
|
||||
int default_enum_value) {
|
||||
if (*value != NULL) (*value)->Type::Clear();
|
||||
}
|
||||
static inline void Merge(const Type& from, Type** to) {
|
||||
(*to)->MergeFrom(from);
|
||||
}
|
||||
|
||||
static void Delete(const Type* ptr) { delete ptr; }
|
||||
|
||||
// Assign default value to given instance.
|
||||
static inline void AssignDefaultValue(Type** value) {
|
||||
*value = const_cast<Type*>(&Type::default_instance());
|
||||
}
|
||||
// Initialize value when constructing MapEntry
|
||||
static inline void Initialize(Type** x) { *x = NULL; }
|
||||
// Same as above, but use default_enum_value to initialize enum type value.
|
||||
static inline void InitializeMaybeByDefaultEnum(
|
||||
Type** x, int default_enum_value) {
|
||||
*x = NULL;
|
||||
}
|
||||
// Initialize value for the first time mutable accessor is called.
|
||||
static inline void EnsureMutable(Type** value) {
|
||||
if (*value == NULL) *value = new Type;
|
||||
}
|
||||
// Return default instance if value is not initialized when calling const
|
||||
// reference accessor.
|
||||
static inline const Type& DefaultIfNotInitialized(Type* value,
|
||||
Type* default_value) {
|
||||
return value != NULL ? *value : *default_value;
|
||||
}
|
||||
// Check if all required fields have values set.
|
||||
static inline bool IsInitialized(Type* value) {
|
||||
return value->IsInitialized();
|
||||
}
|
||||
};
|
||||
|
||||
// Handler for string.
|
||||
template <>
|
||||
class MapCppTypeHandler<string> : public MapCommonTypeHandler<string> {
|
||||
public:
|
||||
static const bool kIsStringOrMessage = true;
|
||||
static inline void Merge(const string& from, string** to) { **to = from; }
|
||||
static inline void Clear(string** value) { (*value)->clear(); }
|
||||
static inline void ClearMaybeByDefaultEnum(string** value, int default_enum) {
|
||||
(*value)->clear();
|
||||
}
|
||||
static inline int SpaceUsedInMapEntry(const string* value) {
|
||||
return sizeof(*value) + StringSpaceUsedExcludingSelf(*value);
|
||||
}
|
||||
static inline int SpaceUsedInMap(const string& value) {
|
||||
return sizeof(value) + StringSpaceUsedExcludingSelf(value);
|
||||
}
|
||||
static void Delete(const string* ptr) {
|
||||
if (ptr != &::google::protobuf::internal::GetEmptyString()) delete ptr;
|
||||
}
|
||||
static inline void AssignDefaultValue(string** value) {}
|
||||
static inline void Initialize(string** value) {
|
||||
*value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
|
||||
}
|
||||
static inline void InitializeMaybeByDefaultEnum(
|
||||
string** value, int default_enum_value) {
|
||||
*value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
|
||||
}
|
||||
static inline void EnsureMutable(string** value) {
|
||||
if (*value == &::google::protobuf::internal::GetEmptyString()) *value = new string;
|
||||
}
|
||||
static inline const string& DefaultIfNotInitialized(string* value,
|
||||
string* default_value) {
|
||||
return value != default_value ? *value : *default_value;
|
||||
}
|
||||
static inline bool IsInitialized(string* value) { return true; }
|
||||
};
|
||||
|
||||
// Base class for primitive type handlers.
|
||||
template <typename Type>
|
||||
class MapPrimitiveTypeHandler : public MapCommonTypeHandler<Type> {
|
||||
public:
|
||||
static const bool kIsStringOrMessage = false;
|
||||
static inline void Delete(const Type& x) {}
|
||||
static inline void Merge(const Type& from, Type* to) { *to = from; }
|
||||
static inline int SpaceUsedInMapEntry(const Type& value) { return 0; }
|
||||
static inline int SpaceUsedInMap(const Type& value) { return sizeof(Type); }
|
||||
static inline void AssignDefaultValue(Type* value) {}
|
||||
static inline const Type& DefaultIfNotInitialized(
|
||||
const Type& value, const Type& default_value) {
|
||||
return value;
|
||||
}
|
||||
static inline bool IsInitialized(const Type& value) { return true; }
|
||||
};
|
||||
|
||||
// Handlers for primitive types.
|
||||
#define PRIMITIVE_HANDLER(CType) \
|
||||
template <> \
|
||||
class MapCppTypeHandler<CType> : public MapPrimitiveTypeHandler<CType> { \
|
||||
public: \
|
||||
static inline void Clear(CType* value) { *value = 0; } \
|
||||
static inline void ClearMaybeByDefaultEnum(CType* value, \
|
||||
int default_enum_value) { \
|
||||
*value = static_cast<CType>(default_enum_value); \
|
||||
} \
|
||||
static inline void Initialize(CType* value) { *value = 0; } \
|
||||
static inline void InitializeMaybeByDefaultEnum(CType* value, \
|
||||
int default_enum_value) { \
|
||||
*value = static_cast<CType>(default_enum_value); \
|
||||
} \
|
||||
static inline void EnsureMutable(CType* value) {} \
|
||||
};
|
||||
|
||||
PRIMITIVE_HANDLER(int32 )
|
||||
PRIMITIVE_HANDLER(int64 )
|
||||
PRIMITIVE_HANDLER(uint32)
|
||||
PRIMITIVE_HANDLER(uint64)
|
||||
PRIMITIVE_HANDLER(double)
|
||||
PRIMITIVE_HANDLER(float )
|
||||
PRIMITIVE_HANDLER(bool )
|
||||
|
||||
#undef PRIMITIVE_HANDLER
|
||||
|
||||
// Define constants for given proto field type
|
||||
template <FieldDescriptor::Type Type>
|
||||
class MapFieldTypeTraits {};
|
||||
|
||||
#define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \
|
||||
template <> \
|
||||
class MapFieldTypeTraits<FieldDescriptor::TYPE_##FieldType> { \
|
||||
public: \
|
||||
typedef CType CppType; \
|
||||
static const bool kIsMessage = IsMessage; \
|
||||
static const bool kIsEnum = IsEnum; \
|
||||
static const WireFormatLite::WireType kWireType = \
|
||||
WireFormatLite::WIRETYPE_##WireFormatType; \
|
||||
};
|
||||
|
||||
TYPE_TRAITS(MESSAGE , Message, LENGTH_DELIMITED, true, false)
|
||||
TYPE_TRAITS(STRING , string , LENGTH_DELIMITED, false, false)
|
||||
TYPE_TRAITS(BYTES , string , LENGTH_DELIMITED, false, false)
|
||||
TYPE_TRAITS(INT64 , int64 , VARINT , false, false)
|
||||
TYPE_TRAITS(UINT64 , uint64 , VARINT , false, false)
|
||||
TYPE_TRAITS(INT32 , int32 , VARINT , false, false)
|
||||
TYPE_TRAITS(UINT32 , uint32 , VARINT , false, false)
|
||||
TYPE_TRAITS(SINT64 , int64 , VARINT , false, false)
|
||||
TYPE_TRAITS(SINT32 , int32 , VARINT , false, false)
|
||||
TYPE_TRAITS(ENUM , int , VARINT , false, true )
|
||||
TYPE_TRAITS(DOUBLE , double , FIXED64, false, false)
|
||||
TYPE_TRAITS(FLOAT , float , FIXED32, false, false)
|
||||
TYPE_TRAITS(FIXED64 , uint64 , FIXED64, false, false)
|
||||
TYPE_TRAITS(FIXED32 , uint32 , FIXED32, false, false)
|
||||
TYPE_TRAITS(SFIXED64, int64 , FIXED64, false, false)
|
||||
TYPE_TRAITS(SFIXED32, int32 , FIXED32, false, false)
|
||||
TYPE_TRAITS(BOOL , bool , VARINT , false, false)
|
||||
|
||||
#undef TYPE_TRAITS
|
||||
|
||||
// Handler for proto field type. Define types and constants used in compile
|
||||
// time. Also define functions used in parsing and serializing.
|
||||
template <FieldDescriptor::Type Type>
|
||||
class MapProtoTypeHandler {
|
||||
public:
|
||||
// Internal stored type in MapEntry for given proto field type.
|
||||
typedef typename MapFieldTypeTraits<Type>::CppType CppType;
|
||||
|
||||
// Whether given type is a message.
|
||||
static const bool kIsMessage = MapFieldTypeTraits<Type>::kIsMessage;
|
||||
|
||||
// Whether given type is an enum.
|
||||
static const bool kIsEnum = MapFieldTypeTraits<Type>::kIsEnum;
|
||||
|
||||
// The wire type of given proto field type.
|
||||
static const WireFormatLite::WireType kWireType =
|
||||
MapFieldTypeTraits<Type>::kWireType;
|
||||
|
||||
// Functions used in parsing and serialization. ===================
|
||||
|
||||
template <typename ValueType>
|
||||
static inline int ByteSize(const ValueType& value);
|
||||
template <typename ValueType>
|
||||
static inline int GetCachedSize(const ValueType& value);
|
||||
static inline void Write(int field, const CppType& value,
|
||||
io::CodedOutputStream* output);
|
||||
static inline uint8* WriteToArray(int field, const CppType& value,
|
||||
uint8* output);
|
||||
template <typename ValueType>
|
||||
static inline bool Read(io::CodedInputStream* input, ValueType* value);
|
||||
};
|
||||
|
||||
template <>
|
||||
template <typename ValueType>
|
||||
inline int MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::ByteSize(
|
||||
const ValueType& value) {
|
||||
return WireFormatLite::MessageSizeNoVirtual(value);
|
||||
}
|
||||
|
||||
#define BYTE_SIZE(FieldType, DeclaredType) \
|
||||
template <> \
|
||||
template <typename ValueType> \
|
||||
inline int MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::ByteSize( \
|
||||
const ValueType& value) { \
|
||||
return WireFormatLite::DeclaredType##Size(value); \
|
||||
}
|
||||
|
||||
BYTE_SIZE(STRING, String)
|
||||
BYTE_SIZE(BYTES , Bytes)
|
||||
BYTE_SIZE(INT64 , Int64)
|
||||
BYTE_SIZE(UINT64, UInt64)
|
||||
BYTE_SIZE(INT32 , Int32)
|
||||
BYTE_SIZE(UINT32, UInt32)
|
||||
BYTE_SIZE(SINT64, SInt64)
|
||||
BYTE_SIZE(SINT32, SInt32)
|
||||
BYTE_SIZE(ENUM , Enum)
|
||||
|
||||
#undef BYTE_SIZE
|
||||
|
||||
#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \
|
||||
template <> \
|
||||
template <typename ValueType> \
|
||||
inline int MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::ByteSize( \
|
||||
const ValueType& value) { \
|
||||
return WireFormatLite::k##DeclaredType##Size; \
|
||||
}
|
||||
|
||||
FIXED_BYTE_SIZE(DOUBLE , Double)
|
||||
FIXED_BYTE_SIZE(FLOAT , Float)
|
||||
FIXED_BYTE_SIZE(FIXED64 , Fixed64)
|
||||
FIXED_BYTE_SIZE(FIXED32 , Fixed32)
|
||||
FIXED_BYTE_SIZE(SFIXED64, SFixed64)
|
||||
FIXED_BYTE_SIZE(SFIXED32, SFixed32)
|
||||
FIXED_BYTE_SIZE(BOOL , Bool)
|
||||
|
||||
#undef FIXED_BYTE_SIZE
|
||||
|
||||
template <>
|
||||
template <typename ValueType>
|
||||
inline int MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::GetCachedSize(
|
||||
const ValueType& value) {
|
||||
return WireFormatLite::LengthDelimitedSize(value.GetCachedSize());
|
||||
}
|
||||
|
||||
#define GET_CACHED_SIZE(FieldType, DeclaredType) \
|
||||
template <> \
|
||||
template <typename ValueType> \
|
||||
inline int \
|
||||
MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::GetCachedSize( \
|
||||
const ValueType& value) { \
|
||||
return WireFormatLite::DeclaredType##Size(value); \
|
||||
}
|
||||
|
||||
GET_CACHED_SIZE(STRING, String)
|
||||
GET_CACHED_SIZE(BYTES , Bytes)
|
||||
GET_CACHED_SIZE(INT64 , Int64)
|
||||
GET_CACHED_SIZE(UINT64, UInt64)
|
||||
GET_CACHED_SIZE(INT32 , Int32)
|
||||
GET_CACHED_SIZE(UINT32, UInt32)
|
||||
GET_CACHED_SIZE(SINT64, SInt64)
|
||||
GET_CACHED_SIZE(SINT32, SInt32)
|
||||
GET_CACHED_SIZE(ENUM , Enum)
|
||||
|
||||
#undef GET_CACHED_SIZE
|
||||
|
||||
#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \
|
||||
template <> \
|
||||
template <typename ValueType> \
|
||||
inline int \
|
||||
MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::GetCachedSize( \
|
||||
const ValueType& value) { \
|
||||
return WireFormatLite::k##DeclaredType##Size; \
|
||||
}
|
||||
|
||||
GET_FIXED_CACHED_SIZE(DOUBLE , Double)
|
||||
GET_FIXED_CACHED_SIZE(FLOAT , Float)
|
||||
GET_FIXED_CACHED_SIZE(FIXED64 , Fixed64)
|
||||
GET_FIXED_CACHED_SIZE(FIXED32 , Fixed32)
|
||||
GET_FIXED_CACHED_SIZE(SFIXED64, SFixed64)
|
||||
GET_FIXED_CACHED_SIZE(SFIXED32, SFixed32)
|
||||
GET_FIXED_CACHED_SIZE(BOOL , Bool)
|
||||
|
||||
#undef GET_FIXED_CACHED_SIZE
|
||||
|
||||
template <>
|
||||
inline void MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::Write(
|
||||
int field, const Message& value, io::CodedOutputStream* output) {
|
||||
WireFormatLite::WriteMessageMaybeToArray(field, value, output);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint8* MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::WriteToArray(
|
||||
int field, const Message& value, uint8* output) {
|
||||
return WireFormatLite::WriteMessageToArray(field, value, output);
|
||||
}
|
||||
|
||||
#define WRITE_METHOD(FieldType, DeclaredType) \
|
||||
template <> \
|
||||
inline void MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::Write( \
|
||||
int field, const CppType& value, io::CodedOutputStream* output) { \
|
||||
return WireFormatLite::Write##DeclaredType(field, value, output); \
|
||||
} \
|
||||
template <> \
|
||||
inline uint8* \
|
||||
MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::WriteToArray( \
|
||||
int field, const CppType& value, uint8* output) { \
|
||||
return WireFormatLite::Write##DeclaredType##ToArray(field, value, output); \
|
||||
}
|
||||
|
||||
WRITE_METHOD(STRING , String)
|
||||
WRITE_METHOD(BYTES , Bytes)
|
||||
WRITE_METHOD(INT64 , Int64)
|
||||
WRITE_METHOD(UINT64 , UInt64)
|
||||
WRITE_METHOD(INT32 , Int32)
|
||||
WRITE_METHOD(UINT32 , UInt32)
|
||||
WRITE_METHOD(SINT64 , SInt64)
|
||||
WRITE_METHOD(SINT32 , SInt32)
|
||||
WRITE_METHOD(ENUM , Enum)
|
||||
WRITE_METHOD(DOUBLE , Double)
|
||||
WRITE_METHOD(FLOAT , Float)
|
||||
WRITE_METHOD(FIXED64 , Fixed64)
|
||||
WRITE_METHOD(FIXED32 , Fixed32)
|
||||
WRITE_METHOD(SFIXED64, SFixed64)
|
||||
WRITE_METHOD(SFIXED32, SFixed32)
|
||||
WRITE_METHOD(BOOL , Bool)
|
||||
|
||||
#undef WRITE_METHOD
|
||||
|
||||
template <>
|
||||
template <typename ValueType>
|
||||
inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::Read(
|
||||
io::CodedInputStream* input, ValueType* value) {
|
||||
return WireFormatLite::ReadMessageNoVirtual(input, value);
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename ValueType>
|
||||
inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_STRING>::Read(
|
||||
io::CodedInputStream* input, ValueType* value) {
|
||||
return WireFormatLite::ReadString(input, value);
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename ValueType>
|
||||
inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_BYTES>::Read(
|
||||
io::CodedInputStream* input, ValueType* value) {
|
||||
return WireFormatLite::ReadBytes(input, value);
|
||||
}
|
||||
|
||||
#define READ_METHOD(FieldType) \
|
||||
template <> \
|
||||
template <typename ValueType> \
|
||||
inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::Read( \
|
||||
io::CodedInputStream* input, ValueType* value) { \
|
||||
return WireFormatLite::ReadPrimitive<CppType, \
|
||||
WireFormatLite::TYPE_##FieldType>( \
|
||||
input, value); \
|
||||
}
|
||||
|
||||
READ_METHOD(INT64)
|
||||
READ_METHOD(UINT64)
|
||||
READ_METHOD(INT32)
|
||||
READ_METHOD(UINT32)
|
||||
READ_METHOD(SINT64)
|
||||
READ_METHOD(SINT32)
|
||||
READ_METHOD(ENUM)
|
||||
READ_METHOD(DOUBLE)
|
||||
READ_METHOD(FLOAT)
|
||||
READ_METHOD(FIXED64)
|
||||
READ_METHOD(FIXED32)
|
||||
READ_METHOD(SFIXED64)
|
||||
READ_METHOD(SFIXED32)
|
||||
READ_METHOD(BOOL)
|
||||
|
||||
#undef READ_METHOD
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_TYPE_HANDLER_H__
|
77
src/google/protobuf/map_unittest.proto
Normal file
77
src/google/protobuf/map_unittest.proto
Normal file
@ -0,0 +1,77 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
|
||||
import "google/protobuf/unittest.proto";
|
||||
|
||||
// We don't put this in a package within proto2 because we need to make sure
|
||||
// that the generated code doesn't depend on being in the proto2 namespace.
|
||||
// In map_test_util.h we do "using namespace unittest = protobuf_unittest".
|
||||
package protobuf_unittest;
|
||||
|
||||
// Tests maps.
|
||||
message TestMap {
|
||||
map<int32 , int32 > map_int32_int32 = 1;
|
||||
map<int64 , int64 > map_int64_int64 = 2;
|
||||
map<uint32 , uint32 > map_uint32_uint32 = 3;
|
||||
map<uint64 , uint64 > map_uint64_uint64 = 4;
|
||||
map<sint32 , sint32 > map_sint32_sint32 = 5;
|
||||
map<sint64 , sint64 > map_sint64_sint64 = 6;
|
||||
map<fixed32 , fixed32 > map_fixed32_fixed32 = 7;
|
||||
map<fixed64 , fixed64 > map_fixed64_fixed64 = 8;
|
||||
map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
|
||||
map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
|
||||
map<int32 , float > map_int32_float = 11;
|
||||
map<int32 , double > map_int32_double = 12;
|
||||
map<bool , bool > map_bool_bool = 13;
|
||||
map<string , string > map_string_string = 14;
|
||||
map<int32 , bytes > map_int32_bytes = 15;
|
||||
map<int32 , MapEnum > map_int32_enum = 16;
|
||||
map<int32 , ForeignMessage> map_int32_foreign_message = 17;
|
||||
}
|
||||
|
||||
message TestMessageMap {
|
||||
map<int32, TestAllTypes> map_int32_message = 1;
|
||||
}
|
||||
|
||||
// Two map fields share the same entry default instance.
|
||||
message TestSameTypeMap {
|
||||
map<int32, int32> map1 = 1;
|
||||
map<int32, int32> map2 = 2;
|
||||
}
|
||||
|
||||
|
||||
enum MapEnum {
|
||||
MAP_ENUM_FOO = 0;
|
||||
MAP_ENUM_BAR = 1;
|
||||
MAP_ENUM_BAZ = 2;
|
||||
}
|
@ -430,7 +430,11 @@ const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor(
|
||||
}
|
||||
break;
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::get();
|
||||
if (field->is_map()) {
|
||||
return internal::Singleton<internal::MapFieldAccessor>::get();
|
||||
} else {
|
||||
return internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::get();
|
||||
}
|
||||
}
|
||||
GOOGLE_LOG(FATAL) << "Should not reach here.";
|
||||
return NULL;
|
||||
|
@ -110,7 +110,7 @@ TEST(PreserveUnknownEnumTest, PreserveParseAndSerializeDynamicMessage) {
|
||||
string serialized = orig_message.SerializeAsString();
|
||||
|
||||
google::protobuf::DynamicMessageFactory factory;
|
||||
scoped_ptr<google::protobuf::Message> message(factory.GetPrototype(
|
||||
google::protobuf::scoped_ptr<google::protobuf::Message> message(factory.GetPrototype(
|
||||
proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New());
|
||||
EXPECT_EQ(true, message->ParseFromString(serialized));
|
||||
message->DiscardUnknownFields();
|
||||
|
@ -175,7 +175,7 @@ TEST(ArenaTest, ReleaseMessage) {
|
||||
Arena arena;
|
||||
TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
|
||||
arena_message->mutable_optional_nested_message()->set_bb(118);
|
||||
scoped_ptr<TestAllTypes::NestedMessage> nested(
|
||||
google::protobuf::scoped_ptr<TestAllTypes::NestedMessage> nested(
|
||||
arena_message->release_optional_nested_message());
|
||||
EXPECT_EQ(118, nested->bb());
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#ifndef GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
|
||||
#define GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
|
||||
|
||||
#include <google/protobuf/map_field.h>
|
||||
#include <google/protobuf/reflection.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
|
||||
@ -199,6 +200,73 @@ class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor {
|
||||
Value* scratch_space) const = 0;
|
||||
};
|
||||
|
||||
// An implementation of RandomAccessRepeatedFieldAccessor that manipulates
|
||||
// MapFieldBase.
|
||||
class MapFieldAccessor : public RandomAccessRepeatedFieldAccessor {
|
||||
public:
|
||||
MapFieldAccessor() {}
|
||||
virtual ~MapFieldAccessor() {}
|
||||
virtual bool IsEmpty(const Field* data) const {
|
||||
return GetRepeatedField(data)->empty();
|
||||
}
|
||||
virtual int Size(const Field* data) const {
|
||||
return GetRepeatedField(data)->size();
|
||||
}
|
||||
virtual const Value* Get(const Field* data, int index,
|
||||
Value* scratch_space) const {
|
||||
return ConvertFromEntry(GetRepeatedField(data)->Get(index), scratch_space);
|
||||
}
|
||||
virtual void Clear(Field* data) const {
|
||||
MutableRepeatedField(data)->Clear();
|
||||
}
|
||||
virtual void Set(Field* data, int index, const Value* value) const {
|
||||
ConvertToEntry(value, MutableRepeatedField(data)->Mutable(index));
|
||||
}
|
||||
virtual void Add(Field* data, const Value* value) const {
|
||||
Message* allocated = New(value);
|
||||
ConvertToEntry(value, allocated);
|
||||
MutableRepeatedField(data)->AddAllocated(allocated);
|
||||
}
|
||||
virtual void RemoveLast(Field* data) const {
|
||||
MutableRepeatedField(data)->RemoveLast();
|
||||
}
|
||||
virtual void SwapElements(Field* data, int index1, int index2) const {
|
||||
MutableRepeatedField(data)->SwapElements(index1, index2);
|
||||
}
|
||||
virtual void Swap(
|
||||
Field* data,
|
||||
const internal::RepeatedFieldAccessor* other_mutator,
|
||||
Field* other_data) const {
|
||||
GOOGLE_CHECK(this == other_mutator);
|
||||
MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef RepeatedPtrField<Message> RepeatedFieldType;
|
||||
static const RepeatedFieldType* GetRepeatedField(const Field* data) {
|
||||
return reinterpret_cast<const RepeatedFieldType*>(
|
||||
(&reinterpret_cast<const MapFieldBase*>(data)->GetRepeatedField()));
|
||||
}
|
||||
static RepeatedFieldType* MutableRepeatedField(Field* data) {
|
||||
return reinterpret_cast<RepeatedFieldType*>(
|
||||
reinterpret_cast<MapFieldBase*>(data)->MutableRepeatedField());
|
||||
}
|
||||
virtual Message* New(const Value* value) const {
|
||||
return static_cast<const Message*>(value)->New();
|
||||
}
|
||||
// Convert an object received by this accessor to an MapEntry message to be
|
||||
// stored in the underlying MapFieldBase.
|
||||
virtual void ConvertToEntry(const Value* value, Message* result) const {
|
||||
result->CopyFrom(*static_cast<const Message*>(value));
|
||||
}
|
||||
// Convert a MapEntry message stored in the underlying MapFieldBase to an
|
||||
// object that will be returned by this accessor.
|
||||
virtual const Value* ConvertFromEntry(const Message& value,
|
||||
Value* scratch_space) const {
|
||||
return static_cast<const Value*>(&value);
|
||||
}
|
||||
};
|
||||
|
||||
// Default implementations of RepeatedFieldAccessor for primitive types.
|
||||
template<typename T>
|
||||
class RepeatedFieldPrimitiveAccessor : public RepeatedFieldWrapper<T> {
|
||||
|
@ -86,7 +86,7 @@ inline int CalculateReserve(Iter begin, Iter end, std::forward_iterator_tag) {
|
||||
|
||||
template <typename Iter>
|
||||
inline int CalculateReserve(Iter /*begin*/, Iter /*end*/,
|
||||
std::input_iterator_tag) {
|
||||
std::input_iterator_tag /*unused*/) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -349,6 +349,11 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
|
||||
// use of AddFromCleared(), which is not part of the public interface.
|
||||
friend class ExtensionSet;
|
||||
|
||||
// The MapFieldBase implementation needs to call protected methods directly,
|
||||
// reinterpreting pointers as being to Message instead of a specific Message
|
||||
// subclass.
|
||||
friend class MapFieldBase;
|
||||
|
||||
// To parse directly into a proto2 generated class, the upb class GMR_Handlers
|
||||
// needs to be able to modify a RepeatedPtrFieldBase directly.
|
||||
friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers;
|
||||
|
@ -231,7 +231,7 @@ class RepeatedFieldRefIterator
|
||||
const void* data_;
|
||||
const RepeatedFieldAccessor* accessor_;
|
||||
void* iterator_;
|
||||
scoped_ptr<AccessorValueType> scratch_space_;
|
||||
google::protobuf::scoped_ptr<AccessorValueType> scratch_space_;
|
||||
};
|
||||
|
||||
// TypeTraits that maps the type parameter T of RepeatedFieldRef or
|
||||
|
@ -686,7 +686,7 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefDynamicMessage) {
|
||||
desc->FindFieldByName("repeated_int32");
|
||||
|
||||
DynamicMessageFactory factory;
|
||||
scoped_ptr<Message> dynamic_message(factory.GetPrototype(desc)->New());
|
||||
google::protobuf::scoped_ptr<Message> dynamic_message(factory.GetPrototype(desc)->New());
|
||||
const Reflection* refl = dynamic_message->GetReflection();
|
||||
|
||||
MutableRepeatedFieldRef<int32> rf_int32 =
|
||||
|
@ -267,6 +267,8 @@ static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF);
|
||||
#endif
|
||||
|
||||
#define GOOGLE_GUARDED_BY(x)
|
||||
#define GOOGLE_FALLTHROUGH_INTENDED
|
||||
#define GOOGLE_ATTRIBUTE_COLD
|
||||
|
||||
// x86 and x86-64 can perform unaligned loads/stores directly.
|
||||
#if defined(_M_X64) || defined(__x86_64__) || \
|
||||
|
@ -271,7 +271,7 @@ class LIBPROTOBUF_EXPORT TextFormat {
|
||||
|
||||
bool print_message_fields_in_index_order_;
|
||||
|
||||
scoped_ptr<const FieldValuePrinter> default_field_value_printer_;
|
||||
google::protobuf::scoped_ptr<const FieldValuePrinter> default_field_value_printer_;
|
||||
typedef map<const FieldDescriptor*,
|
||||
const FieldValuePrinter*> CustomPrinterMap;
|
||||
CustomPrinterMap custom_printers_;
|
||||
|
@ -41,6 +41,7 @@ syntax = "proto2";
|
||||
option cc_generic_services = true; // auto-added
|
||||
option java_generic_services = true; // auto-added
|
||||
option py_generic_services = true; // auto-added
|
||||
option cc_enable_arenas = true;
|
||||
|
||||
import "google/protobuf/unittest_import.proto";
|
||||
|
||||
|
@ -34,6 +34,7 @@ import "google/protobuf/unittest_no_arena_import.proto";
|
||||
|
||||
package proto2_arena_unittest;
|
||||
|
||||
option cc_enable_arenas = true;
|
||||
|
||||
message NestedMessage {
|
||||
optional int32 d = 1;
|
||||
|
@ -43,6 +43,7 @@ syntax = "proto2";
|
||||
package protobuf_unittest_import;
|
||||
|
||||
option optimize_for = SPEED;
|
||||
option cc_enable_arenas = true;
|
||||
|
||||
// Exercise the java_package option.
|
||||
option java_package = "com.google.protobuf.test";
|
||||
|
@ -37,6 +37,7 @@
|
||||
syntax = "proto2";
|
||||
package protobuf_unittest;
|
||||
|
||||
option cc_enable_arenas = true;
|
||||
option optimize_for = SPEED;
|
||||
|
||||
// A message with message_set_wire_format.
|
||||
|
@ -43,6 +43,7 @@ syntax = "proto2";
|
||||
option cc_generic_services = true; // auto-added
|
||||
option java_generic_services = true; // auto-added
|
||||
option py_generic_services = true; // auto-added
|
||||
option cc_enable_arenas = false;
|
||||
|
||||
import "google/protobuf/unittest_import.proto";
|
||||
import "google/protobuf/unittest_arena.proto";
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
option cc_enable_arenas = true;
|
||||
|
||||
import "google/protobuf/unittest_import.proto";
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user