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 <limits> 36#include <vector> 37 38#include <google/protobuf/compiler/java/java_helpers.h> 39#include <google/protobuf/descriptor.pb.h> 40#include <google/protobuf/stubs/strutil.h> 41#include <google/protobuf/stubs/substitute.h> 42 43namespace google { 44namespace protobuf { 45namespace compiler { 46namespace java { 47 48const char kThickSeparator[] = 49 "// ===================================================================\n"; 50const char kThinSeparator[] = 51 "// -------------------------------------------------------------------\n"; 52 53namespace { 54 55const char* kDefaultPackage = ""; 56 57const string& FieldName(const FieldDescriptor* field) { 58 // Groups are hacky: The name of the field is just the lower-cased name 59 // of the group type. In Java, though, we would like to retain the original 60 // capitalization of the type name. 61 if (GetType(field) == FieldDescriptor::TYPE_GROUP) { 62 return field->message_type()->name(); 63 } else { 64 return field->name(); 65 } 66} 67 68string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) { 69 string result; 70 // Note: I distrust ctype.h due to locales. 71 for (int i = 0; i < input.size(); i++) { 72 if ('a' <= input[i] && input[i] <= 'z') { 73 if (cap_next_letter) { 74 result += input[i] + ('A' - 'a'); 75 } else { 76 result += input[i]; 77 } 78 cap_next_letter = false; 79 } else if ('A' <= input[i] && input[i] <= 'Z') { 80 if (i == 0 && !cap_next_letter) { 81 // Force first letter to lower-case unless explicitly told to 82 // capitalize it. 83 result += input[i] + ('a' - 'A'); 84 } else { 85 // Capital letters after the first are left as-is. 86 result += input[i]; 87 } 88 cap_next_letter = false; 89 } else if ('0' <= input[i] && input[i] <= '9') { 90 result += input[i]; 91 cap_next_letter = true; 92 } else { 93 cap_next_letter = true; 94 } 95 } 96 return result; 97} 98 99} // namespace 100 101string UnderscoresToCamelCase(const FieldDescriptor* field) { 102 return UnderscoresToCamelCaseImpl(FieldName(field), false); 103} 104 105string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) { 106 return UnderscoresToCamelCaseImpl(FieldName(field), true); 107} 108 109string UnderscoresToCamelCase(const MethodDescriptor* method) { 110 return UnderscoresToCamelCaseImpl(method->name(), false); 111} 112 113string StripProto(const string& filename) { 114 if (HasSuffixString(filename, ".protodevel")) { 115 return StripSuffixString(filename, ".protodevel"); 116 } else { 117 return StripSuffixString(filename, ".proto"); 118 } 119} 120 121string FileClassName(const FileDescriptor* file) { 122 if (file->options().has_java_outer_classname()) { 123 return file->options().java_outer_classname(); 124 } else { 125 string basename; 126 string::size_type last_slash = file->name().find_last_of('/'); 127 if (last_slash == string::npos) { 128 basename = file->name(); 129 } else { 130 basename = file->name().substr(last_slash + 1); 131 } 132 return UnderscoresToCamelCaseImpl(StripProto(basename), true); 133 } 134} 135 136string FileJavaPackage(const FileDescriptor* file) { 137 string result; 138 139 if (file->options().has_java_package()) { 140 result = file->options().java_package(); 141 } else { 142 result = kDefaultPackage; 143 if (!file->package().empty()) { 144 if (!result.empty()) result += '.'; 145 result += file->package(); 146 } 147 } 148 149 150 return result; 151} 152 153string JavaPackageToDir(string package_name) { 154 string package_dir = 155 StringReplace(package_name, ".", "/", true); 156 if (!package_dir.empty()) package_dir += "/"; 157 return package_dir; 158} 159 160string ToJavaName(const string& full_name, const FileDescriptor* file) { 161 string result; 162 if (file->options().java_multiple_files()) { 163 result = FileJavaPackage(file); 164 } else { 165 result = ClassName(file); 166 } 167 if (!result.empty()) { 168 result += '.'; 169 } 170 if (file->package().empty()) { 171 result += full_name; 172 } else { 173 // Strip the proto package from full_name since we've replaced it with 174 // the Java package. 175 result += full_name.substr(file->package().size() + 1); 176 } 177 return result; 178} 179 180string ClassName(const Descriptor* descriptor) { 181 return ToJavaName(descriptor->full_name(), descriptor->file()); 182} 183 184string ClassName(const EnumDescriptor* descriptor) { 185 return ToJavaName(descriptor->full_name(), descriptor->file()); 186} 187 188string ClassName(const ServiceDescriptor* descriptor) { 189 return ToJavaName(descriptor->full_name(), descriptor->file()); 190} 191 192string ClassName(const FileDescriptor* descriptor) { 193 string result = FileJavaPackage(descriptor); 194 if (!result.empty()) result += '.'; 195 result += FileClassName(descriptor); 196 return result; 197} 198 199string FieldConstantName(const FieldDescriptor *field) { 200 string name = field->name() + "_FIELD_NUMBER"; 201 UpperString(&name); 202 return name; 203} 204 205FieldDescriptor::Type GetType(const FieldDescriptor* field) { 206 return field->type(); 207} 208 209JavaType GetJavaType(const FieldDescriptor* field) { 210 switch (GetType(field)) { 211 case FieldDescriptor::TYPE_INT32: 212 case FieldDescriptor::TYPE_UINT32: 213 case FieldDescriptor::TYPE_SINT32: 214 case FieldDescriptor::TYPE_FIXED32: 215 case FieldDescriptor::TYPE_SFIXED32: 216 return JAVATYPE_INT; 217 218 case FieldDescriptor::TYPE_INT64: 219 case FieldDescriptor::TYPE_UINT64: 220 case FieldDescriptor::TYPE_SINT64: 221 case FieldDescriptor::TYPE_FIXED64: 222 case FieldDescriptor::TYPE_SFIXED64: 223 return JAVATYPE_LONG; 224 225 case FieldDescriptor::TYPE_FLOAT: 226 return JAVATYPE_FLOAT; 227 228 case FieldDescriptor::TYPE_DOUBLE: 229 return JAVATYPE_DOUBLE; 230 231 case FieldDescriptor::TYPE_BOOL: 232 return JAVATYPE_BOOLEAN; 233 234 case FieldDescriptor::TYPE_STRING: 235 return JAVATYPE_STRING; 236 237 case FieldDescriptor::TYPE_BYTES: 238 return JAVATYPE_BYTES; 239 240 case FieldDescriptor::TYPE_ENUM: 241 return JAVATYPE_ENUM; 242 243 case FieldDescriptor::TYPE_GROUP: 244 case FieldDescriptor::TYPE_MESSAGE: 245 return JAVATYPE_MESSAGE; 246 247 // No default because we want the compiler to complain if any new 248 // types are added. 249 } 250 251 GOOGLE_LOG(FATAL) << "Can't get here."; 252 return JAVATYPE_INT; 253} 254 255const char* BoxedPrimitiveTypeName(JavaType type) { 256 switch (type) { 257 case JAVATYPE_INT : return "java.lang.Integer"; 258 case JAVATYPE_LONG : return "java.lang.Long"; 259 case JAVATYPE_FLOAT : return "java.lang.Float"; 260 case JAVATYPE_DOUBLE : return "java.lang.Double"; 261 case JAVATYPE_BOOLEAN: return "java.lang.Boolean"; 262 case JAVATYPE_STRING : return "java.lang.String"; 263 case JAVATYPE_BYTES : return "com.google.protobuf.ByteString"; 264 case JAVATYPE_ENUM : return NULL; 265 case JAVATYPE_MESSAGE: return NULL; 266 267 // No default because we want the compiler to complain if any new 268 // JavaTypes are added. 269 } 270 271 GOOGLE_LOG(FATAL) << "Can't get here."; 272 return NULL; 273} 274 275bool AllAscii(const string& text) { 276 for (int i = 0; i < text.size(); i++) { 277 if ((text[i] & 0x80) != 0) { 278 return false; 279 } 280 } 281 return true; 282} 283 284string DefaultValue(const FieldDescriptor* field) { 285 // Switch on CppType since we need to know which default_value_* method 286 // of FieldDescriptor to call. 287 switch (field->cpp_type()) { 288 case FieldDescriptor::CPPTYPE_INT32: 289 return SimpleItoa(field->default_value_int32()); 290 case FieldDescriptor::CPPTYPE_UINT32: 291 // Need to print as a signed int since Java has no unsigned. 292 return SimpleItoa(static_cast<int32>(field->default_value_uint32())); 293 case FieldDescriptor::CPPTYPE_INT64: 294 return SimpleItoa(field->default_value_int64()) + "L"; 295 case FieldDescriptor::CPPTYPE_UINT64: 296 return SimpleItoa(static_cast<int64>(field->default_value_uint64())) + 297 "L"; 298 case FieldDescriptor::CPPTYPE_DOUBLE: { 299 double value = field->default_value_double(); 300 if (value == numeric_limits<double>::infinity()) { 301 return "Double.POSITIVE_INFINITY"; 302 } else if (value == -numeric_limits<double>::infinity()) { 303 return "Double.NEGATIVE_INFINITY"; 304 } else if (value != value) { 305 return "Double.NaN"; 306 } else { 307 return SimpleDtoa(value) + "D"; 308 } 309 } 310 case FieldDescriptor::CPPTYPE_FLOAT: { 311 float value = field->default_value_float(); 312 if (value == numeric_limits<float>::infinity()) { 313 return "Float.POSITIVE_INFINITY"; 314 } else if (value == -numeric_limits<float>::infinity()) { 315 return "Float.NEGATIVE_INFINITY"; 316 } else if (value != value) { 317 return "Float.NaN"; 318 } else { 319 return SimpleFtoa(value) + "F"; 320 } 321 } 322 case FieldDescriptor::CPPTYPE_BOOL: 323 return field->default_value_bool() ? "true" : "false"; 324 case FieldDescriptor::CPPTYPE_STRING: 325 if (GetType(field) == FieldDescriptor::TYPE_BYTES) { 326 if (field->has_default_value()) { 327 // See comments in Internal.java for gory details. 328 return strings::Substitute( 329 "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")", 330 CEscape(field->default_value_string())); 331 } else { 332 return "com.google.protobuf.ByteString.EMPTY"; 333 } 334 } else { 335 if (AllAscii(field->default_value_string())) { 336 // All chars are ASCII. In this case CEscape() works fine. 337 return "\"" + CEscape(field->default_value_string()) + "\""; 338 } else { 339 // See comments in Internal.java for gory details. 340 return strings::Substitute( 341 "com.google.protobuf.Internal.stringDefaultValue(\"$0\")", 342 CEscape(field->default_value_string())); 343 } 344 } 345 346 case FieldDescriptor::CPPTYPE_ENUM: 347 return ClassName(field->enum_type()) + "." + 348 field->default_value_enum()->name(); 349 350 case FieldDescriptor::CPPTYPE_MESSAGE: 351 return ClassName(field->message_type()) + ".getDefaultInstance()"; 352 353 // No default because we want the compiler to complain if any new 354 // types are added. 355 } 356 357 GOOGLE_LOG(FATAL) << "Can't get here."; 358 return ""; 359} 360 361bool IsDefaultValueJavaDefault(const FieldDescriptor* field) { 362 // Switch on CppType since we need to know which default_value_* method 363 // of FieldDescriptor to call. 364 switch (field->cpp_type()) { 365 case FieldDescriptor::CPPTYPE_INT32: 366 return field->default_value_int32() == 0; 367 case FieldDescriptor::CPPTYPE_UINT32: 368 return field->default_value_uint32() == 0; 369 case FieldDescriptor::CPPTYPE_INT64: 370 return field->default_value_int64() == 0L; 371 case FieldDescriptor::CPPTYPE_UINT64: 372 return field->default_value_uint64() == 0L; 373 case FieldDescriptor::CPPTYPE_DOUBLE: 374 return field->default_value_double() == 0.0; 375 case FieldDescriptor::CPPTYPE_FLOAT: 376 return field->default_value_float() == 0.0; 377 case FieldDescriptor::CPPTYPE_BOOL: 378 return field->default_value_bool() == false; 379 380 case FieldDescriptor::CPPTYPE_STRING: 381 case FieldDescriptor::CPPTYPE_ENUM: 382 case FieldDescriptor::CPPTYPE_MESSAGE: 383 return false; 384 385 // No default because we want the compiler to complain if any new 386 // types are added. 387 } 388 389 GOOGLE_LOG(FATAL) << "Can't get here."; 390 return false; 391} 392 393const char* bit_masks[] = { 394 "0x00000001", 395 "0x00000002", 396 "0x00000004", 397 "0x00000008", 398 "0x00000010", 399 "0x00000020", 400 "0x00000040", 401 "0x00000080", 402 403 "0x00000100", 404 "0x00000200", 405 "0x00000400", 406 "0x00000800", 407 "0x00001000", 408 "0x00002000", 409 "0x00004000", 410 "0x00008000", 411 412 "0x00010000", 413 "0x00020000", 414 "0x00040000", 415 "0x00080000", 416 "0x00100000", 417 "0x00200000", 418 "0x00400000", 419 "0x00800000", 420 421 "0x01000000", 422 "0x02000000", 423 "0x04000000", 424 "0x08000000", 425 "0x10000000", 426 "0x20000000", 427 "0x40000000", 428 "0x80000000", 429}; 430 431string GetBitFieldName(int index) { 432 string varName = "bitField"; 433 varName += SimpleItoa(index); 434 varName += "_"; 435 return varName; 436} 437 438string GetBitFieldNameForBit(int bitIndex) { 439 return GetBitFieldName(bitIndex / 32); 440} 441 442namespace { 443 444string GenerateGetBitInternal(const string& prefix, int bitIndex) { 445 string varName = prefix + GetBitFieldNameForBit(bitIndex); 446 int bitInVarIndex = bitIndex % 32; 447 448 string mask = bit_masks[bitInVarIndex]; 449 string result = "((" + varName + " & " + mask + ") == " + mask + ")"; 450 return result; 451} 452 453string GenerateSetBitInternal(const string& prefix, int bitIndex) { 454 string varName = prefix + GetBitFieldNameForBit(bitIndex); 455 int bitInVarIndex = bitIndex % 32; 456 457 string mask = bit_masks[bitInVarIndex]; 458 string result = varName + " |= " + mask; 459 return result; 460} 461 462} // namespace 463 464string GenerateGetBit(int bitIndex) { 465 return GenerateGetBitInternal("", bitIndex); 466} 467 468string GenerateSetBit(int bitIndex) { 469 return GenerateSetBitInternal("", bitIndex); 470} 471 472string GenerateClearBit(int bitIndex) { 473 string varName = GetBitFieldNameForBit(bitIndex); 474 int bitInVarIndex = bitIndex % 32; 475 476 string mask = bit_masks[bitInVarIndex]; 477 string result = varName + " = (" + varName + " & ~" + mask + ")"; 478 return result; 479} 480 481string GenerateGetBitFromLocal(int bitIndex) { 482 return GenerateGetBitInternal("from_", bitIndex); 483} 484 485string GenerateSetBitToLocal(int bitIndex) { 486 return GenerateSetBitInternal("to_", bitIndex); 487} 488 489string GenerateGetBitMutableLocal(int bitIndex) { 490 return GenerateGetBitInternal("mutable_", bitIndex); 491} 492 493string GenerateSetBitMutableLocal(int bitIndex) { 494 return GenerateSetBitInternal("mutable_", bitIndex); 495} 496 497} // namespace java 498} // namespace compiler 499} // namespace protobuf 500} // namespace google 501