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