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