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
EnumType(const char * localName,const Location & location,Type * storageType)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
storageType() const39 const Type *EnumType::storageType() const {
40 return mStorageType;
41 }
42
values() const43 const std::vector<EnumValue *> &EnumType::values() const {
44 return mValues;
45 }
46
addValue(EnumValue * value)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
isElidableType() const65 bool EnumType::isElidableType() const {
66 return mStorageType->isElidableType();
67 }
68
resolveToScalarType() const69 const ScalarType *EnumType::resolveToScalarType() const {
70 return mStorageType->resolveToScalarType();
71 }
72
typeName() const73 std::string EnumType::typeName() const {
74 return "enum " + localName();
75 }
76
isEnum() const77 bool EnumType::isEnum() const {
78 return true;
79 }
80
canCheckEquality() const81 bool EnumType::canCheckEquality() const {
82 return true;
83 }
84
getCppType(StorageMode,bool specifyNamespaces) const85 std::string EnumType::getCppType(StorageMode,
86 bool specifyNamespaces) const {
87 return specifyNamespaces ? fullName() : partialCppName();
88 }
89
getJavaType(bool forInitializer) const90 std::string EnumType::getJavaType(bool forInitializer) const {
91 return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
92 }
93
getJavaSuffix() const94 std::string EnumType::getJavaSuffix() const {
95 return mStorageType->resolveToScalarType()->getJavaSuffix();
96 }
97
getJavaWrapperType() const98 std::string EnumType::getJavaWrapperType() const {
99 return mStorageType->resolveToScalarType()->getJavaWrapperType();
100 }
101
getVtsType() const102 std::string EnumType::getVtsType() const {
103 return "TYPE_ENUM";
104 }
105
getBitfieldType() const106 BitFieldType *EnumType::getBitfieldType() const {
107 return mBitfieldType;
108 }
109
lookupIdentifier(const std::string & name) const110 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
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const124 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
emitJavaFieldReaderWriter(Formatter & out,size_t depth,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const144 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
emitTypeDeclarations(Formatter & out) const156 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
emitEnumBitwiseOperator(Formatter & out,bool lhsIsEnum,bool rhsIsEnum,const std::string & op) const200 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
emitBitFieldBitwiseAssignmentOperator(Formatter & out,const std::string & op) const246 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
emitGlobalTypeDeclarations(Formatter & out) const265 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
emitTypeDefinitions(Formatter & out,const std::string) const294 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
emitJavaTypeDeclarations(Formatter & out,bool atTopLevel) const352 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
emitVtsTypeDeclarations(Formatter & out) const438 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
emitVtsAttributeType(Formatter & out) const476 status_t EnumType::emitVtsAttributeType(Formatter &out) const {
477 out << "type: " << getVtsType() << "\n";
478 out << "predefined_type: \"" << fullName() << "\"\n";
479 return OK;
480 }
481
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const482 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
getTypeChain(std::vector<const EnumType * > * out) const490 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
getAlignmentAndSize(size_t * align,size_t * size) const505 void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
506 mStorageType->getAlignmentAndSize(align, size);
507 }
508
findExportAnnotation() const509 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
appendToExportedTypesVector(std::vector<const Type * > * exportedTypes) const519 void EnumType::appendToExportedTypesVector(
520 std::vector<const Type *> *exportedTypes) const {
521 if (findExportAnnotation() != nullptr) {
522 exportedTypes->push_back(this);
523 }
524 }
525
emitExportedHeader(Formatter & out,bool forJava) const526 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
EnumValue(const char * name,ConstantExpression * value)659 EnumValue::EnumValue(const char *name, ConstantExpression *value)
660 : mName(name),
661 mValue(value),
662 mIsAutoFill(false) {
663 }
664
name() const665 std::string EnumValue::name() const {
666 return mName;
667 }
668
value(ScalarType::Kind castKind) const669 std::string EnumValue::value(ScalarType::Kind castKind) const {
670 CHECK(mValue != nullptr);
671 return mValue->value(castKind);
672 }
673
cppValue(ScalarType::Kind castKind) const674 std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
675 CHECK(mValue != nullptr);
676 return mValue->cppValue(castKind);
677 }
javaValue(ScalarType::Kind castKind) const678 std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
679 CHECK(mValue != nullptr);
680 return mValue->javaValue(castKind);
681 }
682
comment() const683 std::string EnumValue::comment() const {
684 CHECK(mValue != nullptr);
685 return mValue->description();
686 }
687
constExpr() const688 ConstantExpression *EnumValue::constExpr() const {
689 CHECK(mValue != nullptr);
690 return mValue;
691 }
692
autofill(const EnumValue * prev,const ScalarType * type)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
isAutoFill() const707 bool EnumValue::isAutoFill() const {
708 return mIsAutoFill;
709 }
710
isEnumValue() const711 bool EnumValue::isEnumValue() const {
712 return true;
713 }
714
715 ////////////////////////////////////////////////////////////////////////////////
716
isBitField() const717 bool BitFieldType::isBitField() const {
718 return true;
719 }
720
typeName() const721 std::string BitFieldType::typeName() const {
722 return "mask" + (mElementType == nullptr ? "" : (" of " + mElementType->typeName()));
723 }
724
addNamedTypesToSet(std::set<const FQName> &) const725 void BitFieldType::addNamedTypesToSet(std::set<const FQName> &) const {
726 }
727
isCompatibleElementType(Type * elementType) const728 bool BitFieldType::isCompatibleElementType(Type *elementType) const {
729 return elementType->isEnum();
730 }
731
resolveToScalarType() const732 const ScalarType *BitFieldType::resolveToScalarType() const {
733 return mElementType->resolveToScalarType();
734 }
735
getCppType(StorageMode mode,bool specifyNamespaces) const736 std::string BitFieldType::getCppType(StorageMode mode,
737 bool specifyNamespaces) const {
738 return resolveToScalarType()->getCppType(mode, specifyNamespaces);
739 }
740
getJavaType(bool forInitializer) const741 std::string BitFieldType::getJavaType(bool forInitializer) const {
742 return resolveToScalarType()->getJavaType(forInitializer);
743 }
744
getJavaSuffix() const745 std::string BitFieldType::getJavaSuffix() const {
746 return resolveToScalarType()->getJavaSuffix();
747 }
748
getJavaWrapperType() const749 std::string BitFieldType::getJavaWrapperType() const {
750 return resolveToScalarType()->getJavaWrapperType();
751 }
752
getVtsType() const753 std::string BitFieldType::getVtsType() const {
754 return "TYPE_MASK";
755 }
756
isElidableType() const757 bool BitFieldType::isElidableType() const {
758 return resolveToScalarType()->isElidableType();
759 }
760
canCheckEquality() const761 bool BitFieldType::canCheckEquality() const {
762 return resolveToScalarType()->canCheckEquality();
763 }
764
emitVtsAttributeType(Formatter & out) const765 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
getAlignmentAndSize(size_t * align,size_t * size) const775 void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const {
776 resolveToScalarType()->getAlignmentAndSize(align, size);
777 }
778
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const779 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
getEnumType() const796 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.
emitDump(Formatter & out,const std::string & streamName,const std::string & name) const804 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
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const813 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
emitJavaFieldReaderWriter(Formatter & out,size_t depth,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const821 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