LCOV - code coverage report
Current view: top level - third_party/protobuf/src/google/protobuf/compiler/csharp - csharp_helpers.cc (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 0 148 0.0 %
Date: 2015-10-10 Functions: 0 18 0.0 %

          Line data    Source code
       1             : // Protocol Buffers - Google's data interchange format
       2             : // Copyright 2008 Google Inc.  All rights reserved.
       3             : // https://developers.google.com/protocol-buffers/
       4             : //
       5             : // Redistribution and use in source and binary forms, with or without
       6             : // modification, are permitted provided that the following conditions are
       7             : // met:
       8             : //
       9             : //     * Redistributions of source code must retain the above copyright
      10             : // notice, this list of conditions and the following disclaimer.
      11             : //     * Redistributions in binary form must reproduce the above
      12             : // copyright notice, this list of conditions and the following disclaimer
      13             : // in the documentation and/or other materials provided with the
      14             : // distribution.
      15             : //     * Neither the name of Google Inc. nor the names of its
      16             : // contributors may be used to endorse or promote products derived from
      17             : // this software without specific prior written permission.
      18             : //
      19             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      20             : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      21             : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      22             : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      23             : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      24             : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      25             : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      26             : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      27             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      28             : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      29             : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      30             : 
      31             : // Author: kenton@google.com (Kenton Varda)
      32             : //  Based on original Protocol Buffers design by
      33             : //  Sanjay Ghemawat, Jeff Dean, and others.
      34             : 
      35             : #include <algorithm>
      36             : #include <google/protobuf/stubs/hash.h>
      37             : #include <limits>
      38             : #include <vector>
      39             : 
      40             : #include <google/protobuf/compiler/csharp/csharp_helpers.h>
      41             : #include <google/protobuf/descriptor.pb.h>
      42             : #include <google/protobuf/io/printer.h>
      43             : #include <google/protobuf/wire_format.h>
      44             : #include <google/protobuf/stubs/strutil.h>
      45             : #include <google/protobuf/stubs/substitute.h>
      46             : 
      47             : #include <google/protobuf/compiler/csharp/csharp_field_base.h>
      48             : #include <google/protobuf/compiler/csharp/csharp_enum_field.h>
      49             : #include <google/protobuf/compiler/csharp/csharp_map_field.h>
      50             : #include <google/protobuf/compiler/csharp/csharp_message_field.h>
      51             : #include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
      52             : #include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
      53             : #include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h>
      54             : #include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h>
      55             : #include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
      56             : 
      57             : namespace google {
      58             : namespace protobuf {
      59             : namespace compiler {
      60             : namespace csharp {
      61             : 
      62           0 : CSharpType GetCSharpType(FieldDescriptor::Type type) {
      63           0 :   switch (type) {
      64             :     case FieldDescriptor::TYPE_INT32:
      65             :       return CSHARPTYPE_INT32;
      66             :     case FieldDescriptor::TYPE_INT64:
      67           0 :       return CSHARPTYPE_INT64;
      68             :     case FieldDescriptor::TYPE_UINT32:
      69           0 :       return CSHARPTYPE_UINT32;
      70             :     case FieldDescriptor::TYPE_UINT64:
      71           0 :       return CSHARPTYPE_UINT32;
      72             :     case FieldDescriptor::TYPE_SINT32:
      73             :       return CSHARPTYPE_INT32;
      74             :     case FieldDescriptor::TYPE_SINT64:
      75           0 :       return CSHARPTYPE_INT64;
      76             :     case FieldDescriptor::TYPE_FIXED32:
      77           0 :       return CSHARPTYPE_UINT32;
      78             :     case FieldDescriptor::TYPE_FIXED64:
      79           0 :       return CSHARPTYPE_UINT64;
      80             :     case FieldDescriptor::TYPE_SFIXED32:
      81             :       return CSHARPTYPE_INT32;
      82             :     case FieldDescriptor::TYPE_SFIXED64:
      83           0 :       return CSHARPTYPE_INT64;
      84             :     case FieldDescriptor::TYPE_FLOAT:
      85           0 :       return CSHARPTYPE_FLOAT;
      86             :     case FieldDescriptor::TYPE_DOUBLE:
      87           0 :       return CSHARPTYPE_DOUBLE;
      88             :     case FieldDescriptor::TYPE_BOOL:
      89           0 :       return CSHARPTYPE_BOOL;
      90             :     case FieldDescriptor::TYPE_ENUM:
      91           0 :       return CSHARPTYPE_ENUM;
      92             :     case FieldDescriptor::TYPE_STRING:
      93           0 :       return CSHARPTYPE_STRING;
      94             :     case FieldDescriptor::TYPE_BYTES:
      95           0 :       return CSHARPTYPE_BYTESTRING;
      96             :     case FieldDescriptor::TYPE_GROUP:
      97           0 :       return CSHARPTYPE_MESSAGE;
      98             :     case FieldDescriptor::TYPE_MESSAGE:
      99           0 :       return CSHARPTYPE_MESSAGE;
     100             : 
     101             :       // No default because we want the compiler to complain if any new
     102             :       // types are added.
     103             :   }
     104           0 :   GOOGLE_LOG(FATAL)<< "Can't get here.";
     105           0 :   return (CSharpType) -1;
     106             : }
     107             : 
     108           0 : std::string StripDotProto(const std::string& proto_file) {
     109           0 :   int lastindex = proto_file.find_last_of(".");
     110           0 :   return proto_file.substr(0, lastindex);
     111             : }
     112             : 
     113           0 : std::string GetFileNamespace(const FileDescriptor* descriptor) {
     114           0 :   if (descriptor->options().has_csharp_namespace()) {
     115           0 :     return descriptor->options().csharp_namespace();
     116             :   }
     117           0 :   return UnderscoresToCamelCase(descriptor->package(), true, true);
     118             : }
     119             : 
     120           0 : std::string GetUmbrellaClassUnqualifiedName(const FileDescriptor* descriptor) {
     121             :   // We manually rename Descriptor to DescriptorProtoFile to avoid collisions with
     122             :   // the static Descriptor property. It would be nice to be able to do this with an
     123             :   // option, but it would be rarely used.
     124           0 :   if (IsDescriptorProto(descriptor)) {
     125           0 :     return "DescriptorProtoFile";
     126             :   }
     127             :   // umbrella_classname can no longer be set using message option.
     128           0 :   std::string proto_file = descriptor->name();
     129           0 :   int lastslash = proto_file.find_last_of("/");
     130           0 :   std::string base = proto_file.substr(lastslash + 1);
     131           0 :   return UnderscoresToPascalCase(StripDotProto(base));
     132             : }
     133             : 
     134           0 : std::string GetUmbrellaClassNestedNamespace(const FileDescriptor* descriptor) {
     135             :   // TODO(jtattermusch): reintroduce csharp_umbrella_namespace option
     136           0 :   bool collision = false;
     137           0 :   std::string umbrella_classname = GetUmbrellaClassUnqualifiedName(descriptor);
     138           0 :   for(int i = 0; i < descriptor->message_type_count(); i++) {
     139           0 :     if (descriptor->message_type(i)->name() == umbrella_classname) {
     140             :       collision = true;
     141             :       break;
     142             :     }
     143             :   }
     144           0 :   for (int i = 0; i < descriptor->service_count(); i++) {
     145           0 :     if (descriptor->service(i)->name() == umbrella_classname) {
     146             :       collision = true;
     147             :       break;
     148             :     }
     149             :   }
     150           0 :   for (int i = 0; i < descriptor->enum_type_count(); i++) {
     151           0 :     if (descriptor->enum_type(i)->name() == umbrella_classname) {
     152             :       collision = true;
     153             :       break;
     154             :     }
     155             :   }
     156           0 :   return collision ? "Proto" : "";
     157             : }
     158             : 
     159             : // TODO(jtattermusch): can we reuse a utility function?
     160           0 : std::string UnderscoresToCamelCase(const std::string& input,
     161             :                                    bool cap_next_letter,
     162             :                                    bool preserve_period) {
     163             :   string result;
     164             :   // Note:  I distrust ctype.h due to locales.
     165           0 :   for (int i = 0; i < input.size(); i++) {
     166           0 :     if ('a' <= input[i] && input[i] <= 'z') {
     167           0 :       if (cap_next_letter) {
     168           0 :         result += input[i] + ('A' - 'a');
     169             :       } else {
     170           0 :         result += input[i];
     171             :       }
     172             :       cap_next_letter = false;
     173           0 :     } else if ('A' <= input[i] && input[i] <= 'Z') {
     174           0 :       if (i == 0 && !cap_next_letter) {
     175             :         // Force first letter to lower-case unless explicitly told to
     176             :         // capitalize it.
     177           0 :         result += input[i] + ('a' - 'A');
     178             :       } else {
     179             :         // Capital letters after the first are left as-is.
     180           0 :         result += input[i];
     181             :       }
     182             :       cap_next_letter = false;
     183           0 :     } else if ('0' <= input[i] && input[i] <= '9') {
     184           0 :       result += input[i];
     185             :       cap_next_letter = true;
     186             :     } else {
     187           0 :       cap_next_letter = true;
     188           0 :       if (input[i] == '.' && preserve_period) {
     189             :         result += '.';
     190             :       }
     191             :     }
     192             :   }
     193             :   // Add a trailing "_" if the name should be altered.
     194           0 :   if (input[input.size() - 1] == '#') {
     195             :     result += '_';
     196             :   }
     197           0 :   return result;
     198             : }
     199             : 
     200           0 : std::string UnderscoresToPascalCase(const std::string& input) {
     201           0 :   return UnderscoresToCamelCase(input, true);
     202             : }
     203             : 
     204           0 : std::string ToCSharpName(const std::string& name, const FileDescriptor* file) {
     205           0 :   std::string result = GetFileNamespace(file);
     206           0 :   if (result != "") {
     207             :     result += '.';
     208             :   }
     209             :   string classname;
     210           0 :   if (file->package().empty()) {
     211             :     classname = name;
     212             :   } else {
     213             :     // Strip the proto package from full_name since we've replaced it with
     214             :     // the C# namespace.
     215           0 :     classname = name.substr(file->package().size() + 1);
     216             :   }
     217           0 :   result += StringReplace(classname, ".", ".Types.", true);
     218           0 :   return "global::" + result;
     219             : }
     220             : 
     221           0 : std::string GetUmbrellaClassName(const FileDescriptor* descriptor) {
     222           0 :   std::string result = GetFileNamespace(descriptor);
     223           0 :   if (!result.empty()) {
     224             :     result += '.';
     225             :   }
     226           0 :   std::string umbrellaNamespace = GetUmbrellaClassNestedNamespace(descriptor);
     227           0 :   if (!umbrellaNamespace.empty()) {
     228           0 :       result += umbrellaNamespace + ".";
     229             :   }
     230           0 :   result += GetUmbrellaClassUnqualifiedName(descriptor);
     231           0 :   return "global::" + result;
     232             : }
     233             : 
     234           0 : std::string GetClassName(const Descriptor* descriptor) {
     235           0 :   return ToCSharpName(descriptor->full_name(), descriptor->file());
     236             : }
     237             : 
     238           0 : std::string GetClassName(const EnumDescriptor* descriptor) {
     239           0 :   return ToCSharpName(descriptor->full_name(), descriptor->file());
     240             : }
     241             : 
     242             : // Groups are hacky:  The name of the field is just the lower-cased name
     243             : // of the group type.  In C#, though, we would like to retain the original
     244             : // capitalization of the type name.
     245           0 : std::string GetFieldName(const FieldDescriptor* descriptor) {
     246           0 :   if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
     247           0 :     return descriptor->message_type()->name();
     248             :   } else {
     249           0 :     return descriptor->name();
     250             :   }
     251             : }
     252             : 
     253           0 : std::string GetFieldConstantName(const FieldDescriptor* field) {
     254           0 :   return GetPropertyName(field) + "FieldNumber";
     255             : }
     256             : 
     257           0 : std::string GetPropertyName(const FieldDescriptor* descriptor) {
     258             :   // TODO(jtattermusch): consider introducing csharp_property_name field option
     259           0 :   std::string property_name = UnderscoresToPascalCase(GetFieldName(descriptor));
     260             :   // Avoid either our own type name or reserved names. Note that not all names
     261             :   // are reserved - a field called to_string, write_to etc would still cause a problem.
     262             :   // There are various ways of ending up with naming collisions, but we try to avoid obvious
     263             :   // ones.
     264           0 :   if (property_name == descriptor->containing_type()->name()
     265           0 :       || property_name == "Types"
     266           0 :       || property_name == "Descriptor") {
     267             :     property_name += "_";
     268             :   }
     269           0 :   return property_name;
     270             : }
     271             : 
     272             : // TODO: c&p from Java protoc plugin
     273             : // For encodings with fixed sizes, returns that size in bytes.  Otherwise
     274             : // returns -1.
     275           0 : int GetFixedSize(FieldDescriptor::Type type) {
     276           0 :   switch (type) {
     277             :     case FieldDescriptor::TYPE_INT32   : return -1;
     278             :     case FieldDescriptor::TYPE_INT64   : return -1;
     279             :     case FieldDescriptor::TYPE_UINT32  : return -1;
     280             :     case FieldDescriptor::TYPE_UINT64  : return -1;
     281             :     case FieldDescriptor::TYPE_SINT32  : return -1;
     282             :     case FieldDescriptor::TYPE_SINT64  : return -1;
     283           0 :     case FieldDescriptor::TYPE_FIXED32 : return internal::WireFormatLite::kFixed32Size;
     284           0 :     case FieldDescriptor::TYPE_FIXED64 : return internal::WireFormatLite::kFixed64Size;
     285           0 :     case FieldDescriptor::TYPE_SFIXED32: return internal::WireFormatLite::kSFixed32Size;
     286           0 :     case FieldDescriptor::TYPE_SFIXED64: return internal::WireFormatLite::kSFixed64Size;
     287           0 :     case FieldDescriptor::TYPE_FLOAT   : return internal::WireFormatLite::kFloatSize;
     288           0 :     case FieldDescriptor::TYPE_DOUBLE  : return internal::WireFormatLite::kDoubleSize;
     289             : 
     290           0 :     case FieldDescriptor::TYPE_BOOL    : return internal::WireFormatLite::kBoolSize;
     291             :     case FieldDescriptor::TYPE_ENUM    : return -1;
     292             : 
     293             :     case FieldDescriptor::TYPE_STRING  : return -1;
     294             :     case FieldDescriptor::TYPE_BYTES   : return -1;
     295             :     case FieldDescriptor::TYPE_GROUP   : return -1;
     296             :     case FieldDescriptor::TYPE_MESSAGE : return -1;
     297             : 
     298             :     // No default because we want the compiler to complain if any new
     299             :     // types are added.
     300             :   }
     301           0 :   GOOGLE_LOG(FATAL) << "Can't get here.";
     302           0 :   return -1;
     303             : }
     304             : 
     305             : static const char base64_chars[] =
     306             :     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     307             : 
     308           0 : std::string StringToBase64(const std::string& input) {
     309             :   std::string result;
     310           0 :   size_t remaining = input.size();
     311           0 :   const unsigned char *src = (const unsigned char*) input.c_str();
     312           0 :   while (remaining > 2) {
     313           0 :     result += base64_chars[src[0] >> 2];
     314           0 :     result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)];
     315           0 :     result += base64_chars[((src[1] & 0xf) << 2) | (src[2] >> 6)];
     316           0 :     result += base64_chars[src[2] & 0x3f];
     317           0 :     remaining -= 3;
     318           0 :     src += 3;
     319             :   }
     320           0 :   switch (remaining) {
     321             :     case 2:
     322           0 :       result += base64_chars[src[0] >> 2];
     323           0 :       result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)];
     324           0 :       result += base64_chars[(src[1] & 0xf) << 2];
     325             :       result += '=';
     326             :       src += 2;
     327             :       break;
     328             :     case 1:
     329           0 :       result += base64_chars[src[0] >> 2];
     330           0 :       result += base64_chars[((src[0] & 0x3) << 4)];
     331             :       result += '=';
     332             :       result += '=';
     333             :       src += 1;
     334             :       break;
     335             :   }
     336           0 :   return result;
     337             : }
     338             : 
     339           0 : std::string FileDescriptorToBase64(const FileDescriptor* descriptor) {
     340             :   std::string fdp_bytes;
     341           0 :   FileDescriptorProto fdp;
     342           0 :   descriptor->CopyTo(&fdp);
     343           0 :   fdp.SerializeToString(&fdp_bytes);
     344           0 :   return StringToBase64(fdp_bytes);
     345             : }
     346             : 
     347           0 : FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
     348             :                                          int fieldOrdinal) {
     349           0 :   switch (descriptor->type()) {
     350             :     case FieldDescriptor::TYPE_GROUP:
     351             :     case FieldDescriptor::TYPE_MESSAGE:
     352           0 :       if (descriptor->is_repeated()) {
     353           0 :         if (descriptor->is_map()) {
     354           0 :           return new MapFieldGenerator(descriptor, fieldOrdinal);
     355             :         } else {
     356           0 :           return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal);
     357             :         }
     358             :       } else {
     359           0 :         if (IsWrapperType(descriptor)) {
     360           0 :           if (descriptor->containing_oneof()) {
     361           0 :             return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal);
     362             :           } else {
     363           0 :             return new WrapperFieldGenerator(descriptor, fieldOrdinal);
     364             :           }
     365             :         } else {
     366           0 :           if (descriptor->containing_oneof()) {
     367           0 :             return new MessageOneofFieldGenerator(descriptor, fieldOrdinal);
     368             :           } else {
     369           0 :             return new MessageFieldGenerator(descriptor, fieldOrdinal);
     370             :           }
     371             :         }
     372             :       }
     373             :     case FieldDescriptor::TYPE_ENUM:
     374           0 :       if (descriptor->is_repeated()) {
     375           0 :         return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal);
     376             :       } else {
     377           0 :         if (descriptor->containing_oneof()) {
     378           0 :           return new EnumOneofFieldGenerator(descriptor, fieldOrdinal);
     379             :         } else {
     380           0 :           return new EnumFieldGenerator(descriptor, fieldOrdinal);
     381             :         }
     382             :       }
     383             :     default:
     384           0 :       if (descriptor->is_repeated()) {
     385           0 :         return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal);
     386             :       } else {
     387           0 :         if (descriptor->containing_oneof()) {
     388           0 :           return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal);
     389             :         } else {
     390           0 :           return new PrimitiveFieldGenerator(descriptor, fieldOrdinal);
     391             :         }
     392             :       }
     393             :   }
     394             : }
     395             : 
     396             : }  // namespace csharp
     397             : }  // namespace compiler
     398             : }  // namespace protobuf
     399             : }  // namespace google

Generated by: LCOV version 1.10