aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler/cpp/cpp_map_field.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/compiler/cpp/cpp_map_field.cc')
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.cc255
1 files changed, 255 insertions, 0 deletions
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
new file mode 100644
index 00000000..0154eeb8
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -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