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