ArrayType.cpp revision 3b320f8a60e4343bf06319bca3fc949c95eaf326
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 22#include "ConstantExpression.h" 23 24namespace android { 25 26ArrayType::ArrayType(ArrayType *srcArray, ConstantExpression *size) 27 : mElementType(srcArray->mElementType), 28 mSizes(srcArray->mSizes) { 29 prependDimension(size); 30} 31 32ArrayType::ArrayType(Type *elementType, ConstantExpression *size) 33 : mElementType(elementType) { 34 prependDimension(size); 35} 36 37void ArrayType::prependDimension(ConstantExpression *size) { 38 mSizes.insert(mSizes.begin(), size); 39} 40 41void ArrayType::appendDimension(ConstantExpression *size) { 42 mSizes.push_back(size); 43} 44 45size_t ArrayType::countDimensions() const { 46 return mSizes.size(); 47} 48 49void ArrayType::addNamedTypesToSet(std::set<const FQName> &set) const { 50 mElementType->addNamedTypesToSet(set); 51} 52 53bool ArrayType::isArray() const { 54 return true; 55} 56 57Type *ArrayType::getElementType() const { 58 return mElementType; 59} 60 61std::string ArrayType::getCppType(StorageMode mode, 62 bool specifyNamespaces) const { 63 const std::string base = mElementType->getCppStackType(specifyNamespaces); 64 65 std::string space = specifyNamespaces ? "::android::hardware::" : ""; 66 std::string arrayType = space + "hidl_array<" + base; 67 68 for (size_t i = 0; i < mSizes.size(); ++i) { 69 arrayType += ", "; 70 arrayType += mSizes[i]->cppValue(); 71 72 if (!mSizes[i]->descriptionIsTrivial()) { 73 arrayType += " /* "; 74 arrayType += mSizes[i]->description(); 75 arrayType += " */"; 76 } 77 } 78 79 arrayType += ">"; 80 81 switch (mode) { 82 case StorageMode_Stack: 83 return arrayType; 84 85 case StorageMode_Argument: 86 return "const " + arrayType + "&"; 87 88 case StorageMode_Result: 89 return "const " + arrayType + "*"; 90 } 91 92 CHECK(!"Should not be here"); 93} 94 95std::string ArrayType::getJavaType( 96 std::string *extra, bool forInitializer) const { 97 std::string baseExtra; 98 const std::string base = 99 mElementType->getJavaType(&baseExtra, forInitializer); 100 101 CHECK(baseExtra.empty()); 102 103 extra->clear(); 104 105 for (size_t i = 0; i < mSizes.size(); ++i) { 106 *extra += "["; 107 108 if (forInitializer) { 109 *extra += mSizes[i]->javaValue(); 110 } 111 112 if (!forInitializer || !mSizes[i]->descriptionIsTrivial()) { 113 if (forInitializer) 114 *extra += " "; 115 *extra += "/* " + mSizes[i]->description() + " */"; 116 } 117 118 *extra += "]"; 119 } 120 121 return base; 122} 123 124std::string ArrayType::getJavaWrapperType() const { 125 return mElementType->getJavaWrapperType(); 126} 127 128std::string ArrayType::getVtsType() const { 129 return "TYPE_ARRAY"; 130} 131 132void ArrayType::emitReaderWriter( 133 Formatter &out, 134 const std::string &name, 135 const std::string &parcelObj, 136 bool parcelObjIsPointer, 137 bool isReader, 138 ErrorMode mode) const { 139 std::string baseType = mElementType->getCppStackType(); 140 141 const std::string parentName = "_hidl_" + name + "_parent"; 142 143 out << "size_t " << parentName << ";\n\n"; 144 145 const std::string parcelObjDeref = 146 parcelObj + (parcelObjIsPointer ? "->" : "."); 147 148 if (isReader) { 149 150 out << name 151 << " = (" 152 << getCppResultType() 153 << ")" 154 << parcelObjDeref 155 << "readBuffer(&" 156 << parentName 157 << ");\n\n"; 158 159 out << "if (" << name << " == nullptr) {\n"; 160 161 out.indent(); 162 163 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n"; 164 handleError2(out, mode); 165 166 out.unindent(); 167 out << "}\n\n"; 168 } else { 169 size_t numArrayElements = 1; 170 for (auto size : mSizes) { 171 numArrayElements *= size->castSizeT(); 172 } 173 174 out << "_hidl_err = " 175 << parcelObjDeref 176 << "writeBuffer(" 177 << name 178 << ".data(), " 179 << numArrayElements 180 << " * sizeof(" 181 << baseType 182 << "), &" 183 << parentName 184 << ");\n"; 185 186 handleError(out, mode); 187 } 188 189 emitReaderWriterEmbedded( 190 out, 191 0 /* depth */, 192 name, 193 name /* sanitizedName */, 194 isReader /* nameIsPointer */, 195 parcelObj, 196 parcelObjIsPointer, 197 isReader, 198 mode, 199 parentName, 200 "0 /* parentOffset */"); 201} 202 203void ArrayType::emitReaderWriterEmbedded( 204 Formatter &out, 205 size_t depth, 206 const std::string &name, 207 const std::string &sanitizedName, 208 bool nameIsPointer, 209 const std::string &parcelObj, 210 bool parcelObjIsPointer, 211 bool isReader, 212 ErrorMode mode, 213 const std::string &parentName, 214 const std::string &offsetText) const { 215 if (!mElementType->needsEmbeddedReadWrite()) { 216 return; 217 } 218 219 const std::string nameDeref = name + (nameIsPointer ? "->" : "."); 220 221 std::string baseType = mElementType->getCppStackType(); 222 223 std::string iteratorName = "_hidl_index_" + std::to_string(depth); 224 225 out << "for (size_t " 226 << iteratorName 227 << " = 0; " 228 << iteratorName 229 << " < " 230 << dimension() 231 << "; ++" 232 << iteratorName 233 << ") {\n"; 234 235 out.indent(); 236 237 mElementType->emitReaderWriterEmbedded( 238 out, 239 depth + 1, 240 nameDeref + "data()[" + iteratorName + "]", 241 sanitizedName + "_indexed", 242 false /* nameIsPointer */, 243 parcelObj, 244 parcelObjIsPointer, 245 isReader, 246 mode, 247 parentName, 248 offsetText 249 + " + " + iteratorName + " * sizeof(" 250 + baseType 251 + ")"); 252 253 out.unindent(); 254 255 out << "}\n\n"; 256} 257 258void ArrayType::emitResolveReferences( 259 Formatter &out, 260 const std::string &name, 261 bool nameIsPointer, 262 const std::string &parcelObj, 263 bool parcelObjIsPointer, 264 bool isReader, 265 ErrorMode mode) const { 266 emitResolveReferencesEmbedded( 267 out, 268 0 /* depth */, 269 name, 270 name /* sanitizedName */, 271 nameIsPointer, 272 parcelObj, 273 parcelObjIsPointer, 274 isReader, 275 mode, 276 "_hidl_" + name + "_parent", 277 "0 /* parentOffset */"); 278} 279 280void ArrayType::emitResolveReferencesEmbedded( 281 Formatter &out, 282 size_t depth, 283 const std::string &name, 284 const std::string &sanitizedName, 285 bool nameIsPointer, 286 const std::string &parcelObj, 287 bool parcelObjIsPointer, 288 bool isReader, 289 ErrorMode mode, 290 const std::string &parentName, 291 const std::string &offsetText) const { 292 CHECK(needsResolveReferences() && mElementType->needsResolveReferences()); 293 294 const std::string nameDeref = name + (nameIsPointer ? "->" : "."); 295 296 std::string baseType = mElementType->getCppStackType(); 297 298 std::string iteratorName = "_hidl_index_" + std::to_string(depth); 299 300 out << "for (size_t " 301 << iteratorName 302 << " = 0; " 303 << iteratorName 304 << " < " 305 << dimension() 306 << "; ++" 307 << iteratorName 308 << ") {\n"; 309 310 out.indent(); 311 312 mElementType->emitResolveReferencesEmbedded( 313 out, 314 depth + 1, 315 nameDeref + "data()[" + iteratorName + "]", 316 sanitizedName + "_indexed", 317 false /* nameIsPointer */, 318 parcelObj, 319 parcelObjIsPointer, 320 isReader, 321 mode, 322 parentName, 323 offsetText + " + " + iteratorName + " * sizeof(" 324 + baseType 325 + ")"); 326 327 out.unindent(); 328 329 out << "}\n\n"; 330} 331 332 333bool ArrayType::needsEmbeddedReadWrite() const { 334 return mElementType->needsEmbeddedReadWrite(); 335} 336 337bool ArrayType::needsResolveReferences() const { 338 return mElementType->needsResolveReferences(); 339} 340 341bool ArrayType::resultNeedsDeref() const { 342 return true; 343} 344 345void ArrayType::emitJavaReaderWriter( 346 Formatter &out, 347 const std::string &parcelObj, 348 const std::string &argName, 349 bool isReader) const { 350 if (isReader) { 351 std::string extra; 352 out << "new " 353 << getJavaType(&extra, true /* forInitializer */) 354 << extra 355 << ";\n"; 356 } 357 358 out << "{\n"; 359 out.indent(); 360 361 out << "HwBlob _hidl_blob = "; 362 363 if (isReader) { 364 out << parcelObj 365 << ".readBuffer();\n"; 366 } else { 367 size_t align, size; 368 getAlignmentAndSize(&align, &size); 369 370 out << "new HwBlob(" 371 << size 372 << " /* size */);\n"; 373 } 374 375 emitJavaFieldReaderWriter( 376 out, 377 0 /* depth */, 378 parcelObj, 379 "_hidl_blob", 380 argName, 381 "0 /* offset */", 382 isReader); 383 384 if (!isReader) { 385 out << parcelObj << ".writeBuffer(_hidl_blob);\n"; 386 } 387 388 out.unindent(); 389 out << "}\n"; 390} 391 392void ArrayType::emitJavaFieldInitializer( 393 Formatter &out, const std::string &fieldName) const { 394 std::string extra; 395 std::string typeName = getJavaType(&extra, false /* forInitializer */); 396 397 std::string extraInit; 398 getJavaType(&extraInit, true /* forInitializer */); 399 400 out << "final " 401 << typeName 402 << extra 403 << " " 404 << fieldName 405 << " = new " 406 << typeName 407 << extraInit 408 << ";\n"; 409} 410 411void ArrayType::emitJavaFieldReaderWriter( 412 Formatter &out, 413 size_t depth, 414 const std::string &parcelName, 415 const std::string &blobName, 416 const std::string &fieldName, 417 const std::string &offset, 418 bool isReader) const { 419 out << "{\n"; 420 out.indent(); 421 422 std::string offsetName = "_hidl_array_offset_" + std::to_string(depth); 423 out << "long " << offsetName << " = " << offset << ";\n"; 424 425 std::string indexString; 426 for (size_t dim = 0; dim < mSizes.size(); ++dim) { 427 std::string iteratorName = 428 "_hidl_index_" + std::to_string(depth) + "_" + std::to_string(dim); 429 430 out << "for (int " 431 << iteratorName 432 << " = 0; " 433 << iteratorName 434 << " < " 435 << mSizes[dim]->javaValue() 436 << "; ++" 437 << iteratorName 438 << ") {\n"; 439 440 out.indent(); 441 442 indexString += "[" + iteratorName + "]"; 443 } 444 445 if (isReader && mElementType->isCompoundType()) { 446 std::string extra; 447 std::string typeName = 448 mElementType->getJavaType(&extra, false /* forInitializer */); 449 450 CHECK(extra.empty()); 451 452 out << fieldName 453 << indexString 454 << " = new " 455 << typeName 456 << "();\n"; 457 } 458 459 mElementType->emitJavaFieldReaderWriter( 460 out, 461 depth + 1, 462 parcelName, 463 blobName, 464 fieldName + indexString, 465 offsetName, 466 isReader); 467 468 size_t elementAlign, elementSize; 469 mElementType->getAlignmentAndSize(&elementAlign, &elementSize); 470 471 out << offsetName << " += " << std::to_string(elementSize) << ";\n"; 472 473 for (size_t dim = 0; dim < mSizes.size(); ++dim) { 474 out.unindent(); 475 out << "}\n"; 476 } 477 478 out.unindent(); 479 out << "}\n"; 480} 481 482status_t ArrayType::emitVtsTypeDeclarations(Formatter &out) const { 483 out << "type: " << getVtsType() << "\n"; 484 out << "vector_value: {\n"; 485 out.indent(); 486 out << "vector_size: " << mSizes[0]->value() << "\n"; 487 // Simple array case. 488 if (mSizes.size() == 1) { 489 status_t err = mElementType->emitVtsTypeDeclarations(out); 490 if (err != OK) { 491 return err; 492 } 493 } else { // Multi-dimension array case. 494 for (size_t index = 1; index < mSizes.size(); index++) { 495 out << "type: " << getVtsType() << "\n"; 496 out << "vector_value: {\n"; 497 out.indent(); 498 out << "vector_size: " << mSizes[index]->value() << "\n"; 499 if (index == mSizes.size() - 1) { 500 status_t err = mElementType->emitVtsTypeDeclarations(out); 501 if (err != OK) { 502 return err; 503 } 504 } 505 } 506 } 507 for (size_t index = 0; index < mSizes.size(); index++) { 508 out.unindent(); 509 out << "}\n"; 510 } 511 return OK; 512} 513 514bool ArrayType::isJavaCompatible() const { 515 return mElementType->isJavaCompatible(); 516} 517 518void ArrayType::getAlignmentAndSize(size_t *align, size_t *size) const { 519 mElementType->getAlignmentAndSize(align, size); 520 521 for (auto sizeInDimension : mSizes) { 522 (*size) *= sizeInDimension->castSizeT(); 523 } 524} 525 526size_t ArrayType::dimension() const { 527 size_t numArrayElements = 1; 528 for (auto size : mSizes) { 529 numArrayElements *= size->castSizeT(); 530 } 531 return numArrayElements; 532} 533 534} // namespace android 535 536