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