ArrayType.cpp revision a72e0d2be173cebf62f728b9d215808bd862f219
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 "ArrayType.h" 18 19#include <hidl-util/Formatter.h> 20#include <android-base/logging.h> 21 22namespace android { 23 24ArrayType::ArrayType(Type *elementType, const char *dimension) 25 : mElementType(elementType), 26 mDimension(dimension) { 27} 28 29void ArrayType::addNamedTypesToSet(std::set<const FQName> &set) const { 30 mElementType->addNamedTypesToSet(set); 31} 32 33std::string ArrayType::getCppType(StorageMode mode, 34 std::string *extra, 35 bool specifyNamespaces) const { 36 const std::string base = mElementType->getCppType(extra, specifyNamespaces); 37 38 CHECK(extra->empty()); 39 40 *extra = "[" + mDimension + "]"; 41 42 switch (mode) { 43 case StorageMode_Stack: 44 return base; 45 46 case StorageMode_Argument: 47 return "const " + base; 48 49 case StorageMode_Result: 50 { 51 extra->clear(); 52 return "const " + base + "*"; 53 } 54 } 55} 56 57std::string ArrayType::getJavaType() const { 58 return mElementType->getJavaType() + "[]"; 59} 60 61void ArrayType::emitReaderWriter( 62 Formatter &out, 63 const std::string &name, 64 const std::string &parcelObj, 65 bool parcelObjIsPointer, 66 bool isReader, 67 ErrorMode mode) const { 68 std::string baseExtra; 69 std::string baseType = mElementType->getCppType(&baseExtra); 70 71 const std::string parentName = "_hidl_" + name + "_parent"; 72 73 out << "size_t " << parentName << ";\n\n"; 74 75 const std::string parcelObjDeref = 76 parcelObj + (parcelObjIsPointer ? "->" : "."); 77 78 if (isReader) { 79 out << name 80 << " = (const " 81 << baseType 82 << " *)" 83 << parcelObjDeref 84 << "readBuffer(&" 85 << parentName 86 << ");\n\n"; 87 88 out << "if (" << name << " == nullptr) {\n"; 89 90 out.indent(); 91 92 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n"; 93 handleError2(out, mode); 94 95 out.unindent(); 96 out << "}\n\n"; 97 } else { 98 out << "_hidl_err = " 99 << parcelObjDeref 100 << "writeBuffer(" 101 << name 102 << ", " 103 << mDimension 104 << " * sizeof(" 105 << baseType 106 << "), &" 107 << parentName 108 << ");\n"; 109 110 handleError(out, mode); 111 } 112 113 emitReaderWriterEmbedded( 114 out, 115 name, 116 isReader /* nameIsPointer */, 117 parcelObj, 118 parcelObjIsPointer, 119 isReader, 120 mode, 121 parentName, 122 "0 /* parentOffset */"); 123} 124 125void ArrayType::emitReaderWriterEmbedded( 126 Formatter &out, 127 const std::string &name, 128 bool nameIsPointer, 129 const std::string &parcelObj, 130 bool parcelObjIsPointer, 131 bool isReader, 132 ErrorMode mode, 133 const std::string &parentName, 134 const std::string &offsetText) const { 135 if (!mElementType->needsEmbeddedReadWrite()) { 136 return; 137 } 138 139 const std::string nameDeref = name + (nameIsPointer ? "->" : "."); 140 141 std::string baseExtra; 142 std::string baseType = mElementType->getCppType(&baseExtra); 143 144 out << "for (size_t _hidl_index = 0; _hidl_index < " 145 << mDimension 146 << "; ++_hidl_index) {\n"; 147 148 out.indent(); 149 150 mElementType->emitReaderWriterEmbedded( 151 out, 152 name + "[_hidl_index]", 153 false /* nameIsPointer */, 154 parcelObj, 155 parcelObjIsPointer, 156 isReader, 157 mode, 158 parentName, 159 offsetText + " + _hidl_index * sizeof(" + baseType + ")"); 160 161 out.unindent(); 162 163 out << "}\n\n"; 164} 165 166bool ArrayType::needsEmbeddedReadWrite() const { 167 return mElementType->needsEmbeddedReadWrite(); 168} 169 170void ArrayType::emitJavaReaderWriter( 171 Formatter &out, 172 const std::string &parcelObj, 173 const std::string &argName, 174 bool isReader) const { 175 if (mElementType->isCompoundType()) { 176 if (isReader) { 177 out << mElementType->getJavaType() 178 << ".readArrayFromParcel(" 179 << parcelObj 180 << ", " 181 << mDimension 182 << ");\n"; 183 } else { 184 out << mElementType->getJavaType() 185 << ".writeArrayToParcel(" 186 << parcelObj 187 << ", " 188 << mDimension 189 << ", " 190 << argName 191 << ");\n"; 192 } 193 194 return; 195 } 196 197 emitJavaReaderWriterWithSuffix( 198 out, 199 parcelObj, 200 argName, 201 isReader, 202 mElementType->getJavaSuffix() + "Array", 203 mDimension); 204} 205 206void ArrayType::emitJavaFieldInitializer( 207 Formatter &out, const std::string &fieldName) const { 208 out << "final " 209 << mElementType->getJavaType() 210 << "[] " 211 << fieldName 212 << " = new " 213 << mElementType->getJavaType() 214 << "[" 215 << mDimension 216 << "];\n"; 217} 218 219void ArrayType::emitJavaFieldReaderWriter( 220 Formatter &out, 221 const std::string &blobName, 222 const std::string &fieldName, 223 const std::string &offset, 224 bool isReader) const { 225 out << "for (int _hidl_index = 0; _hidl_index < " 226 << mDimension 227 << "; ++_hidl_index) {\n"; 228 229 out.indent(); 230 231 size_t elementAlign, elementSize; 232 mElementType->getAlignmentAndSize(&elementAlign, &elementSize); 233 234 mElementType->emitJavaFieldReaderWriter( 235 out, 236 blobName, 237 fieldName + "[_hidl_index]", 238 offset + " + _hidl_index * " + std::to_string(elementSize), 239 isReader); 240 241 out.unindent(); 242 out << "}\n"; 243} 244 245status_t ArrayType::emitVtsTypeDeclarations(Formatter &out) const { 246 out << "type: TYPE_ARRAY\n" << "vector_value: {\n"; 247 out.indent(); 248 out << "size: " << mDimension << "\n"; 249 status_t err = mElementType->emitVtsTypeDeclarations(out); 250 if (err != OK) { 251 return err; 252 } 253 out.unindent(); 254 out << "}\n"; 255 return OK; 256} 257 258bool ArrayType::isJavaCompatible() const { 259 return mElementType->isJavaCompatible(); 260} 261 262void ArrayType::getAlignmentAndSize(size_t *align, size_t *size) const { 263 mElementType->getAlignmentAndSize(align, size); 264 265 char *end; 266 unsigned long dim = strtoul(mDimension.c_str(), &end, 10); 267 CHECK(end > mDimension.c_str() && *end == '\0'); 268 269 (*size) *= dim; 270} 271 272} // namespace android 273 274