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 "Type.h" 18 #include <sstream> 19 20 #include <hidl-util/StringHelper.h> 21 22 namespace android { 23 24 Type::Type(std::vector<Qualifier*> *qualifiers) 25 : mQualifiers(qualifiers) 26 {} 27 28 Type::~Type() { 29 if(mArrays != NULL) { 30 for(auto* array : *mArrays) { 31 delete array; 32 } 33 } 34 35 if(mQualifiers != NULL) { 36 for(auto* qual : *mQualifiers) { 37 delete qual; 38 } 39 } 40 delete mQualifiers;} 41 42 43 void Type::setArrays(std::vector<Expression*> *arrays) { 44 mArrays = arrays; 45 } 46 47 const std::string Type::decorateName(const std::string &name) const { 48 std::stringstream ss; 49 50 std::string special = getSpecialTypeName(); 51 52 if(special.empty()) { 53 ss << getHidlType(); 54 } else { 55 ss << special; 56 } 57 58 ss << " " << name; 59 60 return ss.str(); 61 } 62 63 // static 64 std::map<std::string, std::string> Type::kSignedToUnsignedMap = { 65 { "char", "uint8_t" }, 66 { "short", "uint16_t" }, 67 { "int", "uint32_t" }, 68 { "long", "uint64_t" }, 69 { "int8_t", "uint8_t" }, 70 { "int16_t", "uint16_t" }, 71 { "int32_t", "uint32_t" }, 72 { "int64_t", "uint64_t" }, 73 }; 74 75 // static 76 const std::string Type::signedToUnsigned(const std::string &signedType) { 77 auto it = kSignedToUnsignedMap.find(signedType); 78 79 if (it == kCToHidlMap.end()) { 80 return ""; 81 } 82 83 return (*it).second; 84 } 85 86 // static 87 std::map<std::string, std::string> Type::kCToHidlMap = { 88 { "char", "int8_t /* NOTE: char */" }, 89 { "short", "int16_t" }, 90 { "int", "int32_t" }, 91 { "long", "int64_t"}, 92 { "native_handle_t", "handle" }, 93 { "size_t", "uint64_t" }, 94 { "int8_t", "int8_t" }, 95 { "uint8_t", "uint8_t" }, 96 { "int16_t", "int16_t" }, 97 { "uint16_t", "uint16_t" }, 98 { "int32_t", "int32_t" }, 99 { "uint32_t", "uint32_t" }, 100 { "int64_t", "int64_t" }, 101 { "uint64_t", "uint64_t" }, 102 { "float", "float" }, 103 { "double", "double" }, 104 { "bool", "bool" }, 105 { "wchar_t", "int32_t /* NOTE: wchar_t */"}, 106 // { "hidl_string", "string" }, 107 // { "hidl_vec", "vec"}, 108 }; 109 110 // static 111 const std::string Type::cToHidlType(const std::string &cType) { 112 auto it = kCToHidlMap.find(cType); 113 114 if (it == kCToHidlMap.end()) { 115 return ""; 116 } 117 118 return (*it).second; 119 } 120 121 const std::string Type::getHidlType() const { 122 if (mQualifiers == NULL) { 123 return ""; 124 } 125 126 std::stringstream ss; 127 128 for (auto it = mQualifiers->begin(); it != mQualifiers->end(); ++it) { 129 if (it != mQualifiers->begin()) { 130 ss << " "; 131 } 132 133 switch((*it)->qualification) { 134 case Type::Qualifier::STRUCT: 135 case Type::Qualifier::UNION: 136 case Type::Qualifier::ENUM: 137 case Type::Qualifier::POINTER: 138 case Type::Qualifier::CONST: { 139 ss << "/* " 140 << Type::qualifierText((*it)->qualification) 141 << " */"; 142 break; 143 } 144 case Type::Qualifier::ID: { 145 std::string id = (*it)->id; 146 std::string conversion = cToHidlType(id); 147 if (!conversion.empty()) { 148 ss << conversion; 149 } else { 150 std::string baseName = StringHelper::RTrim(id, "_t"); 151 ss << StringHelper::ToPascalCase(baseName); 152 } 153 break; 154 } 155 case Type::Qualifier::GENERICS: { 156 ss << "<" 157 << (*it)->generics->decorateName("") 158 << ">"; 159 break; 160 } 161 case Type::Qualifier::UNSIGNED: { 162 auto next = it + 1; 163 if (next == mQualifiers->end()) { 164 ss << "uint32_t"; // 'unsigned a' -> 'uint32_t a' 165 break; 166 } 167 std::string unsignedType = signedToUnsigned((*next)->id); 168 if(unsignedType.empty()) { 169 ss << Type::qualifierText((*it)->qualification); 170 } else { 171 ss << unsignedType; 172 ++it; 173 } 174 break; 175 } 176 default: { 177 ss << Type::qualifierText((*it)->qualification); 178 } 179 } 180 } 181 182 if (mArrays != NULL) { 183 for (const auto &array : *mArrays) { 184 ss << "[" << array->toString() << "]"; 185 } 186 } 187 188 return ss.str(); 189 } 190 191 const std::string Type::getRawQualifierList() const { 192 if (mQualifiers == NULL) { 193 return ""; 194 } 195 196 std::stringstream ss; 197 198 for(auto* qualifier : *mQualifiers) { 199 ss << Type::qualifierText(qualifier->qualification) << " "; 200 } 201 202 return ss.str(); 203 } 204 205 const std::string Type::getSpecialTypeName() const { 206 // this makes for a relatively expensive comparison, but it is 207 // readable until the converstion get nailed down. 208 std::string qualifiers = getRawQualifierList(); 209 210 if (qualifiers == "const ID * " || 211 qualifiers == "ID * ") { 212 213 std::string id = mQualifiers->at(mQualifiers->size() - 2)->id; 214 215 if (id == "char") { 216 return "string"; 217 } else { 218 // can't tell if it's a hidl_vec or a pointer 219 // return "vec<" + id + ">"; 220 return ""; 221 } 222 } 223 224 return ""; 225 } 226 227 bool Type::isVoid() const { 228 if (mQualifiers->size() == 0) { 229 return true; 230 } 231 232 return mQualifiers->size() == 1 && 233 (*mQualifiers)[0]->qualification == Type::Qualifier::VOID; 234 } 235 236 bool Type::isHwDevice() const { 237 if (mQualifiers->size() < 2) { 238 return false; 239 } 240 241 return (*mQualifiers)[0]->qualification == Type::Qualifier::STRUCT && 242 (*mQualifiers)[1]->qualification == Type::Qualifier::ID && 243 (*mQualifiers)[1]->id == "hw_device_t"; 244 } 245 246 std::string Type::removeLastId() { 247 if(mQualifiers == NULL || mQualifiers->size() == 0) { 248 return ""; 249 } 250 251 Qualifier *last = (*mQualifiers)[mQualifiers->size() - 1]; 252 253 if(last == NULL || last->qualification != Qualifier::ID) { 254 return ""; 255 } 256 257 std::string ret{last->id}; 258 259 mQualifiers->erase(mQualifiers->end() - 1); 260 261 return ret; 262 } 263 264 } //namespace android 265