ArrayType.cpp revision 709b62dbda6184770bb34470ff550e02c1643e67
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(ArrayType *srcArray, size_t size) 25 : mElementType(srcArray->mElementType), 26 mSizes(srcArray->mSizes) { 27 addDimension(size); 28} 29 30ArrayType::ArrayType(Type *elementType, size_t size) 31 : mElementType(elementType) { 32 addDimension(size); 33} 34 35void ArrayType::addDimension(size_t size) { 36 mSizes.insert(mSizes.begin(), size); 37} 38 39void ArrayType::addNamedTypesToSet(std::set<const FQName> &set) const { 40 mElementType->addNamedTypesToSet(set); 41} 42 43bool ArrayType::isArray() const { 44 return true; 45} 46 47std::string ArrayType::getCppType(StorageMode mode, 48 std::string *extra, 49 bool specifyNamespaces) const { 50 const std::string base = mElementType->getCppType(extra, specifyNamespaces); 51 CHECK(extra->empty()); 52 53 size_t numArrayElements = 1; 54 for (auto size : mSizes) { 55 numArrayElements *= size; 56 } 57 58 *extra += "["; 59 *extra += std::to_string(numArrayElements); 60 *extra += "]"; 61 62 switch (mode) { 63 case StorageMode_Stack: 64 return base; 65 66 case StorageMode_Argument: 67 case StorageMode_Result: 68 { 69 *extra = " /* " + base; 70 for (auto size : mSizes) { 71 *extra += "[" + std::to_string(size) + "]"; 72 } 73 *extra += " */"; 74 75 return "const " + base + "*"; 76 } 77 } 78} 79 80std::string ArrayType::getJavaType( 81 std::string *extra, bool forInitializer) const { 82 std::string baseExtra; 83 const std::string base = 84 mElementType->getJavaType(&baseExtra, forInitializer); 85 86 CHECK(baseExtra.empty()); 87 88 extra->clear(); 89 90 for (auto size : mSizes) { 91 *extra += "["; 92 93 if (forInitializer) { 94 *extra += std::to_string(size); 95 } 96 97 *extra += "]"; 98 } 99 100 return base; 101} 102 103void ArrayType::emitReaderWriter( 104 Formatter &out, 105 const std::string &name, 106 const std::string &parcelObj, 107 bool parcelObjIsPointer, 108 bool isReader, 109 ErrorMode mode) const { 110 std::string baseExtra; 111 std::string baseType = mElementType->getCppType(&baseExtra); 112 CHECK(baseExtra.empty()); 113 114 const std::string parentName = "_hidl_" + name + "_parent"; 115 116 out << "size_t " << parentName << ";\n\n"; 117 118 const std::string parcelObjDeref = 119 parcelObj + (parcelObjIsPointer ? "->" : "."); 120 121 if (isReader) { 122 out << name 123 << " = (const " 124 << baseType 125 << " *)" 126 << parcelObjDeref 127 << "readBuffer(&" 128 << parentName 129 << ");\n\n"; 130 131 out << "if (" << name << " == nullptr) {\n"; 132 133 out.indent(); 134 135 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n"; 136 handleError2(out, mode); 137 138 out.unindent(); 139 out << "}\n\n"; 140 } else { 141 out << "_hidl_err = " 142 << parcelObjDeref 143 << "writeBuffer(" 144 << name 145 << ", "; 146 147 for (auto size : mSizes) { 148 out << size << " * "; 149 } 150 151 out << "sizeof(" 152 << baseType 153 << "), &" 154 << parentName 155 << ");\n"; 156 157 handleError(out, mode); 158 } 159 160 emitReaderWriterEmbedded( 161 out, 162 0 /* depth */, 163 name, 164 isReader /* nameIsPointer */, 165 parcelObj, 166 parcelObjIsPointer, 167 isReader, 168 mode, 169 parentName, 170 "0 /* parentOffset */"); 171} 172 173void ArrayType::emitReaderWriterEmbedded( 174 Formatter &out, 175 size_t depth, 176 const std::string &name, 177 bool nameIsPointer, 178 const std::string &parcelObj, 179 bool parcelObjIsPointer, 180 bool isReader, 181 ErrorMode mode, 182 const std::string &parentName, 183 const std::string &offsetText) const { 184 if (!mElementType->needsEmbeddedReadWrite()) { 185 return; 186 } 187 188 const std::string nameDeref = name + (nameIsPointer ? "->" : "."); 189 190 std::string baseExtra; 191 std::string baseType = mElementType->getCppType(&baseExtra); 192 CHECK(baseExtra.empty()); 193 194 std::string iteratorName = "_hidl_index_" + std::to_string(depth); 195 196 size_t numArrayElements = 1; 197 for (auto size : mSizes) { 198 numArrayElements *= size; 199 } 200 201 out << "for (size_t " 202 << iteratorName 203 << " = 0; " 204 << iteratorName 205 << " < " 206 << numArrayElements 207 << "; ++" 208 << iteratorName 209 << ") {\n"; 210 211 out.indent(); 212 213 mElementType->emitReaderWriterEmbedded( 214 out, 215 depth + 1, 216 name + "[" + iteratorName + "]", 217 false /* nameIsPointer */, 218 parcelObj, 219 parcelObjIsPointer, 220 isReader, 221 mode, 222 parentName, 223 offsetText 224 + " + " + iteratorName + " * sizeof(" 225 + baseType 226 + ")"); 227 228 out.unindent(); 229 230 out << "}\n\n"; 231} 232 233bool ArrayType::needsEmbeddedReadWrite() const { 234 return mElementType->needsEmbeddedReadWrite(); 235} 236 237void ArrayType::emitJavaReaderWriter( 238 Formatter &out, 239 const std::string &parcelObj, 240 const std::string &argName, 241 bool isReader) const { 242 if (isReader) { 243 std::string extra; 244 out << "new " 245 << getJavaType(&extra, true /* forInitializer */) 246 << extra 247 << ";\n"; 248 } 249 250 out << "{\n"; 251 out.indent(); 252 253 out << "HwBlob _hidl_blob = "; 254 255 if (isReader) { 256 out << parcelObj 257 << ".readBuffer();\n"; 258 } else { 259 size_t align, size; 260 getAlignmentAndSize(&align, &size); 261 262 out << "new HwBlob(" 263 << size 264 << " /* size */);\n"; 265 } 266 267 emitJavaFieldReaderWriter( 268 out, 269 0 /* depth */, 270 parcelObj, 271 "_hidl_blob", 272 argName, 273 "0 /* offset */", 274 isReader); 275 276 if (!isReader) { 277 out << parcelObj << ".writeBuffer(_hidl_blob);\n"; 278 } 279 280 out.unindent(); 281 out << "}\n"; 282} 283 284void ArrayType::emitJavaFieldInitializer( 285 Formatter &out, const std::string &fieldName) const { 286 std::string extra; 287 std::string typeName = getJavaType(&extra, false /* forInitializer */); 288 289 std::string extraInit; 290 getJavaType(&extraInit, true /* forInitializer */); 291 292 out << "final " 293 << typeName 294 << extra 295 << " " 296 << fieldName 297 << " = new " 298 << typeName 299 << extraInit 300 << ";\n"; 301} 302 303void ArrayType::emitJavaFieldReaderWriter( 304 Formatter &out, 305 size_t depth, 306 const std::string &parcelName, 307 const std::string &blobName, 308 const std::string &fieldName, 309 const std::string &offset, 310 bool isReader) const { 311 std::string offsetName = "_hidl_array_offset_" + std::to_string(depth); 312 out << "long " << offsetName << " = " << offset << ";\n"; 313 314 std::string indexString; 315 for (size_t dim = 0; dim < mSizes.size(); ++dim) { 316 std::string iteratorName = 317 "_hidl_index_" + std::to_string(depth) + "_" + std::to_string(dim); 318 319 out << "for (int " 320 << iteratorName 321 << " = 0; " 322 << iteratorName 323 << " < " 324 << mSizes[dim] 325 << "; ++" 326 << iteratorName 327 << ") {\n"; 328 329 out.indent(); 330 331 indexString += "[" + iteratorName + "]"; 332 } 333 334 if (isReader && mElementType->isCompoundType()) { 335 std::string extra; 336 std::string typeName = 337 mElementType->getJavaType(&extra, false /* forInitializer */); 338 339 CHECK(extra.empty()); 340 341 out << fieldName 342 << indexString 343 << " = new " 344 << typeName 345 << "();\n"; 346 } 347 348 mElementType->emitJavaFieldReaderWriter( 349 out, 350 depth + 1, 351 parcelName, 352 blobName, 353 fieldName + indexString, 354 offsetName, 355 isReader); 356 357 size_t elementAlign, elementSize; 358 mElementType->getAlignmentAndSize(&elementAlign, &elementSize); 359 360 out << offsetName << " += " << std::to_string(elementSize) << ";\n"; 361 362 for (size_t dim = 0; dim < mSizes.size(); ++dim) { 363 out.unindent(); 364 out << "}\n"; 365 } 366} 367 368status_t ArrayType::emitVtsTypeDeclarations(Formatter &out) const { 369 if (mSizes.size() > 1) { 370 // Multi-dimensional arrays are yet to be supported in VTS. 371 return UNKNOWN_ERROR; 372 } 373 374 out << "type: TYPE_ARRAY\n" << "vector_value: {\n"; 375 out.indent(); 376 out << "size: " << mSizes[0] << "\n"; 377 status_t err = mElementType->emitVtsTypeDeclarations(out); 378 if (err != OK) { 379 return err; 380 } 381 out.unindent(); 382 out << "}\n"; 383 return OK; 384} 385 386bool ArrayType::isJavaCompatible() const { 387 return mElementType->isJavaCompatible(); 388} 389 390void ArrayType::getAlignmentAndSize(size_t *align, size_t *size) const { 391 mElementType->getAlignmentAndSize(align, size); 392 393 for (auto sizeInDimension : mSizes) { 394 (*size) *= sizeInDimension; 395 } 396} 397 398} // namespace android 399 400