EnumType.cpp revision a15f8091d2d4312a16edfcebccb13b3ea4782c29
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 <unordered_map> 22 23#include "Annotation.h" 24#include "Location.h" 25#include "ScalarType.h" 26 27namespace android { 28 29EnumType::EnumType(const char* localName, const Location& location, 30 const Reference<Type>& storageType, Scope* parent) 31 : Scope(localName, location, parent), mValues(), mStorageType(storageType) { 32 BitFieldType* bitfieldType = new BitFieldType(); 33 bitfieldType->setElementType(Reference<Type>(this, Location())); 34 mBitfieldType.set(bitfieldType); 35} 36 37const Type *EnumType::storageType() const { 38 return mStorageType; 39} 40 41const std::vector<EnumValue *> &EnumType::values() const { 42 return mValues; 43} 44 45void EnumType::addValue(EnumValue* value) { 46 CHECK(value != nullptr); 47 mValues.push_back(value); 48} 49 50status_t EnumType::resolveInheritance() { 51 const EnumType* prevType = nullptr; 52 EnumValue* prevValue = nullptr; 53 54 for (const auto* type : superTypeChain()) { 55 if (!type->values().empty()) { 56 prevType = type; 57 prevValue = type->values().back(); 58 break; 59 } 60 } 61 62 for (auto* value : mValues) { 63 value->autofill(prevType, prevValue, mStorageType->resolveToScalarType()); 64 prevType = this; 65 prevValue = value; 66 } 67 68 return Scope::resolveInheritance(); 69} 70 71status_t EnumType::evaluate() { 72 status_t err = mStorageType->callForReference(&Type::evaluate); 73 if (err != OK) return err; 74 75 for (auto* value : mValues) { 76 err = value->evaluate(); 77 if (err != OK) return err; 78 } 79 return Scope::evaluate(); 80} 81 82status_t EnumType::validate() const { 83 CHECK(getSubTypes().empty()); 84 85 status_t err = mStorageType->callForReference(&Type::validate); 86 if (err != OK) return err; 87 88 for (auto* value : mValues) { 89 err = value->validate(); 90 if (err != OK) return err; 91 } 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 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() << "define in enum '" 126 << 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::canCheckEquality() 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 179BitFieldType* EnumType::getBitfieldType() const { 180 return mBitfieldType; 181} 182 183LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const { 184 std::vector<const EnumType*> chain = typeChain(); 185 for (auto it = chain.begin(); it != chain.end(); ++it) { 186 const auto &type = *it; 187 for(EnumValue *v : type->values()) { 188 if(v->name() == name) { 189 return v; 190 } 191 } 192 } 193 return nullptr; 194} 195 196void EnumType::emitReaderWriter( 197 Formatter &out, 198 const std::string &name, 199 const std::string &parcelObj, 200 bool parcelObjIsPointer, 201 bool isReader, 202 ErrorMode mode) const { 203 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 204 CHECK(scalarType != NULL); 205 206 scalarType->emitReaderWriterWithCast( 207 out, 208 name, 209 parcelObj, 210 parcelObjIsPointer, 211 isReader, 212 mode, 213 true /* needsCast */); 214} 215 216void EnumType::emitJavaFieldReaderWriter( 217 Formatter &out, 218 size_t depth, 219 const std::string &parcelName, 220 const std::string &blobName, 221 const std::string &fieldName, 222 const std::string &offset, 223 bool isReader) const { 224 return mStorageType->emitJavaFieldReaderWriter( 225 out, depth, parcelName, blobName, fieldName, offset, isReader); 226} 227 228status_t EnumType::emitTypeDeclarations(Formatter &out) const { 229 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 230 CHECK(scalarType != nullptr); 231 232 const std::string storageType = scalarType->getCppStackType(); 233 234 out << "enum class " 235 << localName() 236 << " : " 237 << storageType 238 << " {\n"; 239 240 out.indent(); 241 242 std::vector<const EnumType*> chain = typeChain(); 243 244 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 245 const auto &type = *it; 246 247 for (const auto &entry : type->values()) { 248 out << entry->name(); 249 250 std::string value = entry->cppValue(scalarType->getKind()); 251 CHECK(!value.empty()); // use autofilled values for c++. 252 out << " = " << value; 253 254 out << ","; 255 256 std::string comment = entry->comment(); 257 if (!comment.empty() && comment != value) { 258 out << " // " << comment; 259 } 260 261 out << "\n"; 262 } 263 } 264 265 out.unindent(); 266 out << "};\n\n"; 267 268 return OK; 269} 270 271void EnumType::emitEnumBitwiseOperator( 272 Formatter &out, 273 bool lhsIsEnum, 274 bool rhsIsEnum, 275 const std::string &op) const { 276 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 277 CHECK(scalarType != nullptr); 278 279 const std::string storageType = scalarType->getCppStackType(); 280 281 out << "constexpr " 282 << storageType 283 << " operator" 284 << op 285 << "(const " 286 << (lhsIsEnum ? fullName() : storageType) 287 << " lhs, const " 288 << (rhsIsEnum ? fullName() : storageType) 289 << " rhs) {\n"; 290 291 out.indent([&] { 292 out << "return static_cast<" 293 << storageType 294 << ">("; 295 296 if (lhsIsEnum) { 297 out << "static_cast<" 298 << storageType 299 << ">(lhs)"; 300 } else { 301 out << "lhs"; 302 } 303 out << " " << op << " "; 304 if (rhsIsEnum) { 305 out << "static_cast<" 306 << storageType 307 << ">(rhs)"; 308 } else { 309 out << "rhs"; 310 } 311 out << ");\n"; 312 }); 313 314 out << "}\n\n"; 315} 316 317void EnumType::emitBitFieldBitwiseAssignmentOperator( 318 Formatter &out, 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 " << storageType << " &operator" << op << "=(" 326 << storageType << "& v, const " << fullName() << " e) {\n"; 327 328 out.indent([&] { 329 out << "v " << op << "= static_cast<" << storageType << ">(e);\n"; 330 out << "return v;\n"; 331 }); 332 333 out << "}\n\n"; 334} 335 336status_t EnumType::emitGlobalTypeDeclarations(Formatter &out) const { 337 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "|"); 338 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "|"); 339 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "|"); 340 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "&"); 341 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "&"); 342 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "&"); 343 344 emitBitFieldBitwiseAssignmentOperator(out, "|"); 345 emitBitFieldBitwiseAssignmentOperator(out, "&"); 346 347 // toString for bitfields, equivalent to dumpBitfield in Java 348 out << "template<typename>\n" 349 << "std::string toString(" 350 << resolveToScalarType()->getCppArgumentType() 351 << " o);\n"; 352 out << "template<>\n" 353 << "std::string toString<" << getCppStackType() << ">(" 354 << resolveToScalarType()->getCppArgumentType() 355 << " o);\n\n"; 356 357 // toString for enum itself 358 out << "std::string toString(" 359 << getCppArgumentType() 360 << " o);\n\n"; 361 362 return OK; 363} 364 365status_t EnumType::emitTypeDefinitions(Formatter& out, const std::string& /* prefix */) const { 366 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 367 CHECK(scalarType != NULL); 368 369 out << "template<>\n" 370 << "std::string toString<" << getCppStackType() << ">(" 371 << scalarType->getCppArgumentType() 372 << " o) "; 373 out.block([&] { 374 // include toHexString for scalar types 375 out << "using ::android::hardware::details::toHexString;\n" 376 << "std::string os;\n" 377 << getBitfieldType()->getCppStackType() << " flipped = 0;\n" 378 << "bool first = true;\n"; 379 for (EnumValue *value : values()) { 380 std::string valueName = fullName() + "::" + value->name(); 381 out.sIf("(o & " + valueName + ")" + 382 " == static_cast<" + scalarType->getCppStackType() + 383 ">(" + valueName + ")", [&] { 384 out << "os += (first ? \"\" : \" | \");\n" 385 << "os += \"" << value->name() << "\";\n" 386 << "first = false;\n" 387 << "flipped |= " << valueName << ";\n"; 388 }).endl(); 389 } 390 // put remaining bits 391 out.sIf("o != flipped", [&] { 392 out << "os += (first ? \"\" : \" | \");\n"; 393 scalarType->emitHexDump(out, "os", "o & (~flipped)"); 394 }); 395 out << "os += \" (\";\n"; 396 scalarType->emitHexDump(out, "os", "o"); 397 out << "os += \")\";\n"; 398 399 out << "return os;\n"; 400 }).endl().endl(); 401 402 out << "std::string toString(" 403 << getCppArgumentType() 404 << " o) "; 405 406 out.block([&] { 407 out << "using ::android::hardware::details::toHexString;\n"; 408 for (EnumValue *value : values()) { 409 out.sIf("o == " + fullName() + "::" + value->name(), [&] { 410 out << "return \"" << value->name() << "\";\n"; 411 }).endl(); 412 } 413 out << "std::string os;\n"; 414 scalarType->emitHexDump(out, "os", 415 "static_cast<" + scalarType->getCppStackType() + ">(o)"); 416 out << "return os;\n"; 417 }).endl().endl(); 418 419 return OK; 420} 421 422status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool atTopLevel) const { 423 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 424 CHECK(scalarType != NULL); 425 426 out << "public " 427 << (atTopLevel ? "" : "static ") 428 << "final class " 429 << localName() 430 << " {\n"; 431 432 out.indent(); 433 434 const std::string typeName = 435 scalarType->getJavaType(false /* forInitializer */); 436 437 std::vector<const EnumType*> chain = typeChain(); 438 439 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 440 const auto &type = *it; 441 442 for (const auto &entry : type->values()) { 443 out << "public static final " 444 << typeName 445 << " " 446 << entry->name() 447 << " = "; 448 449 // javaValue will make the number signed. 450 std::string value = entry->javaValue(scalarType->getKind()); 451 CHECK(!value.empty()); // use autofilled values for java. 452 out << value; 453 454 out << ";"; 455 456 std::string comment = entry->comment(); 457 if (!comment.empty() && comment != value) { 458 out << " // " << comment; 459 } 460 461 out << "\n"; 462 } 463 } 464 465 out << "public static final String toString(" 466 << typeName << " o) "; 467 out.block([&] { 468 for (EnumValue *value : values()) { 469 out.sIf("o == " + value->name(), [&] { 470 out << "return \"" << value->name() << "\";\n"; 471 }).endl(); 472 } 473 out << "return \"0x\" + "; 474 scalarType->emitConvertToJavaHexString(out, "o"); 475 out << ";\n"; 476 }).endl(); 477 478 auto bitfieldType = getBitfieldType()->getJavaType(false /* forInitializer */); 479 auto bitfieldWrapperType = getBitfieldType()->getJavaWrapperType(); 480 out << "\n" 481 << "public static final String dumpBitfield(" 482 << bitfieldType << " o) "; 483 out.block([&] { 484 out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n"; 485 out << bitfieldType << " flipped = 0;\n"; 486 for (EnumValue *value : values()) { 487 if (value->constExpr()->castSizeT() == 0) { 488 out << "list.add(\"" << value->name() << "\"); // " << value->name() << " == 0\n"; 489 continue; 490 } 491 out.sIf("(o & " + value->name() + ") == " + value->name(), [&] { 492 out << "list.add(\"" << value->name() << "\");\n"; 493 out << "flipped |= " << value->name() << ";\n"; 494 }).endl(); 495 } 496 // put remaining bits 497 out.sIf("o != flipped", [&] { 498 out << "list.add(\"0x\" + "; 499 scalarType->emitConvertToJavaHexString(out, "o & (~flipped)"); 500 out << ");\n"; 501 }).endl(); 502 out << "return String.join(\" | \", list);\n"; 503 }).endl().endl(); 504 505 out.unindent(); 506 out << "};\n\n"; 507 508 return OK; 509} 510 511status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const { 512 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 513 514 out << "name: \"" << fullName() << "\"\n"; 515 out << "type: " << getVtsType() << "\n"; 516 out << "enum_value: {\n"; 517 out.indent(); 518 519 out << "scalar_type: \"" 520 << scalarType->getVtsScalarType() 521 << "\"\n\n"; 522 std::vector<const EnumType*> chain = typeChain(); 523 524 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 525 const auto &type = *it; 526 527 for (const auto &entry : type->values()) { 528 out << "enumerator: \"" << entry->name() << "\"\n"; 529 out << "scalar_value: {\n"; 530 out.indent(); 531 // use autofilled values for vts. 532 std::string value = entry->value(scalarType->getKind()); 533 CHECK(!value.empty()); 534 out << mStorageType->resolveToScalarType()->getVtsScalarType() 535 << ": " 536 << value 537 << "\n"; 538 out.unindent(); 539 out << "}\n"; 540 } 541 } 542 543 out.unindent(); 544 out << "}\n"; 545 return OK; 546} 547 548status_t EnumType::emitVtsAttributeType(Formatter &out) const { 549 out << "type: " << getVtsType() << "\n"; 550 out << "predefined_type: \"" << fullName() << "\"\n"; 551 return OK; 552} 553 554void EnumType::emitJavaDump( 555 Formatter &out, 556 const std::string &streamName, 557 const std::string &name) const { 558 out << streamName << ".append(" << fqName().javaName() << ".toString(" 559 << name << "));\n"; 560} 561 562std::vector<const EnumType*> EnumType::typeChain() const { 563 std::vector<const EnumType*> types; 564 for (const EnumType* type = this; type != nullptr;) { 565 types.push_back(type); 566 567 const Type* superType = type->storageType(); 568 if (superType != nullptr && superType->isEnum()) { 569 type = static_cast<const EnumType*>(superType); 570 } else { 571 type = nullptr; 572 } 573 } 574 575 return types; 576} 577 578std::vector<const EnumType*> EnumType::superTypeChain() const { 579 const Type* superType = storageType(); 580 if (superType == nullptr || !superType->isEnum()) { 581 return {}; 582 } 583 return static_cast<const EnumType*>(superType)->typeChain(); 584} 585 586void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const { 587 mStorageType->getAlignmentAndSize(align, size); 588} 589 590const Annotation *EnumType::findExportAnnotation() const { 591 for (const auto &annotation : annotations()) { 592 if (annotation->name() == "export") { 593 return annotation; 594 } 595 } 596 597 return nullptr; 598} 599 600void EnumType::appendToExportedTypesVector( 601 std::vector<const Type *> *exportedTypes) const { 602 if (findExportAnnotation() != nullptr) { 603 exportedTypes->push_back(this); 604 } 605} 606 607status_t EnumType::emitExportedHeader(Formatter &out, bool forJava) const { 608 const Annotation *annotation = findExportAnnotation(); 609 CHECK(annotation != nullptr); 610 611 std::string name = localName(); 612 613 const AnnotationParam *nameParam = annotation->getParam("name"); 614 if (nameParam != nullptr) { 615 name = nameParam->getSingleString(); 616 } 617 618 bool exportParent = true; 619 const AnnotationParam *exportParentParam = annotation->getParam("export_parent"); 620 if (exportParentParam != nullptr) { 621 exportParent = exportParentParam->getSingleBool(); 622 } 623 624 std::string valuePrefix; 625 const AnnotationParam *prefixParam = annotation->getParam("value_prefix"); 626 if (prefixParam != nullptr) { 627 valuePrefix = prefixParam->getSingleString(); 628 } 629 630 std::string valueSuffix; 631 const AnnotationParam *suffixParam = annotation->getParam("value_suffix"); 632 if (suffixParam != nullptr) { 633 valueSuffix = suffixParam->getSingleString(); 634 } 635 636 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 637 CHECK(scalarType != nullptr); 638 639 std::vector<const EnumType *> chain; 640 if (exportParent) { 641 chain = typeChain(); 642 } else { 643 chain = { this }; 644 } 645 646 if (forJava) { 647 if (!name.empty()) { 648 out << "public final class " 649 << name 650 << " {\n"; 651 652 out.indent(); 653 } else { 654 out << "// Values declared in " << localName() << " follow.\n"; 655 } 656 657 const std::string typeName = 658 scalarType->getJavaType(false /* forInitializer */); 659 660 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 661 const auto &type = *it; 662 663 for (const auto &entry : type->values()) { 664 out << "public static final " 665 << typeName 666 << " " 667 << valuePrefix 668 << entry->name() 669 << valueSuffix 670 << " = "; 671 672 // javaValue will make the number signed. 673 std::string value = entry->javaValue(scalarType->getKind()); 674 CHECK(!value.empty()); // use autofilled values for java. 675 out << value; 676 677 out << ";"; 678 679 std::string comment = entry->comment(); 680 if (!comment.empty() && comment != value) { 681 out << " // " << comment; 682 } 683 684 out << "\n"; 685 } 686 } 687 688 if (!name.empty()) { 689 out.unindent(); 690 out << "};\n"; 691 } 692 out << "\n"; 693 694 return OK; 695 } 696 697 if (!name.empty()) { 698 out << "typedef "; 699 } 700 701 out << "enum {\n"; 702 703 out.indent(); 704 705 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 706 const auto &type = *it; 707 708 for (const auto &entry : type->values()) { 709 out << valuePrefix << entry->name() << valueSuffix; 710 711 std::string value = entry->cppValue(scalarType->getKind()); 712 CHECK(!value.empty()); // use autofilled values for c++. 713 out << " = " << value; 714 715 out << ","; 716 717 std::string comment = entry->comment(); 718 if (!comment.empty() && comment != value) { 719 out << " // " << comment; 720 } 721 722 out << "\n"; 723 } 724 } 725 726 out.unindent(); 727 out << "}"; 728 729 if (!name.empty()) { 730 out << " " << name; 731 } 732 733 out << ";\n\n"; 734 735 return OK; 736} 737 738//////////////////////////////////////////////////////////////////////////////// 739 740EnumValue::EnumValue(const char* name, ConstantExpression* value, const Location& location) 741 : mName(name), mValue(value), mLocation(location), mIsAutoFill(false) {} 742 743std::string EnumValue::name() const { 744 return mName; 745} 746 747std::string EnumValue::value(ScalarType::Kind castKind) const { 748 CHECK(mValue != nullptr); 749 return mValue->value(castKind); 750} 751 752std::string EnumValue::cppValue(ScalarType::Kind castKind) const { 753 CHECK(mValue != nullptr); 754 return mValue->cppValue(castKind); 755} 756std::string EnumValue::javaValue(ScalarType::Kind castKind) const { 757 CHECK(mValue != nullptr); 758 return mValue->javaValue(castKind); 759} 760 761std::string EnumValue::comment() const { 762 CHECK(mValue != nullptr); 763 return mValue->description(); 764} 765 766ConstantExpression *EnumValue::constExpr() const { 767 CHECK(mValue != nullptr); 768 return mValue; 769} 770 771void EnumValue::autofill(const EnumType* prevType, EnumValue* prevValue, const ScalarType* type) { 772 // Value is defined explicitly 773 if (mValue != nullptr) return; 774 775 CHECK((prevType == nullptr) == (prevValue == nullptr)); 776 777 mIsAutoFill = true; 778 if (prevValue == nullptr) { 779 mValue = ConstantExpression::Zero(type->getKind()).release(); 780 } else { 781 std::string description = prevType->fullName() + "." + prevValue->name() + " implicitly"; 782 auto* prevReference = new ReferenceConstantExpression( 783 Reference<LocalIdentifier>(prevValue, mLocation), description); 784 mValue = prevReference->addOne(type->getKind()).release(); 785 } 786} 787 788bool EnumValue::isAutoFill() const { 789 return mIsAutoFill; 790} 791 792bool EnumValue::isEnumValue() const { 793 return true; 794} 795 796status_t EnumValue::evaluate() { 797 mValue->evaluate(); 798 return OK; 799} 800 801status_t EnumValue::validate() const { 802 // TODO(b/64358435) move isSupported from ConstantExpression 803 return OK; 804} 805 806const Location& EnumValue::location() const { 807 return mLocation; 808} 809 810//////////////////////////////////////////////////////////////////////////////// 811 812bool BitFieldType::isBitField() const { 813 return true; 814} 815 816std::string BitFieldType::typeName() const { 817 return "mask" + (mElementType == nullptr ? "" : (" of " + mElementType->typeName())); 818} 819 820bool BitFieldType::isCompatibleElementType(Type* elementType) const { 821 return elementType->isEnum(); 822} 823 824const ScalarType *BitFieldType::resolveToScalarType() const { 825 return mElementType->resolveToScalarType(); 826} 827 828std::string BitFieldType::getCppType(StorageMode mode, 829 bool specifyNamespaces) const { 830 return resolveToScalarType()->getCppType(mode, specifyNamespaces); 831} 832 833std::string BitFieldType::getJavaType(bool forInitializer) const { 834 return resolveToScalarType()->getJavaType(forInitializer); 835} 836 837std::string BitFieldType::getJavaSuffix() const { 838 return resolveToScalarType()->getJavaSuffix(); 839} 840 841std::string BitFieldType::getJavaWrapperType() const { 842 return resolveToScalarType()->getJavaWrapperType(); 843} 844 845std::string BitFieldType::getVtsType() const { 846 return "TYPE_MASK"; 847} 848 849bool BitFieldType::isElidableType() const { 850 return resolveToScalarType()->isElidableType(); 851} 852 853bool BitFieldType::canCheckEquality() const { 854 return resolveToScalarType()->canCheckEquality(); 855} 856 857status_t BitFieldType::emitVtsAttributeType(Formatter &out) const { 858 out << "type: " << getVtsType() << "\n"; 859 out << "scalar_type: \"" 860 << mElementType->resolveToScalarType()->getVtsScalarType() 861 << "\"\n"; 862 out << "predefined_type: \"" << static_cast<NamedType*>(mElementType.get())->fullName() 863 << "\"\n"; 864 return OK; 865} 866 867void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const { 868 resolveToScalarType()->getAlignmentAndSize(align, size); 869} 870 871void BitFieldType::emitReaderWriter( 872 Formatter &out, 873 const std::string &name, 874 const std::string &parcelObj, 875 bool parcelObjIsPointer, 876 bool isReader, 877 ErrorMode mode) const { 878 resolveToScalarType()->emitReaderWriterWithCast( 879 out, 880 name, 881 parcelObj, 882 parcelObjIsPointer, 883 isReader, 884 mode, 885 true /* needsCast */); 886} 887 888EnumType* BitFieldType::getEnumType() const { 889 CHECK(mElementType->isEnum()); 890 return static_cast<EnumType*>(mElementType.get()); 891} 892 893// a bitfield maps to the underlying scalar type in C++, so operator<< is 894// already defined. We can still emit useful information if the bitfield is 895// in a struct / union by overriding emitDump as below. 896void BitFieldType::emitDump( 897 Formatter &out, 898 const std::string &streamName, 899 const std::string &name) const { 900 out << streamName << " += "<< getEnumType()->fqName().cppNamespace() 901 << "::toString<" << getEnumType()->getCppStackType() 902 << ">(" << name << ");\n"; 903} 904 905void BitFieldType::emitJavaDump( 906 Formatter &out, 907 const std::string &streamName, 908 const std::string &name) const { 909 out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield(" 910 << name << "));\n"; 911} 912 913void BitFieldType::emitJavaFieldReaderWriter( 914 Formatter &out, 915 size_t depth, 916 const std::string &parcelName, 917 const std::string &blobName, 918 const std::string &fieldName, 919 const std::string &offset, 920 bool isReader) const { 921 return resolveToScalarType()->emitJavaFieldReaderWriter( 922 out, depth, parcelName, blobName, fieldName, offset, isReader); 923} 924 925} // namespace android 926 927