Home | History | Annotate | Download | only in javanano
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // http://code.google.com/p/protobuf/
      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 (at) google.com (Kenton Varda)
     32 //  Based on original Protocol Buffers design by
     33 //  Sanjay Ghemawat, Jeff Dean, and others.
     34 
     35 #include <google/protobuf/compiler/javanano/javanano_field.h>
     36 #include <google/protobuf/compiler/javanano/javanano_helpers.h>
     37 #include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
     38 #include <google/protobuf/compiler/javanano/javanano_enum_field.h>
     39 #include <google/protobuf/compiler/javanano/javanano_map_field.h>
     40 #include <google/protobuf/compiler/javanano/javanano_message_field.h>
     41 #include <google/protobuf/stubs/common.h>
     42 
     43 namespace google {
     44 namespace protobuf {
     45 namespace compiler {
     46 namespace javanano {
     47 
     48 FieldGenerator::~FieldGenerator() {}
     49 
     50 bool FieldGenerator::SavedDefaultNeeded() const {
     51   // No saved default for this field by default.
     52   // Subclasses whose instances may need saved defaults will override this
     53   // and return the appropriate value.
     54   return false;
     55 }
     56 
     57 void FieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
     58   // No saved default for this field by default.
     59   // Subclasses whose instances may need saved defaults will override this
     60   // and generate the appropriate init code to the printer.
     61 }
     62 
     63 void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const {
     64   // Reaching here indicates a bug. Cases are:
     65   //   - This FieldGenerator should support packing, but this method should be
     66   //     overridden.
     67   //   - This FieldGenerator doesn't support packing, and this method should
     68   //     never have been called.
     69   GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() "
     70              << "called on field generator that does not support packing.";
     71 }
     72 
     73 // =============================================
     74 
     75 FieldGeneratorMap::FieldGeneratorMap(
     76     const Descriptor* descriptor, const Params &params)
     77   : descriptor_(descriptor),
     78     field_generators_(
     79       new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
     80 
     81   int next_has_bit_index = 0;
     82   bool saved_defaults_needed = false;
     83   // Construct all the FieldGenerators.
     84   for (int i = 0; i < descriptor->field_count(); i++) {
     85     FieldGenerator* field_generator = MakeGenerator(
     86         descriptor->field(i), params, &next_has_bit_index);
     87     saved_defaults_needed = saved_defaults_needed
     88         || field_generator->SavedDefaultNeeded();
     89     field_generators_[i].reset(field_generator);
     90   }
     91   total_bits_ = next_has_bit_index;
     92   saved_defaults_needed_ = saved_defaults_needed;
     93 }
     94 
     95 FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
     96     const Params &params, int* next_has_bit_index) {
     97   JavaType java_type = GetJavaType(field);
     98   if (field->is_repeated()) {
     99     switch (java_type) {
    100       case JAVATYPE_MESSAGE:
    101         if (IsMapEntry(field->message_type())) {
    102           return new MapFieldGenerator(field, params);
    103         } else {
    104           return new RepeatedMessageFieldGenerator(field, params);
    105         }
    106       case JAVATYPE_ENUM:
    107         return new RepeatedEnumFieldGenerator(field, params);
    108       default:
    109         return new RepeatedPrimitiveFieldGenerator(field, params);
    110     }
    111   } else if (field->containing_oneof()) {
    112     switch (java_type) {
    113       case JAVATYPE_MESSAGE:
    114         return new MessageOneofFieldGenerator(field, params);
    115       case JAVATYPE_ENUM:
    116       default:
    117         return new PrimitiveOneofFieldGenerator(field, params);
    118     }
    119   } else if (params.optional_field_accessors() && field->is_optional()
    120       && java_type != JAVATYPE_MESSAGE) {
    121     // We need a has-bit for each primitive/enum field because their default
    122     // values could be same as explicitly set values. But we don't need it
    123     // for a message field because they have no defaults and Nano uses 'null'
    124     // for unset messages, which cannot be set explicitly.
    125     switch (java_type) {
    126       case JAVATYPE_ENUM:
    127         return new AccessorEnumFieldGenerator(
    128             field, params, (*next_has_bit_index)++);
    129       default:
    130         return new AccessorPrimitiveFieldGenerator(
    131             field, params, (*next_has_bit_index)++);
    132     }
    133   } else {
    134     switch (java_type) {
    135       case JAVATYPE_MESSAGE:
    136         return new MessageFieldGenerator(field, params);
    137       case JAVATYPE_ENUM:
    138         return new EnumFieldGenerator(field, params);
    139       default:
    140         return new PrimitiveFieldGenerator(field, params);
    141     }
    142   }
    143 }
    144 
    145 FieldGeneratorMap::~FieldGeneratorMap() {}
    146 
    147 const FieldGenerator& FieldGeneratorMap::get(
    148     const FieldDescriptor* field) const {
    149   GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
    150   return *field_generators_[field->index()];
    151 }
    152 
    153 void SetCommonOneofVariables(const FieldDescriptor* descriptor,
    154                              map<string, string>* variables) {
    155   (*variables)["oneof_name"] =
    156       UnderscoresToCamelCase(descriptor->containing_oneof());
    157   (*variables)["oneof_capitalized_name"] =
    158       UnderscoresToCapitalizedCamelCase(descriptor->containing_oneof());
    159   (*variables)["oneof_index"] =
    160       SimpleItoa(descriptor->containing_oneof()->index());
    161   (*variables)["set_oneof_case"] =
    162       "this." + (*variables)["oneof_name"] +
    163       "Case_ = " + SimpleItoa(descriptor->number());
    164   (*variables)["clear_oneof_case"] =
    165       "this." + (*variables)["oneof_name"] + "Case_ = 0";
    166   (*variables)["has_oneof_case"] =
    167       "this." + (*variables)["oneof_name"] + "Case_ == " +
    168       SimpleItoa(descriptor->number());
    169 }
    170 
    171 void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
    172                               const map<string, string>& variables,
    173                               io::Printer* printer) {
    174   if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
    175     printer->Print(variables,
    176       "if (this.has$capitalized_name$()) {\n"
    177       "  if (!java.util.Arrays.equals((byte[]) this.$oneof_name$_,\n"
    178       "                               (byte[]) other.$oneof_name$_)) {\n"
    179       "    return false;\n"
    180       "  }\n"
    181       "}\n");
    182   } else {
    183     printer->Print(variables,
    184       "if (this.has$capitalized_name$()) {\n"
    185       "  if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n"
    186       "    return false;\n"
    187       "  }\n"
    188       "}\n");
    189   }
    190 }
    191 
    192 void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
    193                                 const map<string, string>& variables,
    194                                 io::Printer* printer) {
    195   if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
    196     printer->Print(variables,
    197       "result = 31 * result + ($has_oneof_case$\n"
    198       "   ? java.util.Arrays.hashCode((byte[]) this.$oneof_name$_) : 0);\n");
    199   } else {
    200     printer->Print(variables,
    201       "result = 31 * result +\n"
    202       "  ($has_oneof_case$ ? this.$oneof_name$_.hashCode() : 0);\n");
    203   }
    204 }
    205 
    206 }  // namespace javanano
    207 }  // namespace compiler
    208 }  // namespace protobuf
    209 }  // namespace google
    210