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