/*
* 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 "ScalarType.h"
#include <hidl-util/Formatter.h>
namespace android {
ScalarType::ScalarType(Kind kind, Scope* parent) : Type(parent), mKind(kind) {}
const ScalarType *ScalarType::resolveToScalarType() const {
return this;
}
bool ScalarType::isValidEnumStorageType() const {
// Only integer types.
return mKind >= KIND_INT8 && mKind <= KIND_UINT64;
}
bool ScalarType::isScalar() const {
return true;
}
bool ScalarType::isElidableType() const {
return true;
}
bool ScalarType::deepCanCheckEquality(std::unordered_set<const Type*>* /* visited */) const {
return true;
}
std::string ScalarType::typeName() const {
return getCppStackType();
}
std::string ScalarType::getCppType(StorageMode, bool) const {
static const char *const kName[] = {
"bool",
"int8_t",
"uint8_t",
"int16_t",
"uint16_t",
"int32_t",
"uint32_t",
"int64_t",
"uint64_t",
"float",
"double"
};
return kName[mKind];
}
std::string ScalarType::getJavaType(bool /* forInitializer */) const {
static const char *const kName[] = {
"boolean",
"byte",
"byte",
"short",
"short",
"int",
"int",
"long",
"long",
"float",
"double"
};
return kName[mKind];
}
std::string ScalarType::getJavaTypeClass() const {
static const char *const kName[] = {
"Boolean",
"Byte",
"Byte",
"Short",
"Short",
"Integer",
"Integer",
"Long",
"Long",
"Float",
"Double"
};
return kName[mKind];
}
std::string ScalarType::getJavaSuffix() const {
static const char *const kSuffix[] = {
"Bool",
"Int8",
"Int8",
"Int16",
"Int16",
"Int32",
"Int32",
"Int64",
"Int64",
"Float",
"Double"
};
return kSuffix[mKind];
}
std::string ScalarType::getVtsType() const {
return "TYPE_SCALAR";
}
std::string ScalarType::getVtsScalarType() const {
static const char * const kName[] = {
"bool_t",
"int8_t",
"uint8_t",
"int16_t",
"uint16_t",
"int32_t",
"uint32_t",
"int64_t",
"uint64_t",
"float_t",
"double_t"
};
return kName[mKind];
}
void ScalarType::emitReaderWriter(
Formatter &out,
const std::string &name,
const std::string &parcelObj,
bool parcelObjIsPointer,
bool isReader,
ErrorMode mode) const {
emitReaderWriterWithCast(
out,
name,
parcelObj,
parcelObjIsPointer,
isReader,
mode,
false /* needsCast */);
}
void ScalarType::emitReaderWriterWithCast(
Formatter &out,
const std::string &name,
const std::string &parcelObj,
bool parcelObjIsPointer,
bool isReader,
ErrorMode mode,
bool needsCast) const {
static const char *const kSuffix[] = {
"Bool",
"Int8",
"Uint8",
"Int16",
"Uint16",
"Int32",
"Uint32",
"Int64",
"Uint64",
"Float",
"Double"
};
const std::string parcelObjDeref =
parcelObj + (parcelObjIsPointer ? "->" : ".");
out << "_hidl_err = "
<< parcelObjDeref
<< (isReader ? "read" : "write")
<< kSuffix[mKind]
<< "(";
if (needsCast) {
out << "("
<< getCppStackType()
<< (isReader ? " *)" : ")");
}
if (isReader) {
out << "&";
}
out << name
<< ");\n";
handleError(out, mode);
}
void ScalarType::emitHexDump(
Formatter &out,
const std::string &streamName,
const std::string &name) const {
out << streamName << " += toHexString(" << name << ");\n";
}
void ScalarType::emitConvertToJavaHexString(
Formatter &out,
const std::string &name) const {
switch(mKind) {
case KIND_BOOL: {
out << "((" << name << ") ? \"0x1\" : \"0x0\")";
break;
}
case KIND_INT8: // fallthrough
case KIND_UINT8: // fallthrough
case KIND_INT16: // fallthrough
case KIND_UINT16: {
// Because Byte and Short doesn't have toHexString, we have to use Integer.toHexString.
out << "Integer.toHexString(" << getJavaTypeClass() << ".toUnsignedInt(("
<< getJavaType(false /* forInitializer */) << ")(" << name << ")))";
break;
}
case KIND_INT32: // fallthrough
case KIND_UINT32: // fallthrough
case KIND_INT64: // fallthrough
case KIND_UINT64: {
out << getJavaTypeClass() << ".toHexString(" << name << ")";
break;
}
case KIND_FLOAT: // fallthrough
case KIND_DOUBLE: // fallthrough
default: {
// no hex for floating point numbers.
out << name;
break;
}
}
}
void ScalarType::emitJavaFieldReaderWriter(
Formatter &out,
size_t /* depth */,
const std::string & /* parcelName */,
const std::string &blobName,
const std::string &fieldName,
const std::string &offset,
bool isReader) const {
if (isReader) {
out << fieldName
<< " = "
<< blobName
<< ".get"
<< getJavaSuffix()
<< "("
<< offset
<< ");\n";
return;
}
out << blobName
<< ".put"
<< getJavaSuffix()
<< "("
<< offset
<< ", "
<< fieldName
<< ");\n";
}
void ScalarType::emitVtsTypeDeclarations(Formatter& out) const {
out << "type: " << getVtsType() << "\n";
out << "scalar_type: \"" << getVtsScalarType() << "\"\n";
}
void ScalarType::getAlignmentAndSize(size_t *align, size_t *size) const {
static const size_t kAlign[] = {
1, // bool, this is NOT standardized!
1, // int8_t
1, // uint8_t
2, // int16_t
2, // uint16_t
4, // int32_t
4, // uint32_t
8, // int64_t
8, // uint64_t
4, // float
8 // double
};
*align = *size = kAlign[mKind];
}
ScalarType::Kind ScalarType::getKind() const {
return mKind;
}
} // namespace android