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