EnumType.cpp revision 1c8580863620f425188e86ec60b90cf269b5201c
1#include "EnumType.h" 2 3#include "Formatter.h" 4#include <inttypes.h> 5#include "ScalarType.h" 6 7#include <android-base/logging.h> 8 9namespace android { 10 11EnumType::EnumType( 12 const char *localName, 13 std::vector<EnumValue *> *values, 14 Type *storageType) 15 : NamedType(localName), 16 mValues(values), 17 mStorageType( 18 storageType != NULL 19 ? storageType 20 : new ScalarType(ScalarType::KIND_INT32)) { 21} 22 23const Type *EnumType::storageType() const { 24 return mStorageType; 25} 26 27const std::vector<EnumValue *> &EnumType::values() const { 28 return *mValues; 29} 30 31const ScalarType *EnumType::resolveToScalarType() const { 32 return mStorageType->resolveToScalarType(); 33} 34 35bool EnumType::isEnum() const { 36 return true; 37} 38 39std::string EnumType::getCppType(StorageMode, std::string *extra) const { 40 extra->clear(); 41 42 return fullName(); 43} 44 45std::string EnumType::getJavaType() const { 46 return mStorageType->resolveToScalarType()->getJavaType(); 47} 48 49std::string EnumType::getJavaSuffix() const { 50 return mStorageType->resolveToScalarType()->getJavaSuffix(); 51} 52 53void EnumType::emitReaderWriter( 54 Formatter &out, 55 const std::string &name, 56 const std::string &parcelObj, 57 bool parcelObjIsPointer, 58 bool isReader, 59 ErrorMode mode) const { 60 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 61 CHECK(scalarType != NULL); 62 63 scalarType->emitReaderWriterWithCast( 64 out, 65 name, 66 parcelObj, 67 parcelObjIsPointer, 68 isReader, 69 mode, 70 true /* needsCast */); 71} 72 73status_t EnumType::emitTypeDeclarations(Formatter &out) const { 74 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 75 CHECK(scalarType != NULL); 76 77 std::string extra; 78 79 out << "enum class " 80 << localName() 81 << " : " 82 << ((Type *)scalarType)->getCppType(&extra) 83 << " {\n"; 84 85 out.indent(); 86 87 std::vector<const EnumType *> chain; 88 getTypeChain(&chain); 89 90 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 91 const auto &type = *it; 92 93 for (const auto &entry : type->values()) { 94 out << entry->name(); 95 96 const char *value = entry->value(); 97 if (value != NULL) { 98 out << " = " << value; 99 } 100 101 out << ",\n"; 102 } 103 } 104 105 out.unindent(); 106 out << "};\n\n"; 107 108 return OK; 109} 110 111// Attempt to convert enum value literals into their signed equivalents, 112// i.e. if an enum value is stored in typeName 'byte', the value "192" 113// will be converted to the output "-64". 114static bool MakeSignedIntegerValue( 115 const std::string &typeName, const char *value, std::string *output) { 116 output->clear(); 117 118 char *end; 119 long long x = strtoll(value, &end, 10); 120 121 if (end > value && *end == '\0' && errno != ERANGE) { 122 char out[32]; 123 if (typeName == "byte") { 124 sprintf(out, "%d", (int)(int8_t)x); 125 } else if (typeName == "short") { 126 sprintf(out, "%d", (int)(int16_t)x); 127 } else if (typeName == "int") { 128 sprintf(out, "%d", (int)(int32_t)x); 129 } else { 130 assert(typeName == "long"); 131 sprintf(out, "%" PRId64 "L", (int64_t)x); 132 } 133 134 *output = out; 135 return true; 136 } 137 138 return false; 139} 140 141status_t EnumType::emitJavaTypeDeclarations(Formatter &out) const { 142 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 143 CHECK(scalarType != NULL); 144 145 out << "public final class " 146 << localName() 147 << " {\n"; 148 149 out.indent(); 150 151 const std::string typeName = scalarType->getJavaType(); 152 153 std::vector<const EnumType *> chain; 154 getTypeChain(&chain); 155 156 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 157 const auto &type = *it; 158 159 for (const auto &entry : type->values()) { 160 out << "public static final " 161 << typeName 162 << " " 163 << entry->name(); 164 165 const char *value = entry->value(); 166 if (value != NULL) { 167 out << " = "; 168 169 std::string convertedValue; 170 if (MakeSignedIntegerValue(typeName, value, &convertedValue)) { 171 out << convertedValue; 172 } else { 173 // The value is not an integer, but some other string, 174 // hopefully referring to some other enum name. 175 out << value; 176 } 177 } 178 179 out << ";\n"; 180 } 181 } 182 183 out.unindent(); 184 out << "};\n\n"; 185 186 return OK; 187} 188 189status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const { 190 out << "name: \"" << localName() << "\"\n" 191 << "type: TYPE_ENUM\n" 192 << "enum_value: {\n"; 193 out.indent(); 194 195 std::vector<const EnumType *> chain; 196 getTypeChain(&chain); 197 198 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 199 const auto &type = *it; 200 201 for (const auto &entry : type->values()) { 202 out << "enumerator: \"" << entry->name() << "\"\n"; 203 204 const char *value = entry->value(); 205 if (value != NULL) { 206 out << "value: " << value << "\n"; 207 } 208 } 209 } 210 211 out.unindent(); 212 out << "}\n"; 213 return OK; 214} 215 216status_t EnumType::emitVtsAttributeType(Formatter &out) const { 217 out << "type: TYPE_ENUM\n" << "predefined_type:\"" << localName() << "\"\n"; 218 return OK; 219} 220 221void EnumType::getTypeChain(std::vector<const EnumType *> *out) const { 222 out->clear(); 223 const EnumType *type = this; 224 for (;;) { 225 out->push_back(type); 226 227 const Type *superType = type->storageType(); 228 if (superType == NULL || !superType->isEnum()) { 229 break; 230 } 231 232 type = static_cast<const EnumType *>(superType); 233 } 234} 235 236//////////////////////////////////////////////////////////////////////////////// 237 238EnumValue::EnumValue(const char *name, const char *value) 239 : mName(name), 240 mValue(value) { 241} 242 243std::string EnumValue::name() const { 244 return mName; 245} 246 247const char *EnumValue::value() const { 248 return mValue; 249} 250 251} // namespace android 252 253