1e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// Protocol Buffers - Google's data interchange format
2e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// Copyright 2008 Google Inc.  All rights reserved.
3e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// http://code.google.com/p/protobuf/
4e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//
5e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// Redistribution and use in source and binary forms, with or without
6e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// modification, are permitted provided that the following conditions are
7e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// met:
8e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//
9e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//     * Redistributions of source code must retain the above copyright
10e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// notice, this list of conditions and the following disclaimer.
11e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//     * Redistributions in binary form must reproduce the above
12e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// copyright notice, this list of conditions and the following disclaimer
13e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// in the documentation and/or other materials provided with the
14e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// distribution.
15e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//     * Neither the name of Google Inc. nor the names of its
16e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// contributors may be used to endorse or promote products derived from
17e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// this software without specific prior written permission.
18e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//
19e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
31e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville// Author: kenton@google.com (Kenton Varda)
32e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//  Based on original Protocol Buffers design by
33e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville//  Sanjay Ghemawat, Jeff Dean, and others.
34e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
350f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith#include <limits>
36e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville#include <vector>
37e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
38e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
39e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville#include <google/protobuf/compiler/javamicro/javamicro_params.h>
40e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville#include <google/protobuf/descriptor.pb.h>
41e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville#include <google/protobuf/stubs/strutil.h>
42e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville#include <google/protobuf/stubs/substitute.h>
43e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
44e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillenamespace google {
45e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillenamespace protobuf {
46e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillenamespace compiler {
47e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillenamespace javamicro {
48e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
49e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savilleconst char kThickSeparator[] =
50e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  "// ===================================================================\n";
51e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savilleconst char kThinSeparator[] =
52e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  "// -------------------------------------------------------------------\n";
53e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
54e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillenamespace {
55e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
56e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savilleconst char* kDefaultPackage = "";
57e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
58e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savilleconst string& FieldName(const FieldDescriptor* field) {
59e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // Groups are hacky:  The name of the field is just the lower-cased name
60e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // of the group type.  In Java, though, we would like to retain the original
61e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // capitalization of the type name.
62e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (field->type() == FieldDescriptor::TYPE_GROUP) {
63e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return field->message_type()->name();
64e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  } else {
65e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return field->name();
66e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
67e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
68e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
69e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) {
70e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  string result;
71e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // Note:  I distrust ctype.h due to locales.
72e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  for (int i = 0; i < input.size(); i++) {
73e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if ('a' <= input[i] && input[i] <= 'z') {
74e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if (cap_next_letter) {
75e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        result += input[i] + ('A' - 'a');
76e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      } else {
77e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        result += input[i];
78e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
79e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      cap_next_letter = false;
80e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else if ('A' <= input[i] && input[i] <= 'Z') {
81e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if (i == 0 && !cap_next_letter) {
82e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        // Force first letter to lower-case unless explicitly told to
83e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        // capitalize it.
84e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        result += input[i] + ('a' - 'A');
85e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      } else {
86e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        // Capital letters after the first are left as-is.
87e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        result += input[i];
88e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
89e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      cap_next_letter = false;
90e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else if ('0' <= input[i] && input[i] <= '9') {
91e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      result += input[i];
92e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      cap_next_letter = true;
93e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else {
94e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      cap_next_letter = true;
95e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
96e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
97e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return result;
98e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
99e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
100e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}  // namespace
101e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
102e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring UnderscoresToCamelCase(const FieldDescriptor* field) {
103e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return UnderscoresToCamelCaseImpl(FieldName(field), false);
104e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
105e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
106e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
107e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return UnderscoresToCamelCaseImpl(FieldName(field), true);
108e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
109e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
110e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring UnderscoresToCamelCase(const MethodDescriptor* method) {
111e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return UnderscoresToCamelCaseImpl(method->name(), false);
112e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
113e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
114e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring StripProto(const string& filename) {
115e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (HasSuffixString(filename, ".protodevel")) {
116e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return StripSuffixString(filename, ".protodevel");
117e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  } else {
118e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return StripSuffixString(filename, ".proto");
119e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
120e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
121e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
122e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring FileClassName(const Params& params, const FileDescriptor* file) {
123e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (params.has_java_outer_classname(file->name())) {
124624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    return params.java_outer_classname(file->name());
125e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  } else {
126624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    // Use the filename itself with underscores removed
127624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    // and a CamelCase style name.
128624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    string basename;
129624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    string::size_type last_slash = file->name().find_last_of('/');
130624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    if (last_slash == string::npos) {
131624c448fbef20a1a2fad2289f622b468c25763d1Max Cai      basename = file->name();
132e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    } else {
133624c448fbef20a1a2fad2289f622b468c25763d1Max Cai      basename = file->name().substr(last_slash + 1);
134e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
135624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    return UnderscoresToCamelCaseImpl(StripProto(basename), true);
136e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
137e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
138e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
139e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring FileJavaPackage(const Params& params, const FileDescriptor* file) {
140e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (params.has_java_package(file->name())) {
141e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return params.java_package(file->name());
142e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  } else {
143e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    string result = kDefaultPackage;
144e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if (!file->package().empty()) {
145e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if (!result.empty()) result += '.';
146e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      result += file->package();
147e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
148e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    return result;
149e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
150e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
151e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
152624c448fbef20a1a2fad2289f622b468c25763d1Max Caibool IsOuterClassNeeded(const Params& params, const FileDescriptor* file) {
153624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  // Enums and extensions need the outer class as the scope.
154624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  if (file->enum_type_count() != 0 || file->extension_count() != 0) {
155624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    return true;
156e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
157624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  // Messages need the outer class only if java_multiple_files is false.
158624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  return !params.java_multiple_files(file->name());
159624c448fbef20a1a2fad2289f622b468c25763d1Max Cai}
160624c448fbef20a1a2fad2289f622b468c25763d1Max Cai
161624c448fbef20a1a2fad2289f622b468c25763d1Max Caistring ToJavaName(const Params& params, const string& name, bool is_class,
162624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    const Descriptor* parent, const FileDescriptor* file) {
163624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  string result;
164624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  if (parent != NULL) {
165624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    result.append(ClassName(params, parent));
166624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  } else if (is_class && params.java_multiple_files(file->name())) {
167624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    result.append(FileJavaPackage(params, file));
168e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  } else {
169624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    result.append(ClassName(params, file));
170e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
171624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  if (!result.empty()) result.append(1, '.');
172624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  result.append(name); // TODO(maxtroy): add '_' if name is a Java keyword.
173e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return result;
174e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
175e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
176e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring ClassName(const Params& params, const FileDescriptor* descriptor) {
177e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  string result = FileJavaPackage(params, descriptor);
178e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  if (!result.empty()) result += '.';
179e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  result += FileClassName(params, descriptor);
180e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return result;
181e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
182e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
183e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring ClassName(const Params& params, const EnumDescriptor* descriptor) {
184624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  // An enum's class name is the enclosing message's class name or the outer
185624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  // class name.
186624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  const Descriptor* parent = descriptor->containing_type();
187624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  if (parent != NULL) {
188624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    return ClassName(params, parent);
189624c448fbef20a1a2fad2289f622b468c25763d1Max Cai  } else {
190624c448fbef20a1a2fad2289f622b468c25763d1Max Cai    return ClassName(params, descriptor->file());
191e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
192e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
193e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
194e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring FieldConstantName(const FieldDescriptor *field) {
195e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  string name = field->name() + "_FIELD_NUMBER";
196e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  UpperString(&name);
197e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return name;
198e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
199e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
200e2d542951c059563a3b7f74c257dac4f222d9dc5Wink SavilleJavaType GetJavaType(FieldDescriptor::Type field_type) {
201e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  switch (field_type) {
202e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_INT32:
203e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_UINT32:
204e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_SINT32:
205e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_FIXED32:
206e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_SFIXED32:
207e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_INT;
208e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
209e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_INT64:
210e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_UINT64:
211e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_SINT64:
212e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_FIXED64:
213e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_SFIXED64:
214e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_LONG;
215e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
216e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_FLOAT:
217e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_FLOAT;
218e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
219e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_DOUBLE:
220e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_DOUBLE;
221e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
222e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_BOOL:
223e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_BOOLEAN;
224e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
225e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_STRING:
226e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_STRING;
227e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
228e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_BYTES:
229e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_BYTES;
230e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
231e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_ENUM:
232e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_ENUM;
233e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
234e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_GROUP:
235e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::TYPE_MESSAGE:
236e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return JAVATYPE_MESSAGE;
237e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
238e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    // No default because we want the compiler to complain if any new
239e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    // types are added.
240e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
241e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
242e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  GOOGLE_LOG(FATAL) << "Can't get here.";
243e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return JAVATYPE_INT;
244e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
245e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
246e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savilleconst char* BoxedPrimitiveTypeName(JavaType type) {
247e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  switch (type) {
248e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_INT    : return "java.lang.Integer";
249e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_LONG   : return "java.lang.Long";
250e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_FLOAT  : return "java.lang.Float";
251e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_DOUBLE : return "java.lang.Double";
252e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_BOOLEAN: return "java.lang.Boolean";
253e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_STRING : return "java.lang.String";
254e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_BYTES  : return "com.google.protobuf.micro.ByteStringMicro";
255e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_ENUM   : return "java.lang.Integer";
256e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case JAVATYPE_MESSAGE: return NULL;
257e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
258e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    // No default because we want the compiler to complain if any new
259e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    // JavaTypes are added.
260e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
261e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
262e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  GOOGLE_LOG(FATAL) << "Can't get here.";
263e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return NULL;
264e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
265e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
266e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillebool AllAscii(const string& text) {
267e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  for (int i = 0; i < text.size(); i++) {
268e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    if ((text[i] & 0x80) != 0) {
269e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return false;
270e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    }
271e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
272e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return true;
273e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
274e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
275e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Savillestring DefaultValue(const Params& params, const FieldDescriptor* field) {
276e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // Switch on cpp_type since we need to know which default_value_* method
277e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  // of FieldDescriptor to call.
278e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  switch (field->cpp_type()) {
279e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_INT32:
280e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return SimpleItoa(field->default_value_int32());
281e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_UINT32:
282e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      // Need to print as a signed int since Java has no unsigned.
283e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
284e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_INT64:
285e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return SimpleItoa(field->default_value_int64()) + "L";
286e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_UINT64:
287e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
288e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville             "L";
2890f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith    case FieldDescriptor::CPPTYPE_DOUBLE: {
2900f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith     double value = field->default_value_double();
2910f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith      if (value == numeric_limits<double>::infinity()) {
2920f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith        return "Double.POSITIVE_INFINITY";
2930f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith      } else if (value == -numeric_limits<double>::infinity()) {
2940f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith        return "Double.NEGATIVE_INFINITY";
2950f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith      } else if (value != value) {
2960f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith        return "Double.NaN";
2970f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith      } else {
2980f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith        return SimpleDtoa(value) + "D";
2990f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith      }
3000f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith    }
3010f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith    case FieldDescriptor::CPPTYPE_FLOAT: {
3020f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith      float value = field->default_value_float();
3030f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith      if (value == numeric_limits<float>::infinity()) {
3040f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith        return "Float.POSITIVE_INFINITY";
3050f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith      } else if (value == -numeric_limits<float>::infinity()) {
3060f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith        return "Float.NEGATIVE_INFINITY";
3070f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith      } else if (value != value) {
3080f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith        return "Float.NaN";
3090f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith      } else {
3100f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith        return SimpleFtoa(value) + "F";
3110f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith      }
3120f2ca89132ab81441f7eb351c7a053a8c8d9d1c3Chris Smith    }
313e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_BOOL:
314e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return field->default_value_bool() ? "true" : "false";
315e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_STRING:
316e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      if (field->type() == FieldDescriptor::TYPE_BYTES) {
317e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        if (field->has_default_value()) {
318e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          // See comments in Internal.java for gory details.
319e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          return strings::Substitute(
320e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville            "com.google.protobuf.micro.ByteStringMicro.copyFromUtf8(\"$0\")",
321e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville            CEscape(field->default_value_string()));
322e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        } else {
323e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          return "com.google.protobuf.micro.ByteStringMicro.EMPTY";
324e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        }
325e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      } else {
326e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        if (AllAscii(field->default_value_string())) {
327e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          // All chars are ASCII.  In this case CEscape() works fine.
328e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          return "\"" + CEscape(field->default_value_string()) + "\"";
329e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        } else {
330e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          // See comments in Internal.java for gory details.
331e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          // BUG: Internal NOT SUPPORTED need to fix!!
332e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville          return strings::Substitute(
333e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville            "com.google.protobuf.micro.Internal.stringDefaultValue(\"$0\")",
334e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville            CEscape(field->default_value_string()));
335e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville        }
336e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      }
337e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
338e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_ENUM:
339e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return ClassName(params, field->enum_type()) + "." +
340e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville             field->default_value_enum()->name();
341e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
342e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    case FieldDescriptor::CPPTYPE_MESSAGE:
343e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville      return ClassName(params, field->message_type()) + ".getDefaultInstance()";
344e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
345e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    // No default because we want the compiler to complain if any new
346e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville    // types are added.
347e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  }
348e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
349e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  GOOGLE_LOG(FATAL) << "Can't get here.";
350e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville  return "";
351e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}
352e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville
353e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}  // namespace javamicro
354e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}  // namespace compiler
355e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}  // namespace protobuf
356e2d542951c059563a3b7f74c257dac4f222d9dc5Wink Saville}  // namespace google
357