/*
|
* Copyright (C) 2016 The Android Open Source Project
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
|
#include "Type.h"
|
#include <sstream>
|
|
#include <hidl-util/StringHelper.h>
|
|
namespace android {
|
|
Type::Type(std::vector<Qualifier*> *qualifiers)
|
: mQualifiers(qualifiers)
|
{}
|
|
Type::~Type() {
|
if(mArrays != nullptr) {
|
for(auto* array : *mArrays) {
|
delete array;
|
}
|
}
|
|
if(mQualifiers != nullptr) {
|
for(auto* qual : *mQualifiers) {
|
delete qual;
|
}
|
}
|
delete mQualifiers;}
|
|
|
void Type::setArrays(std::vector<Expression*> *arrays) {
|
mArrays = arrays;
|
}
|
|
const std::string Type::decorateName(const std::string &name) const {
|
std::stringstream ss;
|
|
std::string special = getSpecialTypeName();
|
|
if(special.empty()) {
|
ss << getHidlType();
|
} else {
|
ss << special;
|
}
|
|
ss << " " << name;
|
|
return ss.str();
|
}
|
|
std::map<std::string, std::string> Type::kSignedToUnsignedMap = {
|
{ "char", "uint8_t" },
|
{ "short", "uint16_t" },
|
{ "int", "uint32_t" },
|
{ "long", "uint64_t" },
|
{ "int8_t", "uint8_t" },
|
{ "int16_t", "uint16_t" },
|
{ "int32_t", "uint32_t" },
|
{ "int64_t", "uint64_t" },
|
};
|
|
const std::string Type::signedToUnsigned(const std::string &signedType) {
|
auto it = kSignedToUnsignedMap.find(signedType);
|
|
if (it == kCToHidlMap.end()) {
|
return "";
|
}
|
|
return (*it).second;
|
}
|
|
std::map<std::string, std::string> Type::kCToHidlMap = {
|
{ "char", "int8_t /* NOTE: char */" },
|
{ "short", "int16_t" },
|
{ "int", "int32_t" },
|
{ "long", "int64_t"},
|
{ "native_handle_t", "handle" },
|
{ "size_t", "uint64_t" },
|
{ "int8_t", "int8_t" },
|
{ "uint8_t", "uint8_t" },
|
{ "int16_t", "int16_t" },
|
{ "uint16_t", "uint16_t" },
|
{ "int32_t", "int32_t" },
|
{ "uint32_t", "uint32_t" },
|
{ "int64_t", "int64_t" },
|
{ "uint64_t", "uint64_t" },
|
{ "float", "float" },
|
{ "double", "double" },
|
{ "bool", "bool" },
|
{ "wchar_t", "int32_t /* NOTE: wchar_t */"},
|
// { "hidl_string", "string" },
|
// { "hidl_vec", "vec"},
|
};
|
|
const std::string Type::cToHidlType(const std::string &cType) {
|
auto it = kCToHidlMap.find(cType);
|
|
if (it == kCToHidlMap.end()) {
|
return "";
|
}
|
|
return (*it).second;
|
}
|
|
const std::string Type::getHidlType() const {
|
if (mQualifiers == nullptr) {
|
return "";
|
}
|
|
std::stringstream ss;
|
|
for (auto it = mQualifiers->begin(); it != mQualifiers->end(); ++it) {
|
if (it != mQualifiers->begin()) {
|
ss << " ";
|
}
|
|
switch((*it)->qualification) {
|
case Type::Qualifier::STRUCT:
|
case Type::Qualifier::UNION:
|
case Type::Qualifier::ENUM:
|
case Type::Qualifier::POINTER:
|
case Type::Qualifier::CONST: {
|
ss << "/* "
|
<< Type::qualifierText((*it)->qualification)
|
<< " */";
|
break;
|
}
|
case Type::Qualifier::ID: {
|
std::string id = (*it)->id;
|
std::string conversion = cToHidlType(id);
|
if (!conversion.empty()) {
|
ss << conversion;
|
} else {
|
std::string baseName = StringHelper::RTrim(id, "_t");
|
ss << StringHelper::ToPascalCase(baseName);
|
}
|
break;
|
}
|
case Type::Qualifier::GENERICS: {
|
ss << "<"
|
<< (*it)->generics->decorateName("")
|
<< ">";
|
break;
|
}
|
case Type::Qualifier::UNSIGNED: {
|
auto next = it + 1;
|
if (next == mQualifiers->end()) {
|
ss << "uint32_t"; // 'unsigned a' -> 'uint32_t a'
|
break;
|
}
|
std::string unsignedType = signedToUnsigned((*next)->id);
|
if(unsignedType.empty()) {
|
ss << Type::qualifierText((*it)->qualification);
|
} else {
|
ss << unsignedType;
|
++it;
|
}
|
break;
|
}
|
default: {
|
ss << Type::qualifierText((*it)->qualification);
|
}
|
}
|
}
|
|
if (mArrays != nullptr) {
|
for (const auto &array : *mArrays) {
|
ss << "[" << array->toString() << "]";
|
}
|
}
|
|
return ss.str();
|
}
|
|
const std::string Type::getRawQualifierList() const {
|
if (mQualifiers == nullptr) {
|
return "";
|
}
|
|
std::stringstream ss;
|
|
for(auto* qualifier : *mQualifiers) {
|
ss << Type::qualifierText(qualifier->qualification) << " ";
|
}
|
|
return ss.str();
|
}
|
|
const std::string Type::getSpecialTypeName() const {
|
// this makes for a relatively expensive comparison, but it is
|
// readable until the converstion get nailed down.
|
std::string qualifiers = getRawQualifierList();
|
|
if (qualifiers == "const ID * " ||
|
qualifiers == "ID * ") {
|
|
std::string id = mQualifiers->at(mQualifiers->size() - 2)->id;
|
|
if (id == "char") {
|
return "string";
|
} else {
|
// can't tell if it's a hidl_vec or a pointer
|
// return "vec<" + id + ">";
|
return "";
|
}
|
}
|
|
return "";
|
}
|
|
bool Type::isVoid() const {
|
if (mQualifiers->size() == 0) {
|
return true;
|
}
|
|
return mQualifiers->size() == 1 &&
|
(*mQualifiers)[0]->qualification == Type::Qualifier::VOID;
|
}
|
|
bool Type::isHwDevice() const {
|
if (mQualifiers->size() < 2) {
|
return false;
|
}
|
|
return (*mQualifiers)[0]->qualification == Type::Qualifier::STRUCT &&
|
(*mQualifiers)[1]->qualification == Type::Qualifier::ID &&
|
(*mQualifiers)[1]->id == "hw_device_t";
|
}
|
|
std::string Type::removeLastId() {
|
if(mQualifiers == nullptr || mQualifiers->size() == 0) {
|
return "";
|
}
|
|
Qualifier *last = (*mQualifiers)[mQualifiers->size() - 1];
|
|
if(last == nullptr || last->qualification != Qualifier::ID) {
|
return "";
|
}
|
|
std::string ret{last->id};
|
|
mQualifiers->erase(mQualifiers->end() - 1);
|
|
return ret;
|
}
|
|
} //namespace android
|