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@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/java/java_field.h>
36#include <google/protobuf/compiler/java/java_helpers.h>
37#include <google/protobuf/compiler/java/java_primitive_field.h>
38#include <google/protobuf/compiler/java/java_enum_field.h>
39#include <google/protobuf/compiler/java/java_message_field.h>
40#include <google/protobuf/compiler/java/java_string_field.h>
41#include <google/protobuf/stubs/common.h>
42
43namespace google {
44namespace protobuf {
45namespace compiler {
46namespace java {
47
48FieldGenerator::~FieldGenerator() {}
49
50void FieldGenerator::GenerateParsingCodeFromPacked(io::Printer* printer) const {
51  // Reaching here indicates a bug. Cases are:
52  //   - This FieldGenerator should support packing, but this method should be
53  //     overridden.
54  //   - This FieldGenerator doesn't support packing, and this method should
55  //     never have been called.
56  GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() "
57             << "called on field generator that does not support packing.";
58}
59
60FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
61  : descriptor_(descriptor),
62    field_generators_(
63      new scoped_ptr<FieldGenerator>[descriptor->field_count()]),
64    extension_generators_(
65      new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
66
67  // Construct all the FieldGenerators and assign them bit indices for their
68  // bit fields.
69  int messageBitIndex = 0;
70  int builderBitIndex = 0;
71  for (int i = 0; i < descriptor->field_count(); i++) {
72    FieldGenerator* generator = MakeGenerator(descriptor->field(i),
73        messageBitIndex, builderBitIndex);
74    field_generators_[i].reset(generator);
75    messageBitIndex += generator->GetNumBitsForMessage();
76    builderBitIndex += generator->GetNumBitsForBuilder();
77  }
78  for (int i = 0; i < descriptor->extension_count(); i++) {
79    FieldGenerator* generator = MakeGenerator(descriptor->extension(i),
80        messageBitIndex, builderBitIndex);
81    extension_generators_[i].reset(generator);
82    messageBitIndex += generator->GetNumBitsForMessage();
83    builderBitIndex += generator->GetNumBitsForBuilder();
84  }
85}
86
87FieldGenerator* FieldGeneratorMap::MakeGenerator(
88    const FieldDescriptor* field, int messageBitIndex, int builderBitIndex) {
89  if (field->is_repeated()) {
90    switch (GetJavaType(field)) {
91      case JAVATYPE_MESSAGE:
92        return new RepeatedMessageFieldGenerator(
93            field, messageBitIndex, builderBitIndex);
94      case JAVATYPE_ENUM:
95        return new RepeatedEnumFieldGenerator(
96            field, messageBitIndex, builderBitIndex);
97      case JAVATYPE_STRING:
98        return new RepeatedStringFieldGenerator(
99            field, messageBitIndex, builderBitIndex);
100      default:
101        return new RepeatedPrimitiveFieldGenerator(
102            field, messageBitIndex, builderBitIndex);
103    }
104  } else {
105    switch (GetJavaType(field)) {
106      case JAVATYPE_MESSAGE:
107        return new MessageFieldGenerator(
108            field, messageBitIndex, builderBitIndex);
109      case JAVATYPE_ENUM:
110        return new EnumFieldGenerator(
111            field, messageBitIndex, builderBitIndex);
112      case JAVATYPE_STRING:
113        return new StringFieldGenerator(
114            field, messageBitIndex, builderBitIndex);
115      default:
116        return new PrimitiveFieldGenerator(
117            field, messageBitIndex, builderBitIndex);
118    }
119  }
120}
121
122FieldGeneratorMap::~FieldGeneratorMap() {}
123
124const FieldGenerator& FieldGeneratorMap::get(
125    const FieldDescriptor* field) const {
126  GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
127  return *field_generators_[field->index()];
128}
129
130const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
131  return *extension_generators_[index];
132}
133
134}  // namespace java
135}  // namespace compiler
136}  // namespace protobuf
137}  // namespace google
138