EnumType.cpp revision 6961d3f487ba89ff73d89ec78f148cd130d27fa5
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "EnumType.h" 18 19#include <hidl-util/Formatter.h> 20#include <inttypes.h> 21#include <iostream> 22#include <unordered_map> 23 24#include "Annotation.h" 25#include "Location.h" 26#include "ScalarType.h" 27 28namespace android { 29 30EnumType::EnumType(const char* localName, const FQName& fullName, const Location& location, 31 const Reference<Type>& storageType, Scope* parent) 32 : Scope(localName, fullName, location, parent), mValues(), mStorageType(storageType) {} 33 34const Type *EnumType::storageType() const { 35 return mStorageType.get(); 36} 37 38const std::vector<EnumValue *> &EnumType::values() const { 39 return mValues; 40} 41 42void EnumType::forEachValueFromRoot(const std::function<void(EnumValue*)> f) const { 43 std::vector<const EnumType*> chain = typeChain(); 44 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 45 const auto& type = *it; 46 for (EnumValue* v : type->values()) { 47 f(v); 48 } 49 } 50} 51 52void EnumType::addValue(EnumValue* value) { 53 CHECK(value != nullptr); 54 mValues.push_back(value); 55} 56 57status_t EnumType::resolveInheritance() { 58 const EnumType* prevType = nullptr; 59 EnumValue* prevValue = nullptr; 60 61 for (const auto* type : superTypeChain()) { 62 if (!type->values().empty()) { 63 prevType = type; 64 prevValue = type->values().back(); 65 break; 66 } 67 } 68 69 for (auto* value : mValues) { 70 value->autofill(prevType, prevValue, mStorageType->resolveToScalarType()); 71 prevType = this; 72 prevValue = value; 73 } 74 75 return Scope::resolveInheritance(); 76} 77 78std::vector<const Reference<Type>*> EnumType::getReferences() const { 79 return {&mStorageType}; 80} 81 82std::vector<const ConstantExpression*> EnumType::getConstantExpressions() const { 83 std::vector<const ConstantExpression*> ret; 84 for (const auto* value : mValues) { 85 ret.push_back(value->constExpr()); 86 } 87 return ret; 88} 89 90status_t EnumType::validate() const { 91 CHECK(getSubTypes().empty()); 92 93 if (!isElidableType() || !mStorageType->isValidEnumStorageType()) { 94 std::cerr << "ERROR: Invalid enum storage type (" << (mStorageType)->typeName() 95 << ") specified at " << mStorageType.location() << "\n"; 96 return UNKNOWN_ERROR; 97 } 98 99 status_t err = validateUniqueNames(); 100 if (err != OK) return err; 101 102 return Scope::validate(); 103} 104 105status_t EnumType::validateUniqueNames() const { 106 std::unordered_map<std::string, const EnumType*> registeredValueNames; 107 for (const auto* type : superTypeChain()) { 108 for (const auto* enumValue : type->mValues) { 109 // No need to check super value uniqueness 110 registeredValueNames[enumValue->name()] = type; 111 } 112 } 113 114 for (const auto* value : mValues) { 115 auto registered = registeredValueNames.find(value->name()); 116 117 if (registered != registeredValueNames.end()) { 118 const EnumType* definedInType = registered->second; 119 120 if (definedInType == this) { 121 // Defined in this enum 122 std::cerr << "ERROR: Redefinition of value '" << value->name() << "'"; 123 } else { 124 // Defined in super enum 125 std::cerr << "ERROR: Redefinition of value '" << value->name() 126 << "' defined in enum '" << definedInType->fullName() << "'"; 127 } 128 std::cerr << " at " << value->location() << "\n"; 129 return UNKNOWN_ERROR; 130 } 131 132 registeredValueNames[value->name()] = this; 133 } 134 135 return OK; 136} 137 138bool EnumType::isElidableType() const { 139 return mStorageType->isElidableType(); 140} 141 142const ScalarType *EnumType::resolveToScalarType() const { 143 return mStorageType->resolveToScalarType(); 144} 145 146std::string EnumType::typeName() const { 147 return "enum " + localName(); 148} 149 150bool EnumType::isEnum() const { 151 return true; 152} 153 154bool EnumType::deepCanCheckEquality(std::unordered_set<const Type*>* /* visited */) const { 155 return true; 156} 157 158std::string EnumType::getCppType(StorageMode, 159 bool /* specifyNamespaces */) const { 160 return fullName(); 161} 162 163std::string EnumType::getJavaType(bool forInitializer) const { 164 return mStorageType->resolveToScalarType()->getJavaType(forInitializer); 165} 166 167std::string EnumType::getJavaSuffix() const { 168 return mStorageType->resolveToScalarType()->getJavaSuffix(); 169} 170 171std::string EnumType::getJavaWrapperType() const { 172 return mStorageType->resolveToScalarType()->getJavaWrapperType(); 173} 174 175std::string EnumType::getVtsType() const { 176 return "TYPE_ENUM"; 177} 178 179std::string EnumType::getBitfieldCppType(StorageMode mode, bool specifyNamespaces) const { 180 return resolveToScalarType()->getCppType(mode, specifyNamespaces); 181} 182 183std::string EnumType::getBitfieldJavaType(bool forInitializer) const { 184 return resolveToScalarType()->getJavaType(forInitializer); 185} 186 187std::string EnumType::getBitfieldJavaWrapperType() const { 188 return resolveToScalarType()->getJavaWrapperType(); 189} 190 191LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const { 192 std::vector<const EnumType*> chain = typeChain(); 193 for (auto it = chain.begin(); it != chain.end(); ++it) { 194 const auto &type = *it; 195 for(EnumValue *v : type->values()) { 196 if(v->name() == name) { 197 return v; 198 } 199 } 200 } 201 return nullptr; 202} 203 204void EnumType::emitReaderWriter( 205 Formatter &out, 206 const std::string &name, 207 const std::string &parcelObj, 208 bool parcelObjIsPointer, 209 bool isReader, 210 ErrorMode mode) const { 211 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 212 CHECK(scalarType != NULL); 213 214 scalarType->emitReaderWriterWithCast( 215 out, 216 name, 217 parcelObj, 218 parcelObjIsPointer, 219 isReader, 220 mode, 221 true /* needsCast */); 222} 223 224void EnumType::emitJavaFieldReaderWriter( 225 Formatter &out, 226 size_t depth, 227 const std::string &parcelName, 228 const std::string &blobName, 229 const std::string &fieldName, 230 const std::string &offset, 231 bool isReader) const { 232 return mStorageType->emitJavaFieldReaderWriter( 233 out, depth, parcelName, blobName, fieldName, offset, isReader); 234} 235 236status_t EnumType::emitTypeDeclarations(Formatter &out) const { 237 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 238 CHECK(scalarType != nullptr); 239 240 const std::string storageType = scalarType->getCppStackType(); 241 242 out << "enum class " 243 << localName() 244 << " : " 245 << storageType 246 << " {\n"; 247 248 out.indent(); 249 250 std::vector<const EnumType*> chain = typeChain(); 251 252 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 253 const auto &type = *it; 254 255 for (const auto &entry : type->values()) { 256 out << entry->name(); 257 258 std::string value = entry->cppValue(scalarType->getKind()); 259 CHECK(!value.empty()); // use autofilled values for c++. 260 out << " = " << value; 261 262 out << ","; 263 264 std::string comment = entry->comment(); 265 if (!comment.empty()) { 266 out << " // " << comment; 267 } 268 269 out << "\n"; 270 } 271 } 272 273 out.unindent(); 274 out << "};\n\n"; 275 276 return OK; 277} 278 279void EnumType::emitTypeForwardDeclaration(Formatter& out) const { 280 const ScalarType* scalarType = mStorageType->resolveToScalarType(); 281 const std::string storageType = scalarType->getCppStackType(); 282 283 out << "enum class " << localName() << " : " << storageType << ";\n"; 284} 285 286void EnumType::emitIteratorDeclaration(Formatter& out) const { 287 size_t elementCount = 0; 288 for (const auto* type : typeChain()) { 289 elementCount += type->mValues.size(); 290 } 291 292 out << "template<> struct hidl_enum_iterator<" << getCppStackType() << ">\n"; 293 out.block([&] { 294 out << "const " << getCppStackType() << "* begin() { return static_begin(); }\n"; 295 out << "const " << getCppStackType() << "* end() { return begin() + " << elementCount 296 << "; }\n"; 297 out << "private:\n"; 298 out << "static const " << getCppStackType() << "* static_begin() "; 299 out.block([&] { 300 out << "static const " << getCppStackType() << " kVals[" << elementCount << "] "; 301 out.block([&] { 302 auto enumerators = typeChain(); 303 std::reverse(enumerators.begin(), enumerators.end()); 304 for (const auto* type : enumerators) { 305 for (const auto* enumValue : type->mValues) { 306 out << fullName() << "::" << enumValue->name() << ",\n"; 307 } 308 } 309 }) << ";\n"; 310 out << "return &kVals[0];\n"; 311 }); 312 }) << ";\n\n"; 313} 314 315void EnumType::emitEnumBitwiseOperator( 316 Formatter &out, 317 bool lhsIsEnum, 318 bool rhsIsEnum, 319 const std::string &op) const { 320 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 321 CHECK(scalarType != nullptr); 322 323 const std::string storageType = scalarType->getCppStackType(); 324 325 out << "constexpr " 326 << storageType 327 << " operator" 328 << op 329 << "(const " 330 << (lhsIsEnum ? fullName() : storageType) 331 << " lhs, const " 332 << (rhsIsEnum ? fullName() : storageType) 333 << " rhs) {\n"; 334 335 out.indent([&] { 336 out << "return static_cast<" 337 << storageType 338 << ">("; 339 340 if (lhsIsEnum) { 341 out << "static_cast<" 342 << storageType 343 << ">(lhs)"; 344 } else { 345 out << "lhs"; 346 } 347 out << " " << op << " "; 348 if (rhsIsEnum) { 349 out << "static_cast<" 350 << storageType 351 << ">(rhs)"; 352 } else { 353 out << "rhs"; 354 } 355 out << ");\n"; 356 }); 357 358 out << "}\n\n"; 359} 360 361void EnumType::emitBitFieldBitwiseAssignmentOperator( 362 Formatter &out, 363 const std::string &op) const { 364 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 365 CHECK(scalarType != nullptr); 366 367 const std::string storageType = scalarType->getCppStackType(); 368 369 out << "constexpr " << storageType << " &operator" << op << "=(" 370 << storageType << "& v, const " << fullName() << " e) {\n"; 371 372 out.indent([&] { 373 out << "v " << op << "= static_cast<" << storageType << ">(e);\n"; 374 out << "return v;\n"; 375 }); 376 377 out << "}\n\n"; 378} 379 380void EnumType::emitGlobalTypeDeclarations(Formatter& out) const { 381 out << "namespace android {\n"; 382 out << "namespace hardware {\n"; 383 384 emitIteratorDeclaration(out); 385 386 out << "} // namespace hardware\n"; 387 out << "} // namespace android\n"; 388} 389 390status_t EnumType::emitPackageTypeDeclarations(Formatter& out) const { 391 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "|"); 392 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "|"); 393 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "|"); 394 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "&"); 395 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "&"); 396 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "&"); 397 398 emitBitFieldBitwiseAssignmentOperator(out, "|"); 399 emitBitFieldBitwiseAssignmentOperator(out, "&"); 400 401 // TODO(b/65200821): remove these ifndefs 402 out << "#ifdef REALLY_IS_HIDL_INTERNAL_LIB" << gCurrentCompileName << "\n"; 403 // toString for bitfields, equivalent to dumpBitfield in Java 404 out << "template<typename>\n" 405 << "std::string toString(" 406 << resolveToScalarType()->getCppArgumentType() 407 << " o);\n"; 408 out << "template<>\n" 409 << "std::string toString<" << getCppStackType() << ">(" 410 << resolveToScalarType()->getCppArgumentType() 411 << " o);\n\n"; 412 413 // toString for enum itself 414 out << "std::string toString(" 415 << getCppArgumentType() 416 << " o);\n\n"; 417 out << "#else\n"; 418 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 419 CHECK(scalarType != NULL); 420 421 out << "template<typename>\n" 422 << "static inline std::string toString(" << resolveToScalarType()->getCppArgumentType() 423 << " o);\n"; 424 out << "template<>\n" 425 << "inline std::string toString<" << getCppStackType() << ">(" 426 << scalarType->getCppArgumentType() << " o) "; 427 out.block([&] { 428 // include toHexString for scalar types 429 out << "using ::android::hardware::details::toHexString;\n" 430 << "std::string os;\n" 431 << getBitfieldCppType(StorageMode_Stack) << " flipped = 0;\n" 432 << "bool first = true;\n"; 433 for (EnumValue *value : values()) { 434 std::string valueName = fullName() + "::" + value->name(); 435 out.sIf("(o & " + valueName + ")" + 436 " == static_cast<" + scalarType->getCppStackType() + 437 ">(" + valueName + ")", [&] { 438 out << "os += (first ? \"\" : \" | \");\n" 439 << "os += \"" << value->name() << "\";\n" 440 << "first = false;\n" 441 << "flipped |= " << valueName << ";\n"; 442 }).endl(); 443 } 444 // put remaining bits 445 out.sIf("o != flipped", [&] { 446 out << "os += (first ? \"\" : \" | \");\n"; 447 scalarType->emitHexDump(out, "os", "o & (~flipped)"); 448 }); 449 out << "os += \" (\";\n"; 450 scalarType->emitHexDump(out, "os", "o"); 451 out << "os += \")\";\n"; 452 453 out << "return os;\n"; 454 }).endl().endl(); 455 456 out << "static inline std::string toString(" << getCppArgumentType() << " o) "; 457 458 out.block([&] { 459 out << "using ::android::hardware::details::toHexString;\n"; 460 for (EnumValue *value : values()) { 461 out.sIf("o == " + fullName() + "::" + value->name(), [&] { 462 out << "return \"" << value->name() << "\";\n"; 463 }).endl(); 464 } 465 out << "std::string os;\n"; 466 scalarType->emitHexDump(out, "os", 467 "static_cast<" + scalarType->getCppStackType() + ">(o)"); 468 out << "return os;\n"; 469 }).endl().endl(); 470 out << "#endif // REALLY_IS_HIDL_INTERNAL_LIB\n"; 471 472 return OK; 473} 474 475status_t EnumType::emitTypeDefinitions(Formatter& out, const std::string& /* prefix */) const { 476 // TODO(b/65200821): remove toString from .cpp once all prebuilts are rebuilt 477 478 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 479 CHECK(scalarType != NULL); 480 481 out << "template<>\n" 482 << "std::string toString<" << getCppStackType() << ">(" 483 << scalarType->getCppArgumentType() 484 << " o) "; 485 out.block([&] { 486 // include toHexString for scalar types 487 out << "using ::android::hardware::details::toHexString;\n" 488 << "std::string os;\n" 489 << getBitfieldCppType(StorageMode_Stack) << " flipped = 0;\n" 490 << "bool first = true;\n"; 491 492 forEachValueFromRoot([&](EnumValue* value) { 493 std::string valueName = fullName() + "::" + value->name(); 494 out.sIf("(o & " + valueName + ")" + 495 " == static_cast<" + scalarType->getCppStackType() + 496 ">(" + valueName + ")", [&] { 497 out << "os += (first ? \"\" : \" | \");\n" 498 << "os += \"" << value->name() << "\";\n" 499 << "first = false;\n" 500 << "flipped |= " << valueName << ";\n"; 501 }).endl(); 502 }); 503 // put remaining bits 504 out.sIf("o != flipped", [&] { 505 out << "os += (first ? \"\" : \" | \");\n"; 506 scalarType->emitHexDump(out, "os", "o & (~flipped)"); 507 }); 508 out << "os += \" (\";\n"; 509 scalarType->emitHexDump(out, "os", "o"); 510 out << "os += \")\";\n"; 511 512 out << "return os;\n"; 513 }).endl().endl(); 514 515 out << "std::string toString(" 516 << getCppArgumentType() 517 << " o) "; 518 519 out.block([&] { 520 out << "using ::android::hardware::details::toHexString;\n"; 521 522 forEachValueFromRoot([&](EnumValue* value) { 523 out.sIf("o == " + fullName() + "::" + value->name(), [&] { 524 out << "return \"" << value->name() << "\";\n"; 525 }).endl(); 526 }); 527 528 out << "std::string os;\n"; 529 scalarType->emitHexDump(out, "os", 530 "static_cast<" + scalarType->getCppStackType() + ">(o)"); 531 out << "return os;\n"; 532 }).endl().endl(); 533 534 return OK; 535} 536 537status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool atTopLevel) const { 538 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 539 CHECK(scalarType != NULL); 540 541 out << "public " 542 << (atTopLevel ? "" : "static ") 543 << "final class " 544 << localName() 545 << " {\n"; 546 547 out.indent(); 548 549 const std::string typeName = 550 scalarType->getJavaType(false /* forInitializer */); 551 552 std::vector<const EnumType*> chain = typeChain(); 553 554 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 555 const auto &type = *it; 556 557 for (const auto &entry : type->values()) { 558 out << "public static final " 559 << typeName 560 << " " 561 << entry->name() 562 << " = "; 563 564 // javaValue will make the number signed. 565 std::string value = entry->javaValue(scalarType->getKind()); 566 CHECK(!value.empty()); // use autofilled values for java. 567 out << value; 568 569 out << ";"; 570 571 std::string comment = entry->comment(); 572 if (!comment.empty()) { 573 out << " // " << comment; 574 } 575 576 out << "\n"; 577 } 578 } 579 580 out << "public static final String toString(" 581 << typeName << " o) "; 582 out.block([&] { 583 forEachValueFromRoot([&](EnumValue* value) { 584 out.sIf("o == " + value->name(), [&] { 585 out << "return \"" << value->name() << "\";\n"; 586 }).endl(); 587 }); 588 out << "return \"0x\" + "; 589 scalarType->emitConvertToJavaHexString(out, "o"); 590 out << ";\n"; 591 }).endl(); 592 593 auto bitfieldType = getBitfieldJavaType(false /* forInitializer */); 594 auto bitfieldWrapperType = getBitfieldJavaWrapperType(); 595 out << "\n" 596 << "public static final String dumpBitfield(" 597 << bitfieldType << " o) "; 598 out.block([&] { 599 out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n"; 600 out << bitfieldType << " flipped = 0;\n"; 601 forEachValueFromRoot([&](EnumValue* value) { 602 if (value->constExpr()->castSizeT() == 0) { 603 out << "list.add(\"" << value->name() << "\"); // " << value->name() << " == 0\n"; 604 return; // continue to next value 605 } 606 out.sIf("(o & " + value->name() + ") == " + value->name(), [&] { 607 out << "list.add(\"" << value->name() << "\");\n"; 608 out << "flipped |= " << value->name() << ";\n"; 609 }).endl(); 610 }); 611 // put remaining bits 612 out.sIf("o != flipped", [&] { 613 out << "list.add(\"0x\" + "; 614 scalarType->emitConvertToJavaHexString(out, "o & (~flipped)"); 615 out << ");\n"; 616 }).endl(); 617 out << "return String.join(\" | \", list);\n"; 618 }).endl().endl(); 619 620 out.unindent(); 621 out << "};\n\n"; 622 623 return OK; 624} 625 626status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const { 627 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 628 629 out << "name: \"" << fullName() << "\"\n"; 630 out << "type: " << getVtsType() << "\n"; 631 out << "enum_value: {\n"; 632 out.indent(); 633 634 out << "scalar_type: \"" 635 << scalarType->getVtsScalarType() 636 << "\"\n\n"; 637 std::vector<const EnumType*> chain = typeChain(); 638 639 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 640 const auto &type = *it; 641 642 for (const auto &entry : type->values()) { 643 out << "enumerator: \"" << entry->name() << "\"\n"; 644 out << "scalar_value: {\n"; 645 out.indent(); 646 // use autofilled values for vts. 647 std::string value = entry->value(scalarType->getKind()); 648 CHECK(!value.empty()); 649 out << mStorageType->resolveToScalarType()->getVtsScalarType() 650 << ": " 651 << value 652 << "\n"; 653 out.unindent(); 654 out << "}\n"; 655 } 656 } 657 658 out.unindent(); 659 out << "}\n"; 660 return OK; 661} 662 663status_t EnumType::emitVtsAttributeType(Formatter &out) const { 664 out << "type: " << getVtsType() << "\n"; 665 out << "predefined_type: \"" << fullName() << "\"\n"; 666 return OK; 667} 668 669void EnumType::emitJavaDump( 670 Formatter &out, 671 const std::string &streamName, 672 const std::string &name) const { 673 out << streamName << ".append(" << fqName().javaName() << ".toString(" 674 << name << "));\n"; 675} 676 677std::vector<const EnumType*> EnumType::typeChain() const { 678 std::vector<const EnumType*> types; 679 for (const EnumType* type = this; type != nullptr;) { 680 types.push_back(type); 681 682 const Type* superType = type->storageType(); 683 if (superType != nullptr && superType->isEnum()) { 684 type = static_cast<const EnumType*>(superType); 685 } else { 686 type = nullptr; 687 } 688 } 689 690 return types; 691} 692 693std::vector<const EnumType*> EnumType::superTypeChain() const { 694 const Type* superType = storageType(); 695 if (superType == nullptr || !superType->isEnum()) { 696 return {}; 697 } 698 return static_cast<const EnumType*>(superType)->typeChain(); 699} 700 701void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const { 702 mStorageType->getAlignmentAndSize(align, size); 703} 704 705const Annotation *EnumType::findExportAnnotation() const { 706 for (const auto &annotation : annotations()) { 707 if (annotation->name() == "export") { 708 return annotation; 709 } 710 } 711 712 return nullptr; 713} 714 715void EnumType::appendToExportedTypesVector( 716 std::vector<const Type *> *exportedTypes) const { 717 if (findExportAnnotation() != nullptr) { 718 exportedTypes->push_back(this); 719 } 720} 721 722status_t EnumType::emitExportedHeader(Formatter &out, bool forJava) const { 723 const Annotation *annotation = findExportAnnotation(); 724 CHECK(annotation != nullptr); 725 726 std::string name = localName(); 727 728 const AnnotationParam *nameParam = annotation->getParam("name"); 729 if (nameParam != nullptr) { 730 name = nameParam->getSingleString(); 731 } 732 733 bool exportParent = true; 734 const AnnotationParam *exportParentParam = annotation->getParam("export_parent"); 735 if (exportParentParam != nullptr) { 736 exportParent = exportParentParam->getSingleBool(); 737 } 738 739 std::string valuePrefix; 740 const AnnotationParam *prefixParam = annotation->getParam("value_prefix"); 741 if (prefixParam != nullptr) { 742 valuePrefix = prefixParam->getSingleString(); 743 } 744 745 std::string valueSuffix; 746 const AnnotationParam *suffixParam = annotation->getParam("value_suffix"); 747 if (suffixParam != nullptr) { 748 valueSuffix = suffixParam->getSingleString(); 749 } 750 751 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 752 CHECK(scalarType != nullptr); 753 754 std::vector<const EnumType *> chain; 755 if (exportParent) { 756 chain = typeChain(); 757 } else { 758 chain = { this }; 759 } 760 761 if (forJava) { 762 if (!name.empty()) { 763 out << "public final class " 764 << name 765 << " {\n"; 766 767 out.indent(); 768 } else { 769 out << "// Values declared in " << localName() << " follow.\n"; 770 } 771 772 const std::string typeName = 773 scalarType->getJavaType(false /* forInitializer */); 774 775 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 776 const auto &type = *it; 777 778 for (const auto &entry : type->values()) { 779 out << "public static final " 780 << typeName 781 << " " 782 << valuePrefix 783 << entry->name() 784 << valueSuffix 785 << " = "; 786 787 // javaValue will make the number signed. 788 std::string value = entry->javaValue(scalarType->getKind()); 789 CHECK(!value.empty()); // use autofilled values for java. 790 out << value; 791 792 out << ";"; 793 794 std::string comment = entry->comment(); 795 if (!comment.empty()) { 796 out << " // " << comment; 797 } 798 799 out << "\n"; 800 } 801 } 802 803 if (!name.empty()) { 804 out.unindent(); 805 out << "};\n"; 806 } 807 out << "\n"; 808 809 return OK; 810 } 811 812 if (!name.empty()) { 813 out << "typedef "; 814 } 815 816 out << "enum {\n"; 817 818 out.indent(); 819 820 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 821 const auto &type = *it; 822 823 for (const auto &entry : type->values()) { 824 out << valuePrefix << entry->name() << valueSuffix; 825 826 std::string value = entry->cppValue(scalarType->getKind()); 827 CHECK(!value.empty()); // use autofilled values for c++. 828 out << " = " << value; 829 830 out << ","; 831 832 std::string comment = entry->comment(); 833 if (!comment.empty()) { 834 out << " // " << comment; 835 } 836 837 out << "\n"; 838 } 839 } 840 841 out.unindent(); 842 out << "}"; 843 844 if (!name.empty()) { 845 out << " " << name; 846 } 847 848 out << ";\n\n"; 849 850 return OK; 851} 852 853//////////////////////////////////////////////////////////////////////////////// 854 855EnumValue::EnumValue(const char* name, ConstantExpression* value, const Location& location) 856 : mName(name), mValue(value), mLocation(location), mIsAutoFill(false) {} 857 858std::string EnumValue::name() const { 859 return mName; 860} 861 862std::string EnumValue::value(ScalarType::Kind castKind) const { 863 CHECK(mValue != nullptr); 864 return mValue->value(castKind); 865} 866 867std::string EnumValue::cppValue(ScalarType::Kind castKind) const { 868 CHECK(mValue != nullptr); 869 return mValue->cppValue(castKind); 870} 871std::string EnumValue::javaValue(ScalarType::Kind castKind) const { 872 CHECK(mValue != nullptr); 873 return mValue->javaValue(castKind); 874} 875 876std::string EnumValue::comment() const { 877 CHECK(mValue != nullptr); 878 if (mValue->descriptionIsTrivial()) return ""; 879 return mValue->description(); 880} 881 882ConstantExpression *EnumValue::constExpr() const { 883 CHECK(mValue != nullptr); 884 return mValue; 885} 886 887void EnumValue::autofill(const EnumType* prevType, EnumValue* prevValue, const ScalarType* type) { 888 // Value is defined explicitly 889 if (mValue != nullptr) return; 890 891 CHECK((prevType == nullptr) == (prevValue == nullptr)); 892 893 mIsAutoFill = true; 894 if (prevValue == nullptr) { 895 mValue = ConstantExpression::Zero(type->getKind()).release(); 896 } else { 897 std::string description = prevType->fullName() + "." + prevValue->name() + " implicitly"; 898 auto* prevReference = new ReferenceConstantExpression( 899 Reference<LocalIdentifier>(prevValue, mLocation), description); 900 mValue = prevReference->addOne(type->getKind()).release(); 901 } 902} 903 904bool EnumValue::isAutoFill() const { 905 return mIsAutoFill; 906} 907 908bool EnumValue::isEnumValue() const { 909 return true; 910} 911 912const Location& EnumValue::location() const { 913 return mLocation; 914} 915 916//////////////////////////////////////////////////////////////////////////////// 917 918BitFieldType::BitFieldType(Scope* parent) : TemplatedType(parent) {} 919 920bool BitFieldType::isBitField() const { 921 return true; 922} 923 924const EnumType* BitFieldType::getElementEnumType() const { 925 CHECK(mElementType.get() != nullptr && mElementType->isEnum()); 926 return static_cast<const EnumType*>(mElementType.get()); 927} 928 929std::string BitFieldType::templatedTypeName() const { 930 return "mask"; 931} 932 933bool BitFieldType::isCompatibleElementType(const Type* elementType) const { 934 return elementType->isEnum(); 935} 936 937const ScalarType *BitFieldType::resolveToScalarType() const { 938 return mElementType->resolveToScalarType(); 939} 940 941std::string BitFieldType::getCppType(StorageMode mode, 942 bool specifyNamespaces) const { 943 return getElementEnumType()->getBitfieldCppType(mode, specifyNamespaces); 944} 945 946std::string BitFieldType::getJavaType(bool forInitializer) const { 947 return getElementEnumType()->getBitfieldJavaType(forInitializer); 948} 949 950std::string BitFieldType::getJavaSuffix() const { 951 return resolveToScalarType()->getJavaSuffix(); 952} 953 954std::string BitFieldType::getJavaWrapperType() const { 955 return getElementEnumType()->getBitfieldJavaWrapperType(); 956} 957 958std::string BitFieldType::getVtsType() const { 959 return "TYPE_MASK"; 960} 961 962bool BitFieldType::isElidableType() const { 963 return resolveToScalarType()->isElidableType(); 964} 965 966bool BitFieldType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const { 967 return resolveToScalarType()->canCheckEquality(visited); 968} 969 970status_t BitFieldType::emitVtsAttributeType(Formatter &out) const { 971 out << "type: " << getVtsType() << "\n"; 972 out << "scalar_type: \"" 973 << mElementType->resolveToScalarType()->getVtsScalarType() 974 << "\"\n"; 975 out << "predefined_type: \"" << static_cast<const NamedType*>(mElementType.get())->fullName() 976 << "\"\n"; 977 return OK; 978} 979 980void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const { 981 resolveToScalarType()->getAlignmentAndSize(align, size); 982} 983 984void BitFieldType::emitReaderWriter( 985 Formatter &out, 986 const std::string &name, 987 const std::string &parcelObj, 988 bool parcelObjIsPointer, 989 bool isReader, 990 ErrorMode mode) const { 991 resolveToScalarType()->emitReaderWriterWithCast( 992 out, 993 name, 994 parcelObj, 995 parcelObjIsPointer, 996 isReader, 997 mode, 998 true /* needsCast */); 999} 1000 1001const EnumType* BitFieldType::getEnumType() const { 1002 CHECK(mElementType->isEnum()); 1003 return static_cast<const EnumType*>(mElementType.get()); 1004} 1005 1006// a bitfield maps to the underlying scalar type in C++, so operator<< is 1007// already defined. We can still emit useful information if the bitfield is 1008// in a struct / union by overriding emitDump as below. 1009void BitFieldType::emitDump( 1010 Formatter &out, 1011 const std::string &streamName, 1012 const std::string &name) const { 1013 out << streamName << " += "<< getEnumType()->fqName().cppNamespace() 1014 << "::toString<" << getEnumType()->getCppStackType() 1015 << ">(" << name << ");\n"; 1016} 1017 1018void BitFieldType::emitJavaDump( 1019 Formatter &out, 1020 const std::string &streamName, 1021 const std::string &name) const { 1022 out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield(" 1023 << name << "));\n"; 1024} 1025 1026void BitFieldType::emitJavaFieldReaderWriter( 1027 Formatter &out, 1028 size_t depth, 1029 const std::string &parcelName, 1030 const std::string &blobName, 1031 const std::string &fieldName, 1032 const std::string &offset, 1033 bool isReader) const { 1034 return resolveToScalarType()->emitJavaFieldReaderWriter( 1035 out, depth, parcelName, blobName, fieldName, offset, isReader); 1036} 1037 1038} // namespace android 1039 1040